mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
[circuits/float]: improved bootstrapper API
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user