[ckks/advanced]: better StC & CtS

This commit is contained in:
Jean-Philippe Bossuat
2022-02-25 20:34:27 +01:00
committed by Jean-Philippe Bossuat
parent d6213c1771
commit 6cfd218439
12 changed files with 685 additions and 67 deletions

View File

@@ -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.

View File

@@ -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
}
}
}

View File

@@ -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)

View File

@@ -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++

View File

@@ -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)

View File

@@ -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

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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

View File

@@ -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)

View File

@@ -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
View 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)
}
}