staticcheck

This commit is contained in:
Jean-Philippe Bossuat
2020-12-16 11:15:57 +01:00
parent 98fa0eb8a6
commit e2fd203d81
36 changed files with 119 additions and 292 deletions

View File

@@ -22,15 +22,12 @@ type KeyGenerator interface {
// keyGenerator is a structure that stores the elements required to create new keys,
// as well as a small memory pool for intermediate values.
type keyGenerator struct {
params *Parameters
ringQP *ring.Ring
pBigInt *big.Int
polypool [2]*ring.Poly
gaussianSampler *ring.GaussianSampler
uniformSampler *ring.UniformSampler
galElRotRow uint64 // Rows rotation generator
galElRotColLeft []uint64 // Columns right rotations generators
galElRotColRight []uint64 // Columsn left rotations generators
params *Parameters
ringQP *ring.Ring
pBigInt *big.Int
polypool [2]*ring.Poly
gaussianSampler *ring.GaussianSampler
uniformSampler *ring.UniformSampler
}
// SecretKey is a structure that stores the SecretKey.
@@ -55,10 +52,6 @@ const (
// RotationKeys is a structure that stores the switching-keys required during the homomorphic rotations.
type RotationKeys struct {
permuteNTTLeftIndex map[uint64][]uint64
permuteNTTRightIndex map[uint64][]uint64
permuteNTTRowIndex []uint64
evakeyRotColLeft map[uint64]*SwitchingKey
evakeyRotColRight map[uint64]*SwitchingKey
evakeyRotRow *SwitchingKey
@@ -103,15 +96,12 @@ func NewKeyGenerator(params *Parameters) KeyGenerator {
}
return &keyGenerator{
params: params.Copy(),
ringQP: ringQP,
pBigInt: pBigInt,
polypool: [2]*ring.Poly{ringQP.NewPoly(), ringQP.NewPoly()},
gaussianSampler: ring.NewGaussianSampler(prng, ringQP, params.Sigma(), uint64(6*params.Sigma())),
uniformSampler: ring.NewUniformSampler(prng, ringQP),
galElRotColLeft: ring.GenGaloisParams(params.N(), GaloisGen),
galElRotColRight: ring.GenGaloisParams(params.N(), ring.ModExp(GaloisGen, 2*params.N()-1, 2*params.N())),
galElRotRow: 2*params.N() - 1,
params: params.Copy(),
ringQP: ringQP,
pBigInt: pBigInt,
polypool: [2]*ring.Poly{ringQP.NewPoly(), ringQP.NewPoly()},
gaussianSampler: ring.NewGaussianSampler(prng, ringQP, params.Sigma(), uint64(6*params.Sigma())),
uniformSampler: ring.NewUniformSampler(prng, ringQP),
}
}
@@ -311,7 +301,9 @@ func NewRotationKeys() (rotKey *RotationKeys) {
// GenRot populates the target RotationKeys with a SwitchingKey for the desired rotation type and amount.
func (keygen *keyGenerator) GenRot(rotType Rotation, sk *SecretKey, k uint64, rotKey *RotationKeys) {
if keygen.ringQP == nil {
ringQP := keygen.ringQP
if ringQP == nil {
panic("Cannot GenRot: modulus P is empty")
}
@@ -323,7 +315,7 @@ func (keygen *keyGenerator) GenRot(rotType Rotation, sk *SecretKey, k uint64, ro
}
if rotKey.evakeyRotColLeft[k] == nil && k != 0 {
rotKey.evakeyRotColLeft[k] = keygen.genrotKey(sk.Get(), keygen.galElRotColRight[k])
rotKey.evakeyRotColLeft[k] = keygen.genrotKey(sk.Get(), ring.ModExp(GaloisGen, 2*ringQP.N-k, 2*ringQP.N))
}
case RotationRight:
@@ -333,11 +325,11 @@ func (keygen *keyGenerator) GenRot(rotType Rotation, sk *SecretKey, k uint64, ro
}
if rotKey.evakeyRotColRight[k] == nil && k != 0 {
rotKey.evakeyRotColRight[k] = keygen.genrotKey(sk.Get(), keygen.galElRotColLeft[k])
rotKey.evakeyRotColRight[k] = keygen.genrotKey(sk.Get(), ring.ModExp(GaloisGen, k, 2*ringQP.N))
}
case RotationRow:
rotKey.evakeyRotRow = keygen.genrotKey(sk.Get(), keygen.galElRotRow)
rotKey.evakeyRotRow = keygen.genrotKey(sk.Get(), 2*ringQP.N-1)
}
}

View File

@@ -22,18 +22,6 @@ const MaxModuliCount = 34
// MaxModuliSize is the largest bit-length supported for the moduli in the RNS representation.
const MaxModuliSize = 60
// Plaintext moduli allowing batching for the corresponding N in ascending bit-size.
var tBatching = map[uint64][]uint64{
4096: {40961, 114689, 188417, 417793, 1032193, 2056193, 4169729, 8380417, 16760833, 33538049, 67084289, 134176769,
268369921, 536813569, 1073692673, 2147377153, 4294828033},
8192: {65537, 114689, 163841, 1032193, 1785857, 4079617, 8273921, 16760833, 33538049, 67043329, 133857281,
268369921, 536690689, 1073692673, 2147352577, 4294475777},
16384: {65537, 163841, 786433, 1769473, 3735553, 8257537, 16580609, 33292289, 67043329, 133857281, 268369921,
536641537, 1073643521, 2147352577, 4294475777},
32768: {65537, 786433, 1769473, 3735553, 8257537, 16580609, 33292289, 67043329, 132710401, 268369921, 536608769,
1073479681, 2147352577, 4293918721},
}
const (
// PN12QP109 is a set of parameters with N = 2^12 and log(QP) = 109
PN12QP109 = iota
@@ -251,11 +239,11 @@ func (p *Parameters) WithT(T uint64) (pCopy *Parameters) {
// LogModuli generates a LogModuli struct from the parameters' Moduli struct and returns it.
func (p *Parameters) LogModuli() (lm *LogModuli) {
lm = new(LogModuli)
lm.LogQi = make([]uint64, len(p.qi), len(p.qi))
lm.LogQi = make([]uint64, len(p.qi))
for i := range p.qi {
lm.LogQi[i] = uint64(math.Round(math.Log2(float64(p.qi[i]))))
}
lm.LogPi = make([]uint64, len(p.pi), len(p.pi))
lm.LogPi = make([]uint64, len(p.pi))
for i := range p.pi {
lm.LogPi[i] = uint64(math.Round(math.Log2(float64(p.pi[i]))))
}
@@ -471,8 +459,8 @@ func (p *Parameters) UnmarshalBinary(data []byte) error {
p.t = b.ReadUint64()
p.sigma = math.Float64frombits(b.ReadUint64())
p.qi = make([]uint64, lenQi, lenQi)
p.pi = make([]uint64, lenPi, lenPi)
p.qi = make([]uint64, lenQi)
p.pi = make([]uint64, lenPi)
b.ReadUint64Slice(p.qi)
b.ReadUint64Slice(p.pi)

View File

@@ -45,7 +45,7 @@ func BenchmarkBootstrapp(b *testing.B) {
// ModUp ct_{Q_0} -> ct_{Q_L}
t = time.Now()
ct = btp.modUp(ct)
b.Log("After ModUp :", time.Now().Sub(t), ct.Level(), ct.Scale())
b.Log("After ModUp :", time.Since(t), ct.Level(), ct.Scale())
// Brings the ciphertext scale to sineQi/(Q0/scale) if its under
btp.evaluator.ScaleUp(ct, math.Round(btp.postscale/ct.Scale()), ct)
@@ -53,23 +53,23 @@ func BenchmarkBootstrapp(b *testing.B) {
//SubSum X -> (N/dslots) * Y^dslots
t = time.Now()
ct = btp.subSum(ct)
b.Log("After SubSum :", time.Now().Sub(t), ct.Level(), ct.Scale())
b.Log("After SubSum :", time.Since(t), ct.Level(), ct.Scale())
// Part 1 : Coeffs to slots
t = time.Now()
ct0, ct1 = btp.coeffsToSlots(ct)
b.Log("After CtS :", time.Now().Sub(t), ct0.Level(), ct0.Scale())
b.Log("After CtS :", time.Since(t), ct0.Level(), ct0.Scale())
// Part 2 : SineEval
t = time.Now()
ct0, ct1 = btp.evaluateSine(ct0, ct1)
b.Log("After Sine :", time.Now().Sub(t), ct0.Level(), ct0.Scale())
b.Log("After Sine :", time.Since(t), ct0.Level(), ct0.Scale())
// Part 3 : Slots to coeffs
t = time.Now()
ct0 = btp.slotsToCoeffs(ct0, ct1)
ct0.SetScale(math.Exp2(math.Round(math.Log2(ct0.Scale()))))
b.Log("After StC :", time.Now().Sub(t), ct0.Level(), ct0.Scale())
b.Log("After StC :", time.Since(t), ct0.Level(), ct0.Scale())
}
})
}

View File

@@ -2,7 +2,6 @@ package ckks
import (
"fmt"
"log"
"math"
"math/cmplx"
@@ -41,8 +40,6 @@ type Bootstrapper struct {
ctxpool *Ciphertext // Memory pool
decryptor Decryptor
poolQ [1]*ring.Poly // Memory pool for the matrix evaluation
poolP [2]*ring.Poly // Memory pool for the matrix evaluation
}
@@ -62,17 +59,6 @@ func cos2pi(x complex128) complex128 {
return cmplx.Cos(6.283185307179586 * x)
}
func (btp *Bootstrapper) printDebug(message string, ciphertext *Ciphertext) {
coeffs := btp.encoder.Decode(btp.decryptor.DecryptNew(ciphertext), btp.dslots)
if btp.dslots == 2 {
log.Printf(message+"%.10f %.10f...\n", coeffs[0], coeffs[1])
} else {
log.Printf(message+"%.10f %.10f %.10f %.10f...\n", coeffs[0], coeffs[1], coeffs[2], coeffs[3])
}
}
// NewBootstrapper creates a new Bootstrapper.
func NewBootstrapper(params *Parameters, btpParams *BootstrappParams, btpKey *BootstrappingKey) (btp *Bootstrapper, err error) {
@@ -237,8 +223,6 @@ func (btp *Bootstrapper) genDFTMatrices() {
log.Println("Switching-Keys size (GB) :", float64(nbKeys*nbPoly*nbCoefficients*bytesPerCoeff)/float64(1000000000), "(", nbKeys, "keys)")
*/
return
}
func (btp *Bootstrapper) genSinePoly() {

View File

@@ -54,21 +54,6 @@ func chebyshevNodes(n int, a, b complex128) (u []complex128) {
return
}
func evaluateChebyshevPolynomial(coeffs []complex128, x complex128, a, b complex128) (y complex128) {
var u, Tprev, Tnext, T complex128
u = (2*x - a - b) / (b - a)
Tprev = 1
T = u
y = coeffs[0]
for i := 1; i < len(coeffs); i++ {
y = y + T*coeffs[i]
Tnext = 2*u*T - Tprev
Tprev = T
T = Tnext
}
return
}
func chebyCoeffs(nodes, fi []complex128, a, b complex128) (coeffs []complex128) {
var u, Tprev, T, Tnext complex128

View File

@@ -946,7 +946,6 @@ func testRotateColumns(testContext *testParams, t *testing.T) {
values1, _, ciphertext1 := newTestVectors(testContext, testContext.encryptorSk, complex(-1, -1), complex(1, 1), t)
values2 := make([]complex128, len(values1))
ciphertext2 := NewCiphertext(testContext.params, ciphertext1.Degree(), ciphertext1.Level(), ciphertext1.Scale())
for n := 1; n < len(values1); n <<= 1 {
@@ -955,9 +954,7 @@ func testRotateColumns(testContext *testParams, t *testing.T) {
values2[i] = values1[(i+n)%len(values1)]
}
ciphertext2 = testContext.evaluator.RotateNew(ciphertext1, uint64(n), rotKey)
verifyTestVectors(testContext, testContext.decryptor, values2, ciphertext2, t)
verifyTestVectors(testContext, testContext.decryptor, values2, testContext.evaluator.RotateNew(ciphertext1, uint64(n), rotKey), t)
}
})

View File

@@ -138,22 +138,6 @@ func (eval *evaluator) getElemAndCheckBinary(op0, op1, opOut Operand, opOutMinDe
return
}
func (eval *evaluator) getElemAndCheckUnary(op0, opOut Operand, opOutMinDegree uint64) (el0, elOut *Element) {
if op0 == nil || opOut == nil {
panic("operand cannot be nil")
}
if op0.Degree() == 0 {
panic("operand cannot be plaintext")
}
if opOut.Degree() < opOutMinDegree {
panic("receiver operand degree is too small")
}
el0, elOut = op0.El(), opOut.El()
return
}
func (eval *evaluator) newCiphertextBinary(op0, op1 Operand) (ctOut *Ciphertext) {
maxDegree := utils.MaxUint64(op0.Degree(), op1.Degree())
@@ -385,31 +369,28 @@ func (eval *evaluator) AddConstNew(ct0 *Ciphertext, constant interface{}) (ctOut
// AddConst adds the input constant (which can be a uint64, int64, float64 or complex128) to ct0 and returns the result in ctOut.
func (eval *evaluator) AddConst(ct0 *Ciphertext, constant interface{}, ctOut *Ciphertext) {
var level uint64
level = utils.MinUint64(ct0.Level(), ctOut.Level())
var level = utils.MinUint64(ct0.Level(), ctOut.Level())
var cReal, cImag float64
switch constant.(type) {
switch constant := constant.(type) {
case complex128:
cReal = real(constant.(complex128))
cImag = imag(constant.(complex128))
cReal = real(constant)
cImag = imag(constant)
case float64:
cReal = constant.(float64)
cReal = constant
cImag = float64(0)
case uint64:
cReal = float64(constant.(uint64))
cReal = float64(constant)
cImag = float64(0)
case int64:
cReal = float64(constant.(int64))
cReal = float64(constant)
cImag = float64(0)
case int:
cReal = float64(constant.(int))
cReal = float64(constant)
cImag = float64(0)
}
@@ -485,9 +466,7 @@ func (eval *evaluator) AddConst(ct0 *Ciphertext, constant interface{}, ctOut *Ci
// The scale of the receiver element will be set to the scale that the input element would have after the multiplication by the constant.
func (eval *evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interface{}, ctOut *Ciphertext) {
var level uint64
level = utils.MinUint64(ct0.Level(), ctOut.Level())
var level = utils.MinUint64(ct0.Level(), ctOut.Level())
// Forces a drop of ctOut level to ct0 level
if ctOut.Level() > level {
@@ -499,10 +478,10 @@ func (eval *evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interface{},
// Converts to float64 and determines if a scaling is required (which is the case if either real or imag have a rational part)
scale = 1
switch constant.(type) {
switch constant := constant.(type) {
case complex128:
cReal = real(constant.(complex128))
cImag = imag(constant.(complex128))
cReal = real(constant)
cImag = imag(constant)
if cReal != 0 {
valueInt := int64(cReal)
@@ -523,7 +502,7 @@ func (eval *evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interface{},
}
case float64:
cReal = constant.(float64)
cReal = constant
cImag = float64(0)
if cReal != 0 {
@@ -536,15 +515,15 @@ func (eval *evaluator) MultByConstAndAdd(ct0 *Ciphertext, constant interface{},
}
case uint64:
cReal = float64(constant.(uint64))
cReal = float64(constant)
cImag = float64(0)
case int64:
cReal = float64(constant.(int64))
cReal = float64(constant)
cImag = float64(0)
case int:
cReal = float64(constant.(int))
cReal = float64(constant)
cImag = float64(0)
}
@@ -679,19 +658,16 @@ func (eval *evaluator) MultByConstNew(ct0 *Ciphertext, constant interface{}) (ct
// needs to be scaled (its rational part is not zero)). The constant can be a uint64, int64, float64 or complex128.
func (eval *evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, ctOut *Ciphertext) {
var level uint64
var level = utils.MinUint64(ct0.Level(), ctOut.Level())
level = utils.MinUint64(ct0.Level(), ctOut.Level())
var cReal, cImag float64
var scale float64
var scale, cReal, cImag float64
// Converts to float64 and determines if a scaling is required (which is the case if either real or imag have a rational part)
scale = 1
switch constant.(type) {
switch constant := constant.(type) {
case complex128:
cReal = real(constant.(complex128))
cImag = imag(constant.(complex128))
cReal = real(constant)
cImag = imag(constant)
if cReal != 0 {
valueInt := int64(cReal)
@@ -712,7 +688,7 @@ func (eval *evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, ctOut
}
case float64:
cReal = constant.(float64)
cReal = constant
cImag = float64(0)
if cReal != 0 {
@@ -725,15 +701,15 @@ func (eval *evaluator) MultByConst(ct0 *Ciphertext, constant interface{}, ctOut
}
case uint64:
cReal = float64(constant.(uint64))
cReal = float64(constant)
cImag = float64(0)
case int64:
cReal = float64(constant.(int64))
cReal = float64(constant)
cImag = float64(0)
case int:
cReal = float64(constant.(int))
cReal = float64(constant)
cImag = float64(0)
}
@@ -996,9 +972,7 @@ func (eval *evaluator) MultByiNew(ct0 *Ciphertext) (ctOut *Ciphertext) {
// It does not change the scale.
func (eval *evaluator) MultByi(ct0 *Ciphertext, ctOut *Ciphertext) {
var level uint64
level = utils.MinUint64(ct0.Level(), ctOut.Level())
var level = utils.MinUint64(ct0.Level(), ctOut.Level())
ringQ := eval.ringQ
@@ -1068,9 +1042,7 @@ func (eval *evaluator) DivByiNew(ct0 *Ciphertext) (ctOut *Ciphertext) {
// It does not change the scale.
func (eval *evaluator) DivByi(ct0 *Ciphertext, ctOut *Ciphertext) {
var level uint64
level = utils.MinUint64(ct0.Level(), ctOut.Level())
var level = utils.MinUint64(ct0.Level(), ctOut.Level())
ringQ := eval.ringQ
@@ -1139,7 +1111,6 @@ func (eval *evaluator) ScaleUpNew(ct0 *Ciphertext, scale float64) (ctOut *Cipher
func (eval *evaluator) ScaleUp(ct0 *Ciphertext, scale float64, ctOut *Ciphertext) {
eval.MultByConst(ct0, uint64(scale), ctOut)
ctOut.SetScale(ct0.Scale() * scale)
return
}
// SetScale sets the scale of the ciphertext to the input scale (consumes a level)
@@ -1169,8 +1140,7 @@ func (eval *evaluator) MulByPow2New(ct0 *Ciphertext, pow2 uint64) (ctOut *Cipher
// MulByPow2 multiplies ct0 by 2^pow2 and returns the result in ctOut.
func (eval *evaluator) MulByPow2(ct0 *Element, pow2 uint64, ctOut *Element) {
var level uint64
level = utils.MinUint64(ct0.Level(), ctOut.Level())
var level = utils.MinUint64(ct0.Level(), ctOut.Level())
for i := range ctOut.Value() {
eval.ringQ.MulByPow2Lvl(level, ct0.value[i], pow2, ctOut.Value()[i])
}

View File

@@ -96,7 +96,7 @@ func (el *Element) NTT(ringQ *ring.Ring, c *Element) error {
if el.Degree() != c.Degree() {
return errors.New("error: receiver element has invalid degree (it does not match)")
}
if el.IsNTT() != true {
if !el.IsNTT() {
for i := range el.value {
ringQ.NTTLvl(el.Level(), el.Value()[i], c.Value()[i])
}
@@ -110,7 +110,7 @@ func (el *Element) InvNTT(ringQ *ring.Ring, c *Element) error {
if el.Degree() != c.Degree() {
return errors.New("error: receiver element invalid degree (it does not match)")
}
if el.IsNTT() != false {
if el.IsNTT() {
for i := range el.value {
ringQ.InvNTTLvl(el.Level(), el.Value()[i], c.Value()[i])
}

View File

@@ -252,9 +252,9 @@ func NewParametersFromModuli(logN uint64, m *Moduli) (p *Parameters, err error)
return nil, err
}
p.qi = make([]uint64, len(m.Qi), len(m.Qi))
p.qi = make([]uint64, len(m.Qi))
copy(p.qi, m.Qi)
p.pi = make([]uint64, len(m.Pi), len(m.Pi))
p.pi = make([]uint64, len(m.Pi))
copy(p.pi, m.Pi)
p.sigma = DefaultSigma
@@ -365,12 +365,12 @@ func (p *Parameters) LogModuli() (lm *LogModuli) {
lm = new(LogModuli)
lm.LogQi = make([]uint64, len(p.qi), len(p.qi))
lm.LogQi = make([]uint64, len(p.qi))
for i := range p.qi {
lm.LogQi[i] = uint64(math.Round(math.Log2(float64(p.qi[i]))))
}
lm.LogPi = make([]uint64, len(p.pi), len(p.pi))
lm.LogPi = make([]uint64, len(p.pi))
for i := range p.pi {
lm.LogPi[i] = uint64(math.Round(math.Log2(float64(p.pi[i]))))
}
@@ -381,8 +381,8 @@ func (p *Parameters) LogModuli() (lm *LogModuli) {
// Moduli returns a struct Moduli with the moduli of the parameters
func (p *Parameters) Moduli() (m *Moduli) {
m = new(Moduli)
m.Qi = make([]uint64, p.QiCount(), p.QiCount())
m.Pi = make([]uint64, p.PiCount(), p.PiCount())
m.Qi = make([]uint64, p.QiCount())
m.Pi = make([]uint64, p.PiCount())
copy(m.Qi, p.qi)
copy(m.Pi, p.pi)
return
@@ -520,9 +520,9 @@ func (p *Parameters) Copy() (paramsCopy *Parameters) {
paramsCopy.logSlots = p.logSlots
paramsCopy.scale = p.scale
paramsCopy.sigma = p.sigma
paramsCopy.qi = make([]uint64, len(p.qi), len(p.qi))
paramsCopy.qi = make([]uint64, len(p.qi))
copy(paramsCopy.qi, p.qi)
paramsCopy.pi = make([]uint64, len(p.pi), len(p.pi))
paramsCopy.pi = make([]uint64, len(p.pi))
copy(paramsCopy.pi, p.pi)
return
}
@@ -597,8 +597,8 @@ func (p *Parameters) UnmarshalBinary(data []byte) (err error) {
lenQi := b.ReadUint8()
lenPi := b.ReadUint8()
p.qi = make([]uint64, lenQi, lenQi)
p.pi = make([]uint64, lenPi, lenPi)
p.qi = make([]uint64, lenQi)
p.pi = make([]uint64, lenPi)
b.ReadUint64Slice(p.qi)
b.ReadUint64Slice(p.pi)

View File

@@ -18,7 +18,7 @@ type Poly struct {
func NewPoly(coeffs []complex128) (p *Poly) {
p = new(Poly)
p.coeffs = make([]complex128, len(coeffs), len(coeffs))
p.coeffs = make([]complex128, len(coeffs))
copy(p.coeffs, coeffs)
p.maxDeg = uint64(len(coeffs) - 1)
p.lead = true
@@ -49,36 +49,6 @@ func (p *Poly) Degree() uint64 {
return uint64(len(p.coeffs) - 1)
}
func optimalSplit(logDegree uint64) (logSplit uint64) {
logSplit = logDegree >> 1
a := (1 << logSplit) + (1 << (logDegree - logSplit)) + logDegree - logSplit - 3
b := (1 << (logSplit + 1)) + (1 << (logDegree - logSplit - 1)) + logDegree - logSplit - 4
if a > b {
logSplit++
}
return
}
func computeSmallPoly(split uint64, coeffs *Poly) (polyList []*Poly) {
if coeffs.Degree() < (1 << split) {
return []*Poly{coeffs}
}
var nextPower = uint64(1 << split)
for nextPower < (coeffs.Degree()>>1)+1 {
nextPower <<= 1
}
coeffsq, coeffsr := splitCoeffsCheby(coeffs, nextPower)
a := computeSmallPoly(split, coeffsq)
b := computeSmallPoly(split, coeffsr)
return append(a, b...)
}
// EvaluatePoly evaluates a polynomial in standard basis on the input Ciphertext in ceil(log2(deg+1)) levels.
// Returns an error if the input ciphertext does not have enough level to carry out the full polynomial evaluation.
// Returns an error if something is wrong with the scale.
@@ -105,7 +75,7 @@ func (eval *evaluator) EvaluatePoly(ct0 *Ciphertext, pol *Poly, evakey *Evaluati
opOut, err = recurse(eval.scale, logSplit, logDegree, pol, C, eval, evakey)
C = nil
return opOut, nil
return opOut, err
}
// EvaluateCheby evaluates a polynomial in Chebyshev basis on the input Ciphertext in ceil(log2(deg+1))+1 levels.

View File

@@ -40,13 +40,13 @@ func GetPrecisionStats(params *Parameters, encoder Encoder, decryptor Decryptor,
logSlots := params.LogSlots()
slots := uint64(1 << logSlots)
switch element.(type) {
switch element := element.(type) {
case *Ciphertext:
valuesTest = encoder.Decode(decryptor.DecryptNew(element.(*Ciphertext)), logSlots)
valuesTest = encoder.Decode(decryptor.DecryptNew(element), logSlots)
case *Plaintext:
valuesTest = encoder.Decode(element.(*Plaintext), logSlots)
valuesTest = encoder.Decode(element, logSlots)
case []complex128:
valuesTest = element.([]complex128)
valuesTest = element
}
var deltaReal, deltaImag float64

View File

@@ -2,15 +2,10 @@ package ckks
import (
"math/big"
"math/cmplx"
"github.com/ldsec/lattigo/v2/ring"
)
func exp2pi(x complex128) complex128 {
return cmplx.Exp(2 * 3.141592653589793 * complex(0, 1) * x)
}
func scaleUpExact(value float64, n float64, q uint64) (res uint64) {
var isNegative bool
@@ -85,8 +80,6 @@ func scaleUpVecExact(values []float64, n float64, moduli []uint64, coeffs [][]ui
}
}
}
return
}
func scaleUpVecExactBigFloat(values []*big.Float, scale float64, moduli []uint64, coeffs [][]uint64) {
@@ -127,15 +120,6 @@ func scaleUpVecExactBigFloat(values []*big.Float, scale float64, moduli []uint64
coeffs[j][i] = tmp.Uint64()
}
}
return
}
func modVec(values []*big.Int, q uint64, coeffs []uint64) {
tmp := new(big.Int)
for i := range values {
coeffs[i] = tmp.Mod(values[i], ring.NewUint(q)).Uint64()
}
}
// Divides x by n^2, returns a float
@@ -221,23 +205,3 @@ func sliceBitReverseInPlaceRingComplex(slice []*ring.Complex, N uint64) {
}
}
}
func max(array []complex128) (m float64) {
m = real(array[0])
for _, i := range array[1:] {
if real(i) > m {
m = real(i)
}
}
return
}
func min(array []complex128) (m float64) {
m = real(array[0])
for _, i := range array[1:] {
if real(i) < m {
m = real(i)
}
}
return
}

View File

@@ -144,7 +144,6 @@ func benchRelinKeyGenNaive(testCtx *testContext, b *testing.B) {
type Party struct {
*RKGProtocolNaive
u *ring.Poly
s *ring.Poly
share1 RKGNaiveShareRoundOne
share2 RKGNaiveShareRoundTwo

View File

@@ -28,7 +28,6 @@ type testContext struct {
prng utils.PRNG
encoder bfv.Encoder
kgen *bfv.KeyGenerator
sk0Shards []*bfv.SecretKey
sk0 *bfv.SecretKey
@@ -256,7 +255,6 @@ func testRelinKeyGenNaive(testCtx *testContext, t *testing.T) {
type Party struct {
*RKGProtocolNaive
u *ring.Poly
s *ring.Poly
share1 RKGNaiveShareRoundOne
share2 RKGNaiveShareRoundTwo
@@ -561,12 +559,10 @@ func testRefresh(testCtx *testContext, t *testing.T) {
ciphertextTmp := ciphertext.CopyNew().Ciphertext()
coeffsTmp := make([]uint64, len(coeffs))
for i := range coeffs {
coeffsTmp[i] = coeffs[i]
}
copy(coeffsTmp, coeffs)
// Finds the maximum multiplicative depth
for true {
for {
testCtx.evaluator.Relinearize(testCtx.evaluator.MulNew(ciphertextTmp, ciphertextTmp), rlk, ciphertextTmp)

View File

@@ -49,8 +49,7 @@ func (share *RefreshShare) MarshalBinary() ([]byte, error) {
}
ptr += tmp
tmp, err = (*share.RefreshShareRecrypt).WriteTo(data[ptr : ptr+lenRecrypt])
if err != nil {
if _, err = (*share.RefreshShareRecrypt).WriteTo(data[ptr : ptr+lenRecrypt]); err != nil {
return []byte{}, err
}

View File

@@ -178,8 +178,6 @@ func (ekg *RKGProtocol) GenShareRoundOne(u, sk *ring.Poly, crp []*ring.Poly, sha
}
ekg.polypool.Zero()
return
}
// AggregateShareRoundOne adds share1 and share2 on shareOut.

View File

@@ -50,7 +50,7 @@ func (share *RTGShare) MarshalBinary() ([]byte, error) {
// UnmarshalBinary decodes a slice of bytes on the target element.
func (share *RTGShare) UnmarshalBinary(data []byte) error {
if len(data) <= 24 {
return errors.New("Unsufficient data length")
return errors.New("unsufficient data length")
}
share.K = binary.BigEndian.Uint64(data[0:8])
share.Type = bfv.Rotation(binary.BigEndian.Uint64(data[8:16]))
@@ -189,8 +189,6 @@ func (rtg *RTGProtocol) genShare(sk *ring.Poly, galEl uint64, crp []*ring.Poly,
rtg.tmpPoly[0].Zero()
rtg.tmpPoly[1].Zero()
return
}
// Aggregate is the second part of the unique round of the rotkg protocol. Uppon receiving the j-1 public shares,

View File

@@ -32,6 +32,7 @@ func BenchmarkDCKKS(b *testing.B) {
benchPublicKeySwitching(testCtx, b)
benchRotKeyGen(testCtx, b)
benchRefresh(testCtx, b)
benchRefreshAndPermute(testCtx, b)
}
}
@@ -132,7 +133,6 @@ func benchRelinKeyGenNaive(testCtx *testContext, b *testing.B) {
type Party struct {
*RKGProtocolNaive
u *ring.Poly
s *ring.Poly
share1 RKGNaiveShareRoundOne
share2 RKGNaiveShareRoundTwo

View File

@@ -266,7 +266,6 @@ func testRelinKeyGenNaive(testCtx *testContext, t *testing.T) {
type Party struct {
*RKGProtocolNaive
u *ring.Poly
s *ring.Poly
share1 RKGNaiveShareRoundOne
share2 RKGNaiveShareRoundTwo
@@ -696,11 +695,11 @@ func verifyTestVectors(testCtx *testContext, decryptor ckks.Decryptor, valuesWan
var plaintextTest *ckks.Plaintext
var valuesTest []complex128
switch element.(type) {
switch element := element.(type) {
case *ckks.Ciphertext:
plaintextTest = decryptor.DecryptNew(element.(*ckks.Ciphertext))
plaintextTest = decryptor.DecryptNew(element)
case *ckks.Plaintext:
plaintextTest = element.(*ckks.Plaintext)
plaintextTest = element
}
slots := testCtx.params.Slots()

View File

@@ -40,6 +40,8 @@ func NewCKSProtocol(params *ckks.Parameters, sigmaSmudging float64) (cks *CKSPro
cks.tmpDelta = dckksContext.ringQ.NewPoly()
cks.hP = dckksContext.ringP.NewPoly()
cks.sigmaSmudging = sigmaSmudging
cks.baseconverter = ring.NewFastBasisExtender(dckksContext.ringQ, dckksContext.ringP)
prng, err := utils.NewPRNG()
if err != nil {

View File

@@ -39,6 +39,8 @@ func NewPCKSProtocol(params *ckks.Parameters, sigmaSmudging float64) *PCKSProtoc
pcks.share0tmp = dckksContext.ringQP.NewPoly()
pcks.share1tmp = dckksContext.ringQP.NewPoly()
pcks.sigmaSmudging = sigmaSmudging
pcks.baseconverter = ring.NewFastBasisExtender(dckksContext.ringQ, dckksContext.ringP)
prng, err := utils.NewPRNG()
if err != nil {

View File

@@ -175,8 +175,6 @@ func (ekg *RKGProtocol) GenShareRoundOne(u, sk *ring.Poly, crp []*ring.Poly, sha
// s*a + e_2i
ringQP.MulCoeffsMontgomeryAndAdd(sk, crp[i], shareOut[i][1])
}
return
}
// AggregateShareRoundOne adds share1 and share2 on shareOut.

View File

@@ -144,8 +144,6 @@ func (rtg *RTGProtocol) genShare(sk *ring.Poly, galEl uint64, crp []*ring.Poly,
rtg.tmpPoly[0].Zero()
rtg.tmpPoly[1].Zero()
return
}
// Aggregate is the second part of the unique round of the rotkg protocol. Uppon receiving the j-1 public shares,

View File

@@ -24,13 +24,10 @@ func chebyshevinterpolation() {
// Keys
kgen := ckks.NewKeyGenerator(params)
var sk *ckks.SecretKey
var pk *ckks.PublicKey
sk, pk = kgen.GenKeyPair()
sk, pk := kgen.GenKeyPair()
// Relinearization key
var rlk *ckks.EvaluationKey
rlk = kgen.GenRelinKey(sk)
rlk := kgen.GenRelinKey(sk)
// Encryptor
encryptor := ckks.NewEncryptorFromPk(params, pk)
@@ -98,8 +95,7 @@ func f(x complex128) complex128 {
}
func round(x complex128) complex128 {
var factor float64
factor = 100000000
var factor float64 = 100000000
a := math.Round(real(x)*factor) / factor
b := math.Round(imag(x)*factor) / factor
return complex(a, b)

View File

@@ -113,7 +113,7 @@ func main() {
ternarySamplerMontgomery := ring.NewTernarySampler(lattigoPRNG, ringQP, 0.5, true)
// Create each party, and allocate the memory for all the shares that the protocols will need
P := make([]*party, N, N)
P := make([]*party, N)
for i := range P {
pi := &party{}
pi.sk = kgen.GenSecretKey()
@@ -121,7 +121,7 @@ func main() {
pi.rlkEphemSk = ternarySamplerMontgomery.ReadNew()
ringQP.NTT(pi.rlkEphemSk, pi.rlkEphemSk)
pi.input = make([]uint64, 1<<params.LogN(), 1<<params.LogN())
pi.input = make([]uint64, 1<<params.LogN())
for j := range pi.input {
pi.input[j] = uint64(i)
}
@@ -223,9 +223,9 @@ func main() {
// Pre-loading memory
encoder := bfv.NewEncoder(params)
l.Println("> Memory alloc Phase")
encInputs := make([]*bfv.Ciphertext, N, N)
plainMask := make([]*bfv.PlaintextMul, N, N)
encPartial := make([]*bfv.Ciphertext, N, N)
encInputs := make([]*bfv.Ciphertext, N)
plainMask := make([]*bfv.PlaintextMul, N)
encPartial := make([]*bfv.Ciphertext, N)
// Ciphertexts to be retrieved
for i := range encInputs {

View File

@@ -90,7 +90,7 @@ func main() {
// Target private and public keys
tsk, tpk := bfv.NewKeyGenerator(params).GenKeyPair()
expRes := make([]uint64, 1<<params.LogN(), 1<<params.LogN())
expRes := make([]uint64, 1<<params.LogN())
for i := range expRes {
expRes[i] = 1
}
@@ -105,7 +105,7 @@ func main() {
ternarySamplerMontgomery := ring.NewTernarySampler(prng, ringQP, 0.5, true)
// Create each party, and allocate the memory for all the shares that the protocols will need
P := make([]*party, N, N)
P := make([]*party, N)
for i := range P {
pi := &party{}
pi.sk = bfv.NewKeyGenerator(params).GenSecretKey()
@@ -113,7 +113,7 @@ func main() {
pi.rlkEphemSk = ternarySamplerMontgomery.ReadNew()
ringQP.NTT(pi.rlkEphemSk, pi.rlkEphemSk)
pi.input = make([]uint64, 1<<params.LogN(), 1<<params.LogN())
pi.input = make([]uint64, 1<<params.LogN())
for i := range pi.input {
if utils.RandFloat64(0, 1) > 0.3 || i == 4 {
pi.input[i] = 1
@@ -187,7 +187,7 @@ func main() {
// Pre-loading memory
l.Println("> Memory alloc Phase")
encInputs := make([]*bfv.Ciphertext, N, N)
encInputs := make([]*bfv.Ciphertext, N)
for i := range encInputs {
encInputs[i] = bfv.NewCiphertext(params, 1)
}
@@ -195,7 +195,7 @@ func main() {
encLvls := make([][]*bfv.Ciphertext, 0)
encLvls = append(encLvls, encInputs)
for nLvl := N / 2; nLvl > 0; nLvl = nLvl >> 1 {
encLvl := make([]*bfv.Ciphertext, nLvl, nLvl)
encLvl := make([]*bfv.Ciphertext, nLvl)
for i := range encLvl {
encLvl[i] = bfv.NewCiphertext(params, 2)
}

View File

@@ -48,8 +48,8 @@ func BenchmarkDivRound(b *testing.B) {
func BenchmarkDivRoundDebug(b *testing.B) {
y := int64(123456789)
x := int64(987654321)
for i := 0; i < b.N; i++ {
x := int64(987654321)
x = int64(math.Round(float64(x / y)))
}
}

View File

@@ -37,7 +37,7 @@ func NextNTTPrime(q, NthRoot uint64) (qNext uint64, err error) {
qNext += NthRoot
if bits.Len64(qNext) > 61 {
return 0, fmt.Errorf("Next NTT prime exceeds the maximum bit-size of 61 bits")
return 0, fmt.Errorf("next NTT prime exceeds the maximum bit-size of 61 bits")
}
}
@@ -49,7 +49,7 @@ func NextNTTPrime(q, NthRoot uint64) (qNext uint64, err error) {
func PreviousNTTPrime(q, NthRoot uint64) (qPrev uint64, err error) {
if q < NthRoot {
return 0, fmt.Errorf("Previous NTT prime is smaller than NthRoot")
return 0, fmt.Errorf("previous NTT prime is smaller than NthRoot")
}
qPrev = q - NthRoot
@@ -57,7 +57,7 @@ func PreviousNTTPrime(q, NthRoot uint64) (qPrev uint64, err error) {
for !IsPrime(qPrev) {
if q < NthRoot {
return 0, fmt.Errorf("Previous NTT prime is smaller than NthRoot")
return 0, fmt.Errorf("previous NTT prime is smaller than NthRoot")
}
qPrev -= NthRoot
@@ -83,10 +83,10 @@ func GenerateNTTPrimesQ(logQ, NthRoot, levels uint64) (primes []uint64) {
checkfornextprime = true
checkforpreviousprime = true
for true {
for {
if !(checkfornextprime || checkforpreviousprime) {
panic("GenerateNTTPrimesQ error: cannot generate enough primes for the given parameters")
panic("generateNTTPrimesQ error: cannot generate enough primes for the given parameters")
}
if checkfornextprime {
@@ -149,7 +149,7 @@ func GenerateNTTPrimesP(logP, NthRoot, n uint64) (primes []uint64) {
x = Ppow2 + 1
for true {
for {
// We start by subtracting 2N to ensure that the prime bit-length is smaller than LogP
@@ -167,7 +167,7 @@ func GenerateNTTPrimesP(logP, NthRoot, n uint64) (primes []uint64) {
}
} else {
panic("GenerateNTTPrimesP error: cannot generate enough primes for the given parameters")
panic("generateNTTPrimesP error: cannot generate enough primes for the given parameters")
}
}

View File

@@ -138,7 +138,7 @@ func (r *Ring) genNTTParams() error {
}
}
r.RescaleParams = make([][]uint64, len(r.Modulus)-1, len(r.Modulus)-1)
r.RescaleParams = make([][]uint64, len(r.Modulus)-1)
for j := len(r.Modulus) - 1; j > 0; j-- {

View File

@@ -420,7 +420,7 @@ func benchBRed(testContext *testParams, b *testing.B) {
b.ResetTimer()
b.Run(fmt.Sprintf("BRed"), func(b *testing.B) {
b.Run("BRed", func(b *testing.B) {
for i := 0; i < b.N; i++ {
x = BRed(x, y, q, u)
}
@@ -439,7 +439,7 @@ func benchMRed(testContext *testParams, b *testing.B) {
b.ResetTimer()
b.Run(fmt.Sprintf("MRed"), func(b *testing.B) {
b.Run("MRed", func(b *testing.B) {
for i := 0; i < b.N; i++ {
x = MRed(x, y, q, m)
}
@@ -454,7 +454,7 @@ func benchBRedAdd(testContext *testParams, b *testing.B) {
b.ResetTimer()
b.Run(fmt.Sprintf("BRedAdd"), func(b *testing.B) {
b.Run("BRedAdd", func(b *testing.B) {
for i := 0; i < b.N; i++ {
BRedAdd(x, q, u)
}

View File

@@ -141,7 +141,7 @@ func (pol *Poly) WriteTo(data []byte) (uint64, error) {
if uint64(len(data)) < pol.GetDataLen(true) {
// The data is not big enough to write all the information
return 0, errors.New("Data array is too small to write ring.Poly")
return 0, errors.New("data array is too small to write ring.Poly")
}
data[0] = uint8(bits.Len64(uint64(N)) - 1)
data[1] = uint8(numberModuli)
@@ -160,7 +160,7 @@ func (pol *Poly) WriteTo32(data []byte) (uint64, error) {
if uint64(len(data)) < pol.GetDataLen32(true) {
//the data is not big enough to write all the information
return 0, errors.New("Data array is too small to write ring.Poly")
return 0, errors.New("data array is too small to write ring.Poly")
}
data[0] = uint8(bits.Len64(uint64(N)) - 1)
data[1] = uint8(numberModuli)
@@ -256,7 +256,7 @@ func (pol *Poly) UnmarshalBinary(data []byte) (err error) {
pointer := uint64(2)
if ((uint64(len(data)) - pointer) >> 3) != N*numberModulies {
return errors.New("error: invalid polynomial encoding")
return errors.New("invalid polynomial encoding")
}
if _, err = pol.DecodePolyNew(data); err != nil {

View File

@@ -63,8 +63,6 @@ func (uniformSampler *UniformSampler) Read(Pol *Poly) {
ptmp[i] = randomUint
}
}
return
}
// Readlvl generates a new polynomial with coefficients following a uniform distribution over [0, Qi-1].
@@ -109,8 +107,6 @@ func (uniformSampler *UniformSampler) Readlvl(level uint64, Pol *Poly) {
ptmp[i] = randomUint
}
}
return
}
// ReadNew generates a new polynomial with coefficients following a uniform distribution over [0, Qi-1].

View File

@@ -15,10 +15,8 @@ type Scaler interface {
// RNSScaler implements the Scaler interface by performing a scaling by t/Q in the RNS domain.
// This implementation of the Scaler interface is preferred over the SimpleScaler implementation.
type RNSScaler struct {
ringQ *Ring
paramsQT *modupParams
modDownParamsQT uint64
polypoolT *Poly
ringQ *Ring
polypoolT *Poly
qHalf *big.Int // (q-1)/2
qHalfModT uint64 // (q-1)/2 mod t
@@ -26,7 +24,6 @@ type RNSScaler struct {
t uint64
qInv uint64 //(q mod t)^-1 mod t
bredParamsT []uint64
mredParamsT uint64
paramsQP *modupParams
@@ -468,7 +465,6 @@ func (r *Ring) DivRoundByLastModulus(p0 *Poly) {
pHalf = (r.Modulus[level] - 1) >> 1
p0tmp := p0.Coeffs[level]
pj := r.Modulus[level]
pHalf = (r.Modulus[level] - 1) >> 1
for i := uint64(0); i < r.N; i = i + 8 {

View File

@@ -76,6 +76,7 @@ func TestRing(t *testing.T) {
testTernarySampler(testContext, t)
testGaloisShift(testContext, t)
testModularReduction(testContext, t)
testMForm(testContext, t)
testMulScalarBigint(testContext, t)
testMulPoly(testContext, t)
testExtendBasis(testContext, t)

View File

@@ -32,7 +32,7 @@ func TestBuffer_WriteReadUint64Slice(t *testing.T) {
b := NewBuffer(make([]byte, 0, 8))
b.WriteUint64Slice([]uint64{0x1122334455667788})
assert.Equal(t, []byte{0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88}, b.Bytes())
s := make([]uint64, 1, 1)
s := make([]uint64, 1)
b.ReadUint64Slice(s)
assert.Equal(t, []uint64{0x1122334455667788}, s)
assert.Equal(t, []byte{}, b.Bytes())

View File

@@ -1,7 +1,6 @@
package utils
import (
"fmt"
"testing"
"github.com/stretchr/testify/require"
@@ -9,7 +8,7 @@ import (
func Test_PRNG(t *testing.T) {
t.Run(fmt.Sprintf("PRNG"), func(t *testing.T) {
t.Run("PRNG", func(t *testing.T) {
key := []byte{0x49, 0x0a, 0x42, 0x3d, 0x97, 0x9d, 0xc1, 0x07, 0xa1, 0xd7, 0xe9, 0x7b, 0x3b, 0xce, 0xa1, 0xdb,
0x42, 0xf3, 0xa6, 0xd5, 0x75, 0xd2, 0x0c, 0x92, 0xb7, 0x35, 0xce, 0x0c, 0xee, 0x09, 0x7c, 0x98}