[circuits/float]: improved bootstrapper API

This commit is contained in:
Jean-Philippe Bossuat
2023-09-15 17:49:19 +02:00
parent 705f05d646
commit 820fced615
4 changed files with 32 additions and 36 deletions

View File

@@ -15,13 +15,10 @@ import (
)
type Bootstrapper struct {
Parameters
bridge ckks.DomainSwitcher
bootstrapper *bootstrapping.Bootstrapper
paramsN1 ckks.Parameters
paramsN2 ckks.Parameters
btpParamsN2 bootstrapping.Parameters
xPow2N1 []ring.Poly
xPow2InvN1 []ring.Poly
xPow2N2 []ring.Poly
@@ -30,11 +27,12 @@ type Bootstrapper struct {
evk *BootstrappingKeys
}
func NewBootstrapper(paramsN1 ckks.Parameters, btpParamsN2 Parameters, evk *BootstrappingKeys) (*Bootstrapper, error) {
func NewBootstrapper(btpParams Parameters, evk *BootstrappingKeys) (*Bootstrapper, error) {
b := &Bootstrapper{}
paramsN2 := btpParamsN2.Parameters.Parameters
paramsN1 := btpParams.ResidualParameters
paramsN2 := btpParams.Parameters.Parameters
switch paramsN1.RingType() {
case ring.Standard:
@@ -52,27 +50,25 @@ func NewBootstrapper(paramsN1 ckks.Parameters, btpParamsN2 Parameters, evk *Boot
}
// The switch to standard to conjugate invariant multiplies the scale by 2
btpParamsN2.SlotsToCoeffsParameters.Scaling = new(big.Float).SetFloat64(0.5)
btpParams.SlotsToCoeffsParameters.Scaling = new(big.Float).SetFloat64(0.5)
}
b.paramsN1 = paramsN1
b.paramsN2 = paramsN2
b.btpParamsN2 = btpParamsN2.Parameters
b.Parameters = btpParams
b.evk = evk
b.xPow2N2 = rlwe.GenXPow2(b.paramsN2.RingQ().AtLevel(0), b.paramsN2.LogN(), false)
b.xPow2InvN2 = rlwe.GenXPow2(b.paramsN2.RingQ(), b.paramsN2.LogN(), true)
b.xPow2N2 = rlwe.GenXPow2(paramsN2.RingQ().AtLevel(0), paramsN2.LogN(), false)
b.xPow2InvN2 = rlwe.GenXPow2(paramsN2.RingQ(), paramsN2.LogN(), true)
if paramsN1.N() != b.paramsN2.N() {
if paramsN1.N() != paramsN2.N() {
b.xPow2N1 = b.xPow2N2
b.xPow2InvN1 = b.xPow2InvN2
} else {
b.xPow2N1 = rlwe.GenXPow2(b.paramsN1.RingQ().AtLevel(0), b.paramsN2.LogN(), false)
b.xPow2InvN1 = rlwe.GenXPow2(b.paramsN1.RingQ(), b.paramsN2.LogN(), true)
b.xPow2N1 = rlwe.GenXPow2(paramsN1.RingQ().AtLevel(0), paramsN2.LogN(), false)
b.xPow2InvN1 = rlwe.GenXPow2(paramsN1.RingQ(), paramsN2.LogN(), true)
}
var err error
if b.bootstrapper, err = bootstrapping.NewBootstrapper(btpParamsN2.Parameters, evk.EvkBootstrapping); err != nil {
if b.bootstrapper, err = bootstrapping.NewBootstrapper(btpParams.Parameters, evk.EvkBootstrapping); err != nil {
return nil, err
}
@@ -80,11 +76,11 @@ func NewBootstrapper(paramsN1 ckks.Parameters, btpParamsN2 Parameters, evk *Boot
}
func (b Bootstrapper) Depth() int {
return b.btpParamsN2.SlotsToCoeffsParameters.Depth(true) + b.btpParamsN2.Mod1ParametersLiteral.Depth() + b.btpParamsN2.CoeffsToSlotsParameters.Depth(true)
return b.Parameters.Parameters.MaxLevel() - b.ResidualParameters.MaxLevel()
}
func (b Bootstrapper) OutputLevel() int {
return b.paramsN2.MaxLevel() - b.Depth()
return b.ResidualParameters.MaxLevel()
}
func (b Bootstrapper) MinimumInputLevel() int {
@@ -104,7 +100,7 @@ func (b Bootstrapper) BootstrapMany(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphertext,
var err error
switch b.paramsN1.RingType() {
switch b.ResidualParameters.RingType() {
case ring.ConjugateInvariant:
for i := 0; i < len(cts); i = i + 2 {
@@ -154,7 +150,7 @@ func (b Bootstrapper) BootstrapMany(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphertext,
runtime.GC()
for i := range cts {
cts[i].Scale = b.paramsN1.DefaultScale()
cts[i].Scale = b.ResidualParameters.DefaultScale()
}
return cts, err

View File

@@ -62,7 +62,7 @@ func TestBootstrapping(t *testing.T) {
btpKeys, err := btpParams.GenBootstrappingKeys(sk)
require.NoError(t, err)
bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys)
bootstrapper, err := NewBootstrapper(btpParams, btpKeys)
require.NoError(t, err)
ecd := ckks.NewEncoder(params)
@@ -142,7 +142,7 @@ func TestBootstrapping(t *testing.T) {
btpKeys, err := btpParams.GenBootstrappingKeys(sk)
require.Nil(t, err)
bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys)
bootstrapper, err := NewBootstrapper(btpParams, btpKeys)
require.Nil(t, err)
ecd := ckks.NewEncoder(params)
@@ -225,7 +225,7 @@ func TestBootstrapping(t *testing.T) {
btpKeys, err := btpParams.GenBootstrappingKeys(sk)
require.Nil(t, err)
bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys)
bootstrapper, err := NewBootstrapper(btpParams, btpKeys)
require.Nil(t, err)
ecd := ckks.NewEncoder(params)
@@ -305,7 +305,7 @@ func TestBootstrapping(t *testing.T) {
btpKeys, err := btpParams.GenBootstrappingKeys(sk)
require.Nil(t, err)
bootstrapper, err := NewBootstrapper(params, btpParams, btpKeys)
bootstrapper, err := NewBootstrapper(btpParams, btpKeys)
require.Nil(t, err)
ecd := ckks.NewEncoder(params)

View File

@@ -12,8 +12,8 @@ import (
func (b Bootstrapper) SwitchRingDegreeN1ToN2New(ctN1 *rlwe.Ciphertext) (ctN2 *rlwe.Ciphertext) {
if ctN1.Value[0].N() < b.paramsN2.N() {
ctN2 = ckks.NewCiphertext(b.paramsN2, 1, ctN1.Level())
if ctN1.Value[0].N() < b.Parameters.Parameters.Parameters.N() {
ctN2 = ckks.NewCiphertext(b.Parameters.Parameters.Parameters, 1, ctN1.Level())
if err := b.bootstrapper.ApplyEvaluationKey(ctN1, b.evk.EvkN1ToN2, ctN2); err != nil {
panic(err)
}
@@ -26,8 +26,8 @@ func (b Bootstrapper) SwitchRingDegreeN1ToN2New(ctN1 *rlwe.Ciphertext) (ctN2 *rl
func (b Bootstrapper) SwitchRingDegreeN2ToN1New(ctN2 *rlwe.Ciphertext) (ctN1 *rlwe.Ciphertext) {
if ctN2.Value[0].N() > b.paramsN1.N() {
ctN1 = ckks.NewCiphertext(b.paramsN1, 1, ctN2.Level())
if ctN2.Value[0].N() > b.ResidualParameters.N() {
ctN1 = ckks.NewCiphertext(b.ResidualParameters, 1, ctN2.Level())
if err := b.bootstrapper.ApplyEvaluationKey(ctN2, b.evk.EvkN2ToN1, ctN1); err != nil {
panic(err)
}
@@ -39,7 +39,7 @@ func (b Bootstrapper) SwitchRingDegreeN2ToN1New(ctN2 *rlwe.Ciphertext) (ctN1 *rl
}
func (b Bootstrapper) ComplexToRealNew(ctCmplx *rlwe.Ciphertext) (ctReal *rlwe.Ciphertext) {
ctReal = ckks.NewCiphertext(b.paramsN1, 1, ctCmplx.Level())
ctReal = ckks.NewCiphertext(b.ResidualParameters, 1, ctCmplx.Level())
if err := b.bridge.ComplexToReal(b.bootstrapper.Evaluator, ctCmplx, ctReal); err != nil {
panic(err)
}
@@ -47,7 +47,7 @@ func (b Bootstrapper) ComplexToRealNew(ctCmplx *rlwe.Ciphertext) (ctReal *rlwe.C
}
func (b Bootstrapper) RealToComplexNew(ctReal *rlwe.Ciphertext) (ctCmplx *rlwe.Ciphertext) {
ctCmplx = ckks.NewCiphertext(b.paramsN2, 1, ctReal.Level())
ctCmplx = ckks.NewCiphertext(b.Parameters.Parameters.Parameters, 1, ctReal.Level())
if err := b.bridge.RealToComplex(b.bootstrapper.Evaluator, ctReal, ctCmplx); err != nil {
panic(err)
}
@@ -58,8 +58,8 @@ func (b Bootstrapper) PackAndSwitchN1ToN2(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphe
var err error
if b.paramsN1.N() != b.paramsN2.N() {
if cts, err = b.Pack(cts, b.paramsN1, b.xPow2N1); err != nil {
if b.ResidualParameters.N() != b.Parameters.Parameters.Parameters.N() {
if cts, err = b.Pack(cts, b.ResidualParameters, b.xPow2N1); err != nil {
return nil, fmt.Errorf("cannot PackAndSwitchN1ToN2: PackN1: %w", err)
}
@@ -68,7 +68,7 @@ func (b Bootstrapper) PackAndSwitchN1ToN2(cts []*rlwe.Ciphertext) ([]*rlwe.Ciphe
}
}
if cts, err = b.Pack(cts, b.paramsN2, b.xPow2N2); err != nil {
if cts, err = b.Pack(cts, b.Parameters.Parameters.Parameters, b.xPow2N2); err != nil {
return nil, fmt.Errorf("cannot PackAndSwitchN1ToN2: PackN2: %w", err)
}
@@ -79,11 +79,11 @@ func (b Bootstrapper) UnpackAndSwitchN2Tn1(cts []*rlwe.Ciphertext, LogSlots, Nb
var err error
if cts, err = b.UnPack(cts, b.paramsN2, LogSlots, Nb, b.xPow2InvN2); err != nil {
if cts, err = b.UnPack(cts, b.Parameters.Parameters.Parameters, LogSlots, Nb, b.xPow2InvN2); err != nil {
return nil, fmt.Errorf("cannot UnpackAndSwitchN2Tn1: UnpackN2: %w", err)
}
if b.paramsN1.N() != b.paramsN2.N() {
if b.ResidualParameters.N() != b.Parameters.Parameters.Parameters.N() {
for i := range cts {
cts[i] = b.SwitchRingDegreeN2ToN1New(cts[i])
}

View File

@@ -152,7 +152,7 @@ func main() {
// Instantiates the bootstrapper
var btp *bootstrapper.Bootstrapper
if btp, err = bootstrapper.NewBootstrapper(params, btpParams, evk); err != nil {
if btp, err = bootstrapper.NewBootstrapper(btpParams, evk); err != nil {
panic(err)
}