mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
[ckks/advanced]: better StC & CtS
This commit is contained in:
committed by
Jean-Philippe Bossuat
parent
d6213c1771
commit
6cfd218439
@@ -142,32 +142,39 @@ func (eval *evaluator) CoeffsToSlotsNew(ctIn *ckks.Ciphertext, ctsMatrices Encod
|
||||
// If the packing is sparse (n < N/2), then returns ctReal = Ecd(vReal || vImag) and ctImag = nil.
|
||||
// If the packing is dense (n == N/2), then returns ctReal = Ecd(vReal) and ctImag = Ecd(vImag).
|
||||
func (eval *evaluator) CoeffsToSlots(ctIn *ckks.Ciphertext, ctsMatrices EncodingMatrix, ctReal, ctImag *ckks.Ciphertext) {
|
||||
zV := ctIn.CopyNew()
|
||||
eval.dft(ctIn, ctsMatrices.matrices, zV)
|
||||
|
||||
eval.Conjugate(zV, ctReal)
|
||||
if ctsMatrices.RepackImag2Real {
|
||||
|
||||
var tmp *ckks.Ciphertext
|
||||
if ctImag != nil {
|
||||
tmp = ctImag
|
||||
zV := ctIn.CopyNew()
|
||||
|
||||
eval.dft(ctIn, ctsMatrices.matrices, zV)
|
||||
|
||||
eval.Conjugate(zV, ctReal)
|
||||
|
||||
var tmp *ckks.Ciphertext
|
||||
if ctImag != nil {
|
||||
tmp = ctImag
|
||||
} else {
|
||||
tmp = ckks.NewCiphertextAtLevelFromPoly(ctReal.Level(), [2]*ring.Poly{eval.BuffCt().Value[0], eval.BuffCt().Value[1]})
|
||||
}
|
||||
|
||||
// Imag part
|
||||
eval.Sub(zV, ctReal, tmp)
|
||||
eval.DivByi(tmp, tmp)
|
||||
|
||||
// Real part
|
||||
eval.Add(ctReal, zV, ctReal)
|
||||
|
||||
// If repacking, then ct0 and ct1 right n/2 slots are zero.
|
||||
if eval.params.LogSlots() < eval.params.LogN()-1 {
|
||||
eval.Rotate(tmp, eval.params.Slots(), tmp)
|
||||
eval.Add(ctReal, tmp, ctReal)
|
||||
}
|
||||
|
||||
zV = nil
|
||||
} else {
|
||||
tmp = ckks.NewCiphertextAtLevelFromPoly(ctReal.Level(), [2]*ring.Poly{eval.BuffCt().Value[0], eval.BuffCt().Value[1]})
|
||||
eval.dft(ctIn, ctsMatrices.matrices, ctReal)
|
||||
}
|
||||
|
||||
// Imag part
|
||||
eval.Sub(zV, ctReal, tmp)
|
||||
eval.DivByi(tmp, tmp)
|
||||
|
||||
// Real part
|
||||
eval.Add(ctReal, zV, ctReal)
|
||||
|
||||
// If repacking, then ct0 and ct1 right n/2 slots are zero.
|
||||
if eval.params.LogSlots() < eval.params.LogN()-1 {
|
||||
eval.Rotate(tmp, eval.params.Slots(), tmp)
|
||||
eval.Add(ctReal, tmp, ctReal)
|
||||
}
|
||||
|
||||
zV = nil
|
||||
}
|
||||
|
||||
// SlotsToCoeffsNew applies the homomorphic decoding and returns the result on a new ciphertext.
|
||||
|
||||
@@ -25,6 +25,7 @@ type EncodingMatrix struct {
|
||||
// EncodingMatrixLiteral is a struct storing the parameters to generate the factorized DFT matrix.
|
||||
type EncodingMatrixLiteral struct {
|
||||
LinearTransformType LinearTransformType
|
||||
RepackImag2Real bool // Repack imag into the right n slots or reals.
|
||||
LogN int // log(RingDegree)
|
||||
LogSlots int // log(slots)
|
||||
Scaling float64 // constant by which the matrix is multiplied with
|
||||
@@ -64,24 +65,26 @@ func (mParams *EncodingMatrixLiteral) Levels() (levels []int) {
|
||||
}
|
||||
|
||||
// Rotations returns the list of rotations performed during the CoeffsToSlot operation.
|
||||
func (mParams *EncodingMatrixLiteral) Rotations(logN, logSlots int) (rotations []int) {
|
||||
func (mParams *EncodingMatrixLiteral) Rotations() (rotations []int) {
|
||||
rotations = []int{}
|
||||
|
||||
logSlots := mParams.LogSlots
|
||||
logN := mParams.LogN
|
||||
slots := 1 << logSlots
|
||||
dslots := slots
|
||||
if logSlots < logN-1 {
|
||||
if logSlots < logN-1 && mParams.RepackImag2Real {
|
||||
dslots <<= 1
|
||||
if mParams.LinearTransformType == CoeffsToSlots {
|
||||
rotations = append(rotations, slots)
|
||||
}
|
||||
}
|
||||
|
||||
indexCtS := computeBootstrappingDFTIndexMap(logN, logSlots, mParams.Depth(false), mParams.LinearTransformType, mParams.BitReversed)
|
||||
indexCtS := mParams.computeBootstrappingDFTIndexMap()
|
||||
|
||||
// Coeffs to Slots rotations
|
||||
for i, pVec := range indexCtS {
|
||||
N1 := ckks.FindBestBSGSSplit(pVec, dslots, mParams.BSGSRatio)
|
||||
rotations = addMatrixRotToList(pVec, rotations, N1, slots, mParams.LinearTransformType == SlotsToCoeffs && logSlots < logN-1 && i == 0)
|
||||
rotations = addMatrixRotToList(pVec, rotations, N1, slots, mParams.LinearTransformType == SlotsToCoeffs && logSlots < logN-1 && i == 0 && mParams.RepackImag2Real)
|
||||
}
|
||||
|
||||
return
|
||||
@@ -93,28 +96,16 @@ func (mParams *EncodingMatrixLiteral) Rotations(logN, logSlots int) (rotations [
|
||||
func NewHomomorphicEncodingMatrixFromLiteral(mParams EncodingMatrixLiteral, encoder ckks.Encoder) EncodingMatrix {
|
||||
|
||||
logSlots := mParams.LogSlots
|
||||
slots := 1 << logSlots
|
||||
depth := mParams.Depth(false)
|
||||
logdSlots := mParams.LogSlots + 1
|
||||
if logdSlots == mParams.LogN {
|
||||
logdSlots--
|
||||
}
|
||||
|
||||
roots := computeRoots(slots << 1)
|
||||
pow5 := make([]int, (slots<<1)+1)
|
||||
pow5[0] = 1
|
||||
for i := 1; i < (slots<<1)+1; i++ {
|
||||
pow5[i] = pow5[i-1] * 5
|
||||
pow5[i] &= (slots << 2) - 1
|
||||
logdSlots := logSlots
|
||||
if logdSlots < mParams.LogN-1 && mParams.RepackImag2Real {
|
||||
logdSlots++
|
||||
}
|
||||
|
||||
ctsLevels := mParams.Levels()
|
||||
|
||||
scaling := complex(math.Pow(mParams.Scaling, 1.0/float64(mParams.Depth(false))), 0)
|
||||
|
||||
// CoeffsToSlots vectors
|
||||
matrices := make([]ckks.LinearTransform, len(ctsLevels))
|
||||
pVecDFT := computeDFTMatrices(logSlots, logdSlots, depth, roots, pow5, scaling, mParams.LinearTransformType, mParams.BitReversed)
|
||||
pVecDFT := mParams.computeDFTMatrices()
|
||||
cnt := 0
|
||||
trueDepth := mParams.Depth(true)
|
||||
for i := range mParams.ScalingFactor {
|
||||
@@ -289,7 +280,14 @@ func addMatrixRotToList(pVec map[int]bool, rotations []int, N1, slots int, repac
|
||||
return rotations
|
||||
}
|
||||
|
||||
func computeBootstrappingDFTIndexMap(logN, logSlots, maxDepth int, ltType LinearTransformType, bitreversed bool) (rotationMap []map[int]bool) {
|
||||
func (mParams *EncodingMatrixLiteral) computeBootstrappingDFTIndexMap() (rotationMap []map[int]bool) {
|
||||
|
||||
logN := mParams.LogN
|
||||
logSlots := mParams.LogSlots
|
||||
ltType := mParams.LinearTransformType
|
||||
repacki2r := mParams.RepackImag2Real
|
||||
bitreversed := mParams.BitReversed
|
||||
maxDepth := mParams.Depth(false)
|
||||
|
||||
var level, depth, nextLevel int
|
||||
|
||||
@@ -319,7 +317,7 @@ func computeBootstrappingDFTIndexMap(logN, logSlots, maxDepth int, ltType Linear
|
||||
level = logSlots
|
||||
for i := 0; i < maxDepth; i++ {
|
||||
|
||||
if logSlots < logN-1 && ltType == SlotsToCoeffs && i == 0 {
|
||||
if logSlots < logN-1 && ltType == SlotsToCoeffs && i == 0 && repacki2r {
|
||||
|
||||
// Special initial matrix for the repacking before SlotsToCoeffs
|
||||
rotationMap[i] = genWfftRepackIndexMap(logSlots, level)
|
||||
@@ -335,6 +333,7 @@ func computeBootstrappingDFTIndexMap(logN, logSlots, maxDepth int, ltType Linear
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// First layer of the i-th level of the DFT
|
||||
rotationMap[i] = genWfftIndexMap(logSlots, level, ltType, bitreversed)
|
||||
|
||||
@@ -397,14 +396,32 @@ func nextLevelfftIndexMap(vec map[int]bool, logL, N, nextLevel int, ltType Linea
|
||||
return
|
||||
}
|
||||
|
||||
func computeDFTMatrices(logSlots, logdSlots, maxDepth int, roots []complex128, pow5 []int, diffscale complex128, ltType LinearTransformType, bitreversed bool) (plainVector []map[int][]complex128) {
|
||||
func (mParams *EncodingMatrixLiteral) computeDFTMatrices() (plainVector []map[int][]complex128) {
|
||||
|
||||
logSlots := mParams.LogSlots
|
||||
slots := 1 << logSlots
|
||||
maxDepth := mParams.Depth(false)
|
||||
ltType := mParams.LinearTransformType
|
||||
bitreversed := mParams.BitReversed
|
||||
|
||||
logdSlots := logSlots
|
||||
if logdSlots < mParams.LogN-1 && mParams.RepackImag2Real {
|
||||
logdSlots++
|
||||
}
|
||||
|
||||
roots := computeRoots(slots << 1)
|
||||
pow5 := make([]int, (slots<<1)+1)
|
||||
pow5[0] = 1
|
||||
for i := 1; i < (slots<<1)+1; i++ {
|
||||
pow5[i] = pow5[i-1] * 5
|
||||
pow5[i] &= (slots << 2) - 1
|
||||
}
|
||||
|
||||
var fftLevel, depth, nextfftLevel int
|
||||
|
||||
fftLevel = logSlots
|
||||
|
||||
var a, b, c [][]complex128
|
||||
|
||||
if ltType == CoeffsToSlots {
|
||||
a, b, c = fftInvPlainVec(logSlots, 1<<logdSlots, roots, pow5)
|
||||
} else {
|
||||
@@ -435,7 +452,7 @@ func computeDFTMatrices(logSlots, logdSlots, maxDepth int, roots []complex128, p
|
||||
fftLevel = logSlots
|
||||
for i := 0; i < maxDepth; i++ {
|
||||
|
||||
if logSlots != logdSlots && ltType == SlotsToCoeffs && i == 0 {
|
||||
if logSlots != logdSlots && ltType == SlotsToCoeffs && i == 0 && mParams.RepackImag2Real {
|
||||
|
||||
// Special initial matrix for the repacking before SlotsToCoeffs
|
||||
plainVector[i] = genRepackMatrix(logSlots, bitreversed)
|
||||
@@ -466,7 +483,7 @@ func computeDFTMatrices(logSlots, logdSlots, maxDepth int, roots []complex128, p
|
||||
}
|
||||
|
||||
// Repacking after the CoeffsToSlots (we multiply the last DFT matrix with the vector [1, 1, ..., 1, 1, 0, 0, ..., 0, 0]).
|
||||
if logSlots != logdSlots && ltType == CoeffsToSlots {
|
||||
if logSlots != logdSlots && ltType == CoeffsToSlots && mParams.RepackImag2Real {
|
||||
for j := range plainVector[maxDepth-1] {
|
||||
for x := 0; x < 1<<logSlots; x++ {
|
||||
plainVector[maxDepth-1][j][x+(1<<logSlots)] = complex(0, 0)
|
||||
@@ -475,10 +492,11 @@ func computeDFTMatrices(logSlots, logdSlots, maxDepth int, roots []complex128, p
|
||||
}
|
||||
|
||||
// Rescaling of the DFT matrix of the SlotsToCoeffs/CoeffsToSlots
|
||||
scaling := complex(math.Pow(mParams.Scaling, 1.0/float64(mParams.Depth(false))), 0)
|
||||
for j := range plainVector {
|
||||
for x := range plainVector[j] {
|
||||
for i := range plainVector[j][x] {
|
||||
plainVector[j][x][i] *= diffscale
|
||||
plainVector[j][x][i] *= scaling
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,7 @@ func testCoeffsToSlots(params ckks.Parameters, t *testing.T) {
|
||||
LogSlots: params.LogSlots(),
|
||||
Scaling: 1.0 / float64(2*params.Slots()),
|
||||
LinearTransformType: CoeffsToSlots,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: params.MaxLevel(),
|
||||
BSGSRatio: 16.0,
|
||||
BitReversed: false,
|
||||
@@ -149,7 +150,7 @@ func testCoeffsToSlots(params ckks.Parameters, t *testing.T) {
|
||||
CoeffsToSlotMatrices := NewHomomorphicEncodingMatrixFromLiteral(CoeffsToSlotsParametersLiteral, encoder)
|
||||
|
||||
// Gets the rotations indexes for CoeffsToSlots
|
||||
rotations := CoeffsToSlotsParametersLiteral.Rotations(params.LogN(), params.LogSlots())
|
||||
rotations := CoeffsToSlotsParametersLiteral.Rotations()
|
||||
|
||||
// Generates the rotation keys
|
||||
rotKey := kgen.GenRotationKeysForRotations(rotations, true, sk)
|
||||
@@ -245,6 +246,7 @@ func testSlotsToCoeffs(params ckks.Parameters, t *testing.T) {
|
||||
LogSlots: params.LogSlots(),
|
||||
Scaling: 1.0,
|
||||
LinearTransformType: SlotsToCoeffs,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: params.MaxLevel(),
|
||||
BSGSRatio: 16.0,
|
||||
BitReversed: false,
|
||||
@@ -265,7 +267,7 @@ func testSlotsToCoeffs(params ckks.Parameters, t *testing.T) {
|
||||
SlotsToCoeffsMatrix := NewHomomorphicEncodingMatrixFromLiteral(SlotsToCoeffsParametersLiteral, encoder)
|
||||
|
||||
// Gets the rotations indexes for SlotsToCoeffs
|
||||
rotations := SlotsToCoeffsParametersLiteral.Rotations(params.LogN(), params.LogSlots())
|
||||
rotations := SlotsToCoeffsParametersLiteral.Rotations()
|
||||
|
||||
// Generates the rotation keys
|
||||
rotKey := kgen.GenRotationKeysForRotations(rotations, true, sk)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
// MarshalBinary encode the target EncodingMatrixParameters on a slice of bytes.
|
||||
func (mParams *EncodingMatrixLiteral) MarshalBinary() (data []byte, err error) {
|
||||
data = make([]byte, 8)
|
||||
data = make([]byte, 9)
|
||||
data[0] = uint8(mParams.LinearTransformType)
|
||||
data[1] = uint8(mParams.LevelStart)
|
||||
if mParams.BitReversed {
|
||||
@@ -17,6 +17,10 @@ func (mParams *EncodingMatrixLiteral) MarshalBinary() (data []byte, err error) {
|
||||
binary.BigEndian.PutUint32(data[3:7], math.Float32bits(float32(mParams.BSGSRatio)))
|
||||
data[7] = uint8(len(mParams.ScalingFactor))
|
||||
|
||||
if mParams.RepackImag2Real {
|
||||
data[8] = uint8(1)
|
||||
}
|
||||
|
||||
for _, d := range mParams.ScalingFactor {
|
||||
data = append(data, uint8(len(d)))
|
||||
for j := range d {
|
||||
@@ -37,9 +41,10 @@ func (mParams *EncodingMatrixLiteral) UnmarshalBinary(data []byte) error {
|
||||
mParams.BitReversed = true
|
||||
}
|
||||
mParams.BSGSRatio = float64(math.Float32frombits(binary.BigEndian.Uint32(data[3:7])))
|
||||
|
||||
mParams.ScalingFactor = make([][]float64, data[7])
|
||||
pt := 8
|
||||
mParams.RepackImag2Real = data[8] == 1
|
||||
|
||||
pt := 9
|
||||
for i := range mParams.ScalingFactor {
|
||||
tmp := make([]float64, data[pt])
|
||||
pt++
|
||||
|
||||
@@ -25,7 +25,12 @@ func BenchmarkBootstrapp(b *testing.B) {
|
||||
kgen := ckks.NewKeyGenerator(params)
|
||||
sk := kgen.GenSecretKey()
|
||||
|
||||
<<<<<<< btp_eprint
|
||||
evk := GenEvaluationKeys(btpParams, params, sk)
|
||||
=======
|
||||
rotations := btpParams.RotationsForBootstrapping(params)
|
||||
rotkeys := kgen.GenRotationKeysForRotations(rotations, true, sk)
|
||||
>>>>>>> [ckks/advanced]: better StC & CtS
|
||||
|
||||
if btp, err = NewBootstrapper(params, btpParams, evk); err != nil {
|
||||
panic(err)
|
||||
|
||||
@@ -84,26 +84,433 @@ func (p *Parameters) UnmarshalBinary(data []byte) (err error) {
|
||||
}
|
||||
|
||||
// RotationsForBootstrapping returns the list of rotations performed during the Bootstrapping operation.
|
||||
func (p *Parameters) RotationsForBootstrapping(LogN, LogSlots int) (rotations []int) {
|
||||
func (p *Parameters) RotationsForBootstrapping(params ckks.Parameters) (rotations []int) {
|
||||
|
||||
logN := params.LogN()
|
||||
logSlots := params.LogSlots()
|
||||
|
||||
// List of the rotation key values to needed for the bootstrapp
|
||||
rotations = []int{}
|
||||
|
||||
slots := 1 << LogSlots
|
||||
dslots := slots
|
||||
if LogSlots < LogN-1 {
|
||||
dslots <<= 1
|
||||
}
|
||||
|
||||
//SubSum rotation needed X -> Y^slots rotations
|
||||
for i := LogSlots; i < LogN-1; i++ {
|
||||
for i := logSlots; i < logN-1; i++ {
|
||||
if !utils.IsInSliceInt(1<<i, rotations) {
|
||||
rotations = append(rotations, 1<<i)
|
||||
}
|
||||
}
|
||||
|
||||
rotations = append(rotations, p.CoeffsToSlotsParameters.Rotations(LogN, LogSlots)...)
|
||||
rotations = append(rotations, p.SlotsToCoeffsParameters.Rotations(LogN, LogSlots)...)
|
||||
p.CoeffsToSlotsParameters.LogN = logN
|
||||
p.SlotsToCoeffsParameters.LogN = logN
|
||||
|
||||
p.CoeffsToSlotsParameters.LogSlots = logSlots
|
||||
p.SlotsToCoeffsParameters.LogSlots = logSlots
|
||||
|
||||
rotations = append(rotations, p.CoeffsToSlotsParameters.Rotations()...)
|
||||
rotations = append(rotations, p.SlotsToCoeffsParameters.Rotations()...)
|
||||
|
||||
return
|
||||
}
|
||||
<<<<<<< btp_eprint
|
||||
=======
|
||||
<<<<<<< btp_eprint
|
||||
=======
|
||||
|
||||
// DefaultCKKSParameters are default parameters for the bootstrapping.
|
||||
// To be used in conjonction with DefaultParameters.
|
||||
var DefaultCKKSParameters = []ckks.ParametersLiteral{
|
||||
{
|
||||
LogN: 16,
|
||||
LogSlots: 15,
|
||||
DefaultScale: 1 << 40,
|
||||
H: 192,
|
||||
Sigma: rlwe.DefaultSigma,
|
||||
Q: []uint64{
|
||||
0x10000000006e0001, // 60 Q0
|
||||
0x10000140001, // 40
|
||||
0xffffe80001, // 40
|
||||
0xffffc40001, // 40
|
||||
0x100003e0001, // 40
|
||||
0xffffb20001, // 40
|
||||
0x10000500001, // 40
|
||||
0xffff940001, // 40
|
||||
0xffff8a0001, // 40
|
||||
0xffff820001, // 40
|
||||
0x7fffe60001, // 39 StC
|
||||
0x7fffe40001, // 39 StC
|
||||
0x7fffe00001, // 39 StC
|
||||
0xfffffffff840001, // 60 Sine (double angle)
|
||||
0x1000000000860001, // 60 Sine (double angle)
|
||||
0xfffffffff6a0001, // 60 Sine
|
||||
0x1000000000980001, // 60 Sine
|
||||
0xfffffffff5a0001, // 60 Sine
|
||||
0x1000000000b00001, // 60 Sine
|
||||
0x1000000000ce0001, // 60 Sine
|
||||
0xfffffffff2a0001, // 60 Sine
|
||||
0x100000000060001, // 58 CtS
|
||||
0xfffffffff00001, // 58 CtS
|
||||
0xffffffffd80001, // 58 CtS
|
||||
0x1000000002a0001, // 58 CtS
|
||||
},
|
||||
P: []uint64{
|
||||
0x1fffffffffe00001, // Pi 61
|
||||
0x1fffffffffc80001, // Pi 61
|
||||
0x1fffffffffb40001, // Pi 61
|
||||
0x1fffffffff500001, // Pi 61
|
||||
0x1fffffffff420001, // Pi 61
|
||||
},
|
||||
},
|
||||
{
|
||||
LogN: 16,
|
||||
LogSlots: 15,
|
||||
DefaultScale: 1 << 45,
|
||||
H: 192,
|
||||
Sigma: rlwe.DefaultSigma,
|
||||
Q: []uint64{
|
||||
0x10000000006e0001, // 60 Q0
|
||||
0x2000000a0001, // 45
|
||||
0x2000000e0001, // 45
|
||||
0x1fffffc20001, // 45
|
||||
0x200000440001, // 45
|
||||
0x200000500001, // 45
|
||||
0x3ffffe80001, //42 StC
|
||||
0x3ffffd20001, //42 StC
|
||||
0x3ffffca0001, //42 StC
|
||||
0xffffffffffc0001, // ArcSine
|
||||
0xfffffffff240001, // ArcSine
|
||||
0x1000000000f00001, // ArcSine
|
||||
0xfffffffff840001, // Double angle
|
||||
0x1000000000860001, // Double angle
|
||||
0xfffffffff6a0001, // Sine
|
||||
0x1000000000980001, // Sine
|
||||
0xfffffffff5a0001, // Sine
|
||||
0x1000000000b00001, // Sine
|
||||
0x1000000000ce0001, // Sine
|
||||
0xfffffffff2a0001, // Sine
|
||||
0x400000000360001, // 58 CtS
|
||||
0x3ffffffffbe0001, // 58 CtS
|
||||
0x400000000660001, // 58 CtS
|
||||
0x4000000008a0001, // 58 CtS
|
||||
},
|
||||
P: []uint64{
|
||||
0x1fffffffffe00001, // Pi 61
|
||||
0x1fffffffffc80001, // Pi 61
|
||||
0x1fffffffffb40001, // Pi 61
|
||||
0x1fffffffff500001, // Pi 61
|
||||
},
|
||||
},
|
||||
{
|
||||
LogN: 16,
|
||||
LogSlots: 15,
|
||||
DefaultScale: 1 << 30,
|
||||
H: 192,
|
||||
Sigma: rlwe.DefaultSigma,
|
||||
Q: []uint64{
|
||||
0x80000000080001, // 55 Q0
|
||||
0xffffffffffc0001, // 60
|
||||
0x10000000006e0001, // 60
|
||||
0xfffffffff840001, // 60
|
||||
0x1000000000860001, // 60
|
||||
0xfffffffff6a0001, // 60
|
||||
0x1000000000980001, // 60
|
||||
0xfffffffff5a0001, // 60
|
||||
0x1000000000b00001, // 60 StC (30)
|
||||
0x1000000000ce0001, // 60 StC (30+30)
|
||||
0x80000000440001, // 55 Sine (double angle)
|
||||
0x7fffffffba0001, // 55 Sine (double angle)
|
||||
0x80000000500001, // 55 Sine
|
||||
0x7fffffffaa0001, // 55 Sine
|
||||
0x800000005e0001, // 55 Sine
|
||||
0x7fffffff7e0001, // 55 Sine
|
||||
0x7fffffff380001, // 55 Sine
|
||||
0x80000000ca0001, // 55 Sine
|
||||
0x200000000e0001, // 53 CtS
|
||||
0x20000000140001, // 53 CtS
|
||||
0x20000000280001, // 53 CtS
|
||||
0x1fffffffd80001, // 53 CtS
|
||||
},
|
||||
P: []uint64{
|
||||
0x1fffffffffe00001, // Pi 61
|
||||
0x1fffffffffc80001, // Pi 61
|
||||
0x1fffffffffb40001, // Pi 61
|
||||
0x1fffffffff500001, // Pi 61
|
||||
0x1fffffffff420001, // Pi 61
|
||||
},
|
||||
},
|
||||
{
|
||||
LogN: 16,
|
||||
LogSlots: 15,
|
||||
DefaultScale: 1 << 40,
|
||||
H: 32768,
|
||||
Sigma: rlwe.DefaultSigma,
|
||||
Q: []uint64{
|
||||
0x4000000120001, // 60 Q0
|
||||
0x10000140001,
|
||||
0xffffe80001,
|
||||
0xffffc40001,
|
||||
0x100003e0001,
|
||||
0xffffb20001,
|
||||
0x10000500001,
|
||||
0xffff940001,
|
||||
0xffff8a0001,
|
||||
0xffff820001,
|
||||
0x100000000060001, // 56 StC (28 + 28)
|
||||
0xffa0001, // 28 StC
|
||||
0xffffffffffc0001, // 60 Sine (double angle)
|
||||
0x10000000006e0001, // 60 Sine (double angle)
|
||||
0xfffffffff840001, // 60 Sine (double angle)
|
||||
0x1000000000860001, // 60 Sine (double angle)
|
||||
0xfffffffff6a0001, // 60 Sine
|
||||
0x1000000000980001, // 60 Sine
|
||||
0xfffffffff5a0001, // 60 Sine
|
||||
0x1000000000b00001, // 60 Sine
|
||||
0x1000000000ce0001, // 60 Sine
|
||||
0xfffffffff2a0001, // 60 Sine
|
||||
0xfffffffff240001, // 60 Sine
|
||||
0x1000000000f00001, // 60 Sine
|
||||
0x200000000e0001, // 53 CtS
|
||||
0x20000000140001, // 53 CtS
|
||||
0x20000000280001, // 53 CtS
|
||||
0x1fffffffd80001, // 53 CtS
|
||||
},
|
||||
P: []uint64{
|
||||
0x1fffffffffe00001, // Pi 61
|
||||
0x1fffffffffc80001, // Pi 61
|
||||
0x1fffffffffb40001, // Pi 61
|
||||
0x1fffffffff500001, // Pi 61
|
||||
0x1fffffffff420001, // Pi 61
|
||||
0x1fffffffff380001, // Pi 61
|
||||
},
|
||||
},
|
||||
{
|
||||
LogN: 15,
|
||||
LogSlots: 14,
|
||||
DefaultScale: 1 << 25,
|
||||
H: 192,
|
||||
Sigma: rlwe.DefaultSigma,
|
||||
Q: []uint64{
|
||||
0x1fff90001, // 32 Q0
|
||||
0x4000000420001, // 50
|
||||
0x1fc0001, // 25
|
||||
0xffffffffffc0001, // 60 StC (30+30)
|
||||
0x4000000120001, // 50 Sine
|
||||
0x40000001b0001, // 50 Sine
|
||||
0x3ffffffdf0001, // 50 Sine
|
||||
0x4000000270001, // 50 Sine
|
||||
0x3ffffffd20001, // 50 Sine
|
||||
0x3ffffffcd0001, // 50 Sine
|
||||
0x4000000350001, // 50 Sine
|
||||
0x3ffffffc70001, // 50 Sine
|
||||
0x1fffffff50001, // 49 CtS
|
||||
0x1ffffffea0001, // 49 CtS
|
||||
},
|
||||
P: []uint64{
|
||||
0x7fffffffe0001, // 51
|
||||
0x8000000110001, // 51
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// DefaultParameters are default bootstrapping params for the bootstrapping.
|
||||
var DefaultParameters = []Parameters{
|
||||
|
||||
// SET I
|
||||
// 1546
|
||||
{
|
||||
SlotsToCoeffsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.SlotsToCoeffs,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 12,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{0x7fffe60001},
|
||||
{0x7fffe40001},
|
||||
{0x7fffe00001},
|
||||
},
|
||||
},
|
||||
EvalModParameters: advanced.EvalModLiteral{
|
||||
Q: 0x10000000006e0001,
|
||||
LevelStart: 20,
|
||||
SineType: advanced.Cos1,
|
||||
MessageRatio: 256.0,
|
||||
K: 25,
|
||||
SineDeg: 63,
|
||||
DoubleAngle: 2,
|
||||
ArcSineDeg: 0,
|
||||
ScalingFactor: 1 << 60,
|
||||
},
|
||||
CoeffsToSlotsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.CoeffsToSlots,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 24,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{0x100000000060001},
|
||||
{0xfffffffff00001},
|
||||
{0xffffffffd80001},
|
||||
{0x1000000002a0001},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// SET II
|
||||
// 1547
|
||||
{
|
||||
SlotsToCoeffsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.SlotsToCoeffs,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 8,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{0x3ffffe80001},
|
||||
{0x3ffffd20001},
|
||||
{0x3ffffca0001},
|
||||
},
|
||||
},
|
||||
EvalModParameters: advanced.EvalModLiteral{
|
||||
Q: 0x10000000006e0001,
|
||||
LevelStart: 19,
|
||||
SineType: advanced.Cos1,
|
||||
MessageRatio: 4.0,
|
||||
K: 25,
|
||||
SineDeg: 63,
|
||||
DoubleAngle: 2,
|
||||
ArcSineDeg: 7,
|
||||
ScalingFactor: 1 << 60,
|
||||
},
|
||||
CoeffsToSlotsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.CoeffsToSlots,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 23,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{0x400000000360001},
|
||||
{0x3ffffffffbe0001},
|
||||
{0x400000000660001},
|
||||
{0x4000000008a0001},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// SET III
|
||||
// 1553
|
||||
{
|
||||
SlotsToCoeffsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.SlotsToCoeffs,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 9,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{1073741824.0},
|
||||
{1073741824.0062866, 1073741824.0062866},
|
||||
},
|
||||
},
|
||||
EvalModParameters: advanced.EvalModLiteral{
|
||||
Q: 0x80000000080001,
|
||||
LevelStart: 17,
|
||||
SineType: advanced.Cos1,
|
||||
MessageRatio: 256.0,
|
||||
K: 25,
|
||||
SineDeg: 63,
|
||||
DoubleAngle: 2,
|
||||
ArcSineDeg: 0,
|
||||
ScalingFactor: 1 << 55,
|
||||
},
|
||||
CoeffsToSlotsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.CoeffsToSlots,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 21,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{0x200000000e0001},
|
||||
{0x20000000140001},
|
||||
{0x20000000280001},
|
||||
{0x1fffffffd80001},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Set IV
|
||||
// 1792
|
||||
{
|
||||
SlotsToCoeffsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.SlotsToCoeffs,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 11,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{268435456.0007324, 268435456.0007324},
|
||||
{0xffa0001},
|
||||
},
|
||||
},
|
||||
EvalModParameters: advanced.EvalModLiteral{
|
||||
Q: 0x4000000120001,
|
||||
LevelStart: 23,
|
||||
SineType: advanced.Cos2,
|
||||
MessageRatio: 256.0,
|
||||
K: 325,
|
||||
SineDeg: 255,
|
||||
DoubleAngle: 4,
|
||||
ArcSineDeg: 0,
|
||||
ScalingFactor: 1 << 60,
|
||||
},
|
||||
CoeffsToSlotsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.CoeffsToSlots,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 27,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{0x200000000e0001},
|
||||
{0x20000000140001},
|
||||
{0x20000000280001},
|
||||
{0x1fffffffd80001},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
// Set V
|
||||
// 768
|
||||
{
|
||||
SlotsToCoeffsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.SlotsToCoeffs,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 3,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{1073741823.9998779, 1073741823.9998779},
|
||||
},
|
||||
},
|
||||
EvalModParameters: advanced.EvalModLiteral{
|
||||
Q: 0x1fff90001,
|
||||
LevelStart: 11,
|
||||
SineType: advanced.Cos1,
|
||||
MessageRatio: 256.0,
|
||||
K: 25,
|
||||
SineDeg: 63,
|
||||
DoubleAngle: 2,
|
||||
ArcSineDeg: 0,
|
||||
ScalingFactor: 1 << 50,
|
||||
},
|
||||
CoeffsToSlotsParameters: advanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: advanced.CoeffsToSlots,
|
||||
RepackImag2Real: true,
|
||||
LevelStart: 13,
|
||||
BSGSRatio: 2.0,
|
||||
BitReversed: false,
|
||||
ScalingFactor: [][]float64{
|
||||
{0x1fffffff50001},
|
||||
{0x1ffffffea0001},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
>>>>>>> [ckks/advanced]: better StC & CtS
|
||||
>>>>>>> [ckks/advanced]: better StC & CtS
|
||||
|
||||
@@ -109,7 +109,12 @@ func testbootstrap(params ckks.Parameters, original bool, btpParams Parameters,
|
||||
encryptor := ckks.NewEncryptor(params, sk)
|
||||
decryptor := ckks.NewDecryptor(params, sk)
|
||||
|
||||
<<<<<<< btp_eprint
|
||||
evk := GenEvaluationKeys(btpParams, params, sk)
|
||||
=======
|
||||
rotations := btpParams.RotationsForBootstrapping(params)
|
||||
rotkeys := kgen.GenRotationKeysForRotations(rotations, true, sk)
|
||||
>>>>>>> [ckks/advanced]: better StC & CtS
|
||||
|
||||
btp, err := NewBootstrapper(params, btpParams, evk)
|
||||
if err != nil {
|
||||
|
||||
@@ -147,8 +147,8 @@ func (bb *bootstrapperBase) CheckKeys(btpKeys EvaluationKeys) (err error) {
|
||||
|
||||
rotKeyIndex := []int{}
|
||||
rotKeyIndex = append(rotKeyIndex, bb.params.RotationsForTrace(bb.params.LogSlots(), bb.params.MaxLogSlots())...)
|
||||
rotKeyIndex = append(rotKeyIndex, bb.CoeffsToSlotsParameters.Rotations(bb.params.LogN(), bb.params.LogSlots())...)
|
||||
rotKeyIndex = append(rotKeyIndex, bb.SlotsToCoeffsParameters.Rotations(bb.params.LogN(), bb.params.LogSlots())...)
|
||||
rotKeyIndex = append(rotKeyIndex, bb.CoeffsToSlotsParameters.Rotations()...)
|
||||
rotKeyIndex = append(rotKeyIndex, bb.SlotsToCoeffsParameters.Rotations()...)
|
||||
|
||||
rotMissing := []int{}
|
||||
for _, i := range rotKeyIndex {
|
||||
|
||||
@@ -58,6 +58,7 @@ func SpecialFFTUL8Vec(values []complex128, N, M int, rotGroup []int, roots []com
|
||||
logM := int(bits.Len64(uint64(M))) - 1
|
||||
|
||||
for loglen := 1; loglen <= logN; loglen++ {
|
||||
|
||||
len := 1 << loglen
|
||||
lenh := len >> 1
|
||||
lenq := len << 2
|
||||
@@ -219,6 +220,7 @@ func SpecialiFFTUL8Vec(values []complex128, N, M int, rotGroup []int, roots []co
|
||||
logM := int(bits.Len64(uint64(M))) - 1
|
||||
|
||||
for loglen := logN; loglen > 0; loglen-- {
|
||||
|
||||
len := 1 << loglen
|
||||
lenh := len >> 1
|
||||
lenq := len << 2
|
||||
|
||||
@@ -388,7 +388,7 @@ func (ecd *encoderComplex128) Embed(values interface{}, logSlots int, scale floa
|
||||
ecd.values[i] = 0
|
||||
}
|
||||
|
||||
if logSlots < 3 {
|
||||
if logSlots < 4 {
|
||||
SpecialiFFTVec(ecd.values, slots, ecd.m, ecd.rotGroup, ecd.roots)
|
||||
} else {
|
||||
SpecialiFFTUL8Vec(ecd.values, slots, ecd.m, ecd.rotGroup, ecd.roots)
|
||||
|
||||
@@ -271,6 +271,28 @@ func SliceBitReverseInPlaceComplex128(slice []complex128, N int) {
|
||||
}
|
||||
}
|
||||
|
||||
// SliceBitReverseInPlaceFloat64 applies an in-place bit-reverse permuation on the input slice.
|
||||
func SliceBitReverseInPlaceFloat64(slice []float64, N int) {
|
||||
|
||||
var bit, j int
|
||||
|
||||
for i := 1; i < N; i++ {
|
||||
|
||||
bit = N >> 1
|
||||
|
||||
for j >= bit {
|
||||
j -= bit
|
||||
bit >>= 1
|
||||
}
|
||||
|
||||
j += bit
|
||||
|
||||
if i < j {
|
||||
slice[i], slice[j] = slice[j], slice[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SliceBitReverseInPlaceRingComplex applies an in-place bit-reverse permuation on the input slice.
|
||||
func SliceBitReverseInPlaceRingComplex(slice []*ring.Complex, N int) {
|
||||
|
||||
|
||||
145
examples/main.go
Normal file
145
examples/main.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/tuneinsight/lattigo/v3/ckks"
|
||||
"github.com/tuneinsight/lattigo/v3/ring"
|
||||
"github.com/tuneinsight/lattigo/v3/rlwe"
|
||||
ckksAdvanced "github.com/tuneinsight/lattigo/v3/ckks/advanced"
|
||||
)
|
||||
|
||||
func main() {
|
||||
LUT()
|
||||
}
|
||||
|
||||
// Q modulus Q
|
||||
var Q = []uint64{0x80000000080001, 0x2000000e0001, 0x1fffffc20001}
|
||||
|
||||
// P modulus P
|
||||
var P = []uint64{0x4000000008a0001}
|
||||
|
||||
var ckksParamsN12 = ckks.ParametersLiteral{
|
||||
LogN: 5,
|
||||
LogSlots: 4,
|
||||
Q: Q,
|
||||
P: P,
|
||||
DefaultScale: 1 << 40,
|
||||
Sigma: rlwe.DefaultSigma,
|
||||
RingType: ring.Standard,
|
||||
}
|
||||
|
||||
// LUT example
|
||||
func LUT() {
|
||||
var err error
|
||||
var paramsN12 ckks.Parameters
|
||||
|
||||
if paramsN12, err = ckks.NewParametersFromLiteral(ckksParamsN12); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
kgenN12 := ckks.NewKeyGenerator(paramsN12)
|
||||
skN12 := kgenN12.GenSecretKey()
|
||||
encoderN12 := ckks.NewEncoder(paramsN12)
|
||||
encryptorN12 := ckks.NewEncryptor(paramsN12, skN12)
|
||||
decryptorN12 := ckks.NewDecryptor(paramsN12, skN12)
|
||||
|
||||
fmt.Printf("Gen SlotsToCoeffs Matrices... ")
|
||||
|
||||
// SlotsToCoeffsParameters homomorphic encoding parameters
|
||||
var SlotsToCoeffsParameters = ckksAdvanced.EncodingMatrixLiteral{
|
||||
LogN: paramsN12.LogN(),
|
||||
LogSlots: paramsN12.LogSlots(),
|
||||
Scaling: 1.0,
|
||||
LinearTransformType: ckksAdvanced.SlotsToCoeffs,
|
||||
RepackImag2Real: false,
|
||||
LevelStart: 2, // starting level
|
||||
BSGSRatio: 4.0, // ratio between n1/n2 for n1*n2 = slots
|
||||
BitReversed: false, // bit-reversed input
|
||||
ScalingFactor: [][]float64{ // Decomposition level of the encoding matrix
|
||||
{0x2000000e0001}, // Scale of the second matriox
|
||||
{0x1fffffc20001}, // Scale of the first matrix
|
||||
},
|
||||
}
|
||||
|
||||
// CoeffsToSlotsParameters homomorphic decoding parameters
|
||||
var CoeffsToSlotsParameters = ckksAdvanced.EncodingMatrixLiteral{
|
||||
LinearTransformType: ckksAdvanced.CoeffsToSlots,
|
||||
RepackImag2Real: false,
|
||||
LogN: paramsN12.LogN(),
|
||||
LogSlots: paramsN12.LogSlots(),
|
||||
Scaling: 1/16.0,
|
||||
LevelStart: 2, // starting level
|
||||
BSGSRatio: 4.0, // ratio between n1/n2 for n1*n2 = slots
|
||||
BitReversed: false, // bit-reversed input
|
||||
ScalingFactor: [][]float64{ // Decomposition level of the encoding matrix
|
||||
{0x2000000e0001}, // Scale of the second matriox
|
||||
{0x1fffffc20001}, // Scale of the first matrix
|
||||
},
|
||||
}
|
||||
|
||||
SlotsToCoeffsMatrix := ckksAdvanced.NewHomomorphicEncodingMatrixFromLiteral(SlotsToCoeffsParameters, encoderN12)
|
||||
CoeffsToSlotsMatrix := ckksAdvanced.NewHomomorphicEncodingMatrixFromLiteral(CoeffsToSlotsParameters, encoderN12)
|
||||
|
||||
// Rotation Keys
|
||||
rotations := []int{}
|
||||
for i := 1; i < paramsN12.N(); i <<= 1 {
|
||||
rotations = append(rotations, i)
|
||||
}
|
||||
|
||||
rotations = append(rotations, SlotsToCoeffsParameters.Rotations()...)
|
||||
rotations = append(rotations, CoeffsToSlotsParameters.Rotations()...)
|
||||
|
||||
for i := 0; i < 32; i++{
|
||||
rotations = append(rotations, i)
|
||||
}
|
||||
|
||||
rotKey := kgenN12.GenRotationKeysForRotations(rotations, true, skN12)
|
||||
|
||||
eval := ckksAdvanced.NewEvaluator(paramsN12, rlwe.EvaluationKey{Rlk: nil, Rtks: rotKey})
|
||||
|
||||
values := make([]complex128, paramsN12.Slots())
|
||||
|
||||
for i := 0; i < paramsN12.Slots(); i++ {
|
||||
values[i] = complex(float64(i+1), float64(i+1+paramsN12.Slots()))
|
||||
}
|
||||
|
||||
fmt.Println("Before")
|
||||
ckks.SliceBitReverseInPlaceComplex128(values, paramsN12.Slots())
|
||||
for i := range values{
|
||||
fmt.Printf("%2d: %7.4f\n", i, values[i])
|
||||
}
|
||||
ckks.SliceBitReverseInPlaceComplex128(values, paramsN12.Slots())
|
||||
|
||||
pt := ckks.NewPlaintext(paramsN12, paramsN12.MaxLevel(), paramsN12.DefaultScale())
|
||||
encoderN12.EncodeSlots(values, pt, paramsN12.LogSlots())
|
||||
ctN12 := encryptorN12.EncryptNew(pt)
|
||||
|
||||
|
||||
ctN12R := eval.SlotsToCoeffsNew(ctN12, nil, SlotsToCoeffsMatrix)
|
||||
|
||||
valuesF := encoderN12.DecodeCoeffs(decryptorN12.DecryptNew(ctN12R))
|
||||
|
||||
fmt.Println("After")
|
||||
for i, v := range valuesF{
|
||||
fmt.Printf("%2d: %7.4f\n", i, v)
|
||||
}
|
||||
|
||||
encoderN12.EncodeCoeffs(valuesF, pt)
|
||||
ctN12 = encryptorN12.EncryptNew(pt)
|
||||
|
||||
var ctN12I *ckks.Ciphertext
|
||||
ctN12R, ctN12I = eval.CoeffsToSlotsNew(ctN12, CoeffsToSlotsMatrix)
|
||||
|
||||
if ctN12I != nil{
|
||||
eval.MultByi(ctN12I, ctN12I)
|
||||
eval.Add(ctN12R, ctN12I, ctN12R)
|
||||
}
|
||||
|
||||
values = encoderN12.DecodeSlots(decryptorN12.DecryptNew(ctN12R), paramsN12.LogSlots())
|
||||
|
||||
fmt.Println("After")
|
||||
for i, v := range values{
|
||||
fmt.Printf("%2d: %7.4f\n", i, v)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user