forked from tuneinsight/lattigo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sampler_sol_ternary.go
85 lines (67 loc) · 2.12 KB
/
sampler_sol_ternary.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package ring
import (
"github.com/jzhchu/lattigo/utils"
)
type TernarySolSampler struct {
baseSampler
matrixProbability [2][precision - 1]uint8
matrixValues [][3]uint64
sample func(lvl int, poly *Poly)
seed []byte
}
func NewTernarySolSampler(baseRing *Ring, seed []byte, montgomery bool) *TernarySolSampler {
ternarySolSampler := new(TernarySolSampler)
ternarySolSampler.baseRing = baseRing
ternarySolSampler.sample = ternarySolSampler.sampleProbability
ternarySolSampler.seed = seed
ternarySolSampler.prng = utils.NewSolPRNG(seed, 0)
ternarySolSampler.initializeMatrix(montgomery)
return ternarySolSampler
}
func (ts *TernarySolSampler) SetSalt(salt uint32) {
ts.prng = utils.NewSolPRNG(ts.seed, salt)
}
func (ts *TernarySolSampler) Read(pol *Poly) {
ts.sample(len(ts.baseRing.Modulus)-1, pol)
}
func (ts *TernarySolSampler) ReadLvl(lvl int, pol *Poly) {
ts.sample(lvl, pol)
}
func (ts *TernarySolSampler) ReadNew() (pol *Poly) {
pol = ts.baseRing.NewPoly()
ts.sample(len(ts.baseRing.Modulus)-1, pol)
return pol
}
func (ts *TernarySolSampler) ReadLvlNew(lvl int) (pol *Poly) {
pol = ts.baseRing.NewPolyLvl(lvl)
ts.sample(lvl, pol)
return pol
}
func (ts *TernarySolSampler) initializeMatrix(montgomery bool) {
ts.matrixValues = make([][3]uint64, len(ts.baseRing.Modulus))
for i, Qi := range ts.baseRing.Modulus {
ts.matrixValues[i][0] = 0
if montgomery {
ts.matrixValues[i][1] = MForm(1, Qi, ts.baseRing.BredParams[i])
ts.matrixValues[i][2] = MForm(Qi-1, Qi, ts.baseRing.BredParams[i])
} else {
ts.matrixValues[i][1] = 1
ts.matrixValues[i][2] = Qi - 1
}
}
}
func (ts *TernarySolSampler) sampleProbability(lvl int, pol *Poly) {
var coeff uint64
var sign uint64
var index uint64
randomBytesCoeffs := make([]byte, ts.baseRing.N>>2)
ts.prng.Read(randomBytesCoeffs)
for i := 0; i < ts.baseRing.N; i++ {
coeff = uint64(uint8(randomBytesCoeffs[i>>3])>>(i&7)) & 1
sign = uint64(uint8(randomBytesCoeffs[ts.baseRing.N>>3+i>>3])>>(i&7)) & 1
index = (coeff & (sign ^ 1)) | ((sign & coeff) << 1)
for j := 0; j < lvl+1; j++ {
pol.Coeffs[j][i] = ts.matrixValues[j][index]
}
}
}