mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
Wrappers for polynomial evaluation
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package circuits
|
||||
|
||||
import (
|
||||
//"github.com/tuneinsight/lattigo/v4/bgv"
|
||||
"github.com/tuneinsight/lattigo/v4/ring"
|
||||
"github.com/tuneinsight/lattigo/v4/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/rlwe/ringqp"
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tuneinsight/lattigo/v4/circuits"
|
||||
"github.com/tuneinsight/lattigo/v4/ckks"
|
||||
"github.com/tuneinsight/lattigo/v4/ring"
|
||||
"github.com/tuneinsight/lattigo/v4/rlwe"
|
||||
@@ -48,7 +47,7 @@ type ckksTestContext struct {
|
||||
evaluator *ckks.Evaluator
|
||||
}
|
||||
|
||||
func TestCKKS(t *testing.T) {
|
||||
func TestFloat(t *testing.T) {
|
||||
|
||||
var err error
|
||||
|
||||
@@ -408,7 +407,7 @@ func testEvaluatePolynomial(tc *ckksTestContext, t *testing.T) {
|
||||
valuesWant[j] = poly.Evaluate(values[j])
|
||||
}
|
||||
|
||||
polyVector, err := circuits.NewPolynomialVector([]circuits.Polynomial{circuits.NewPolynomial(poly)}, slotIndex)
|
||||
polyVector, err := NewPolynomialVector([]bignum.Polynomial{poly}, slotIndex)
|
||||
require.NoError(t, err)
|
||||
|
||||
if ciphertext, err = polyEval.Polynomial(ciphertext, polyVector, ciphertext.Scale); err != nil {
|
||||
|
||||
19
circuits/float/polynomial.go
Normal file
19
circuits/float/polynomial.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package float
|
||||
|
||||
import (
|
||||
"github.com/tuneinsight/lattigo/v4/circuits"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
)
|
||||
|
||||
type Polynomial circuits.Polynomial
|
||||
|
||||
func NewPolynomial(poly bignum.Polynomial) Polynomial {
|
||||
return Polynomial(circuits.NewPolynomial(poly))
|
||||
}
|
||||
|
||||
type PolynomialVector circuits.PolynomialVector
|
||||
|
||||
func NewPolynomialVector(polys []bignum.Polynomial, mapping map[int][]int) (PolynomialVector, error) {
|
||||
p, err := circuits.NewPolynomialVector(polys, mapping)
|
||||
return PolynomialVector(p), err
|
||||
}
|
||||
@@ -15,11 +15,11 @@ type PolynomialEvaluator struct {
|
||||
Parameters ckks.Parameters
|
||||
}
|
||||
|
||||
// NewFloatPowerBasis is a wrapper of NewPolynomialBasis.
|
||||
// NewPowerBasis is a wrapper of NewPolynomialBasis.
|
||||
// This function creates a new powerBasis from the input ciphertext.
|
||||
// The input ciphertext is treated as the base monomial X used to
|
||||
// generate the other powers X^{n}.
|
||||
func NewFloatPowerBasis(ct *rlwe.Ciphertext, basis bignum.Basis) circuits.PowerBasis {
|
||||
func NewPowerBasis(ct *rlwe.Ciphertext, basis bignum.Basis) circuits.PowerBasis {
|
||||
return circuits.NewPowerBasis(ct, basis)
|
||||
}
|
||||
|
||||
@@ -40,8 +40,20 @@ func NewPolynomialEvaluator(params ckks.Parameters, eval circuits.EvaluatorForPo
|
||||
// targetScale: the desired output scale. This value shouldn't differ too much from the original ciphertext scale. It can
|
||||
// for example be used to correct small deviations in the ciphertext scale and reset it to the default scale.
|
||||
func (eval PolynomialEvaluator) Polynomial(input interface{}, p interface{}, targetScale rlwe.Scale) (opOut *rlwe.Ciphertext, err error) {
|
||||
|
||||
var pcircuits interface{}
|
||||
switch p := p.(type) {
|
||||
case Polynomial:
|
||||
pcircuits = circuits.Polynomial(p)
|
||||
case PolynomialVector:
|
||||
pcircuits = circuits.PolynomialVector(p)
|
||||
default:
|
||||
pcircuits = p
|
||||
}
|
||||
|
||||
levelsConsummedPerRescaling := eval.Parameters.LevelsConsummedPerRescaling()
|
||||
return circuits.EvaluatePolynomial(eval.PolynomialEvaluator, eval, input, p, targetScale, levelsConsummedPerRescaling, &simEvaluator{eval.Parameters, levelsConsummedPerRescaling})
|
||||
|
||||
return circuits.EvaluatePolynomial(eval.PolynomialEvaluator, eval, input, pcircuits, targetScale, levelsConsummedPerRescaling, &simEvaluator{eval.Parameters, levelsConsummedPerRescaling})
|
||||
}
|
||||
|
||||
func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLevel int, pol circuits.PolynomialVector, pb circuits.PowerBasis, targetScale rlwe.Scale) (res *rlwe.Ciphertext, err error) {
|
||||
@@ -54,7 +66,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
slots := 1 << logSlots.Cols
|
||||
|
||||
params := eval.Parameters
|
||||
slotsIndex := pol.SlotsIndex
|
||||
mapping := pol.Mapping
|
||||
even := pol.IsEven()
|
||||
odd := pol.IsOdd()
|
||||
|
||||
@@ -75,7 +87,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
}
|
||||
|
||||
// If an index slot is given (either multiply polynomials or masking)
|
||||
if slotsIndex != nil {
|
||||
if mapping != nil {
|
||||
|
||||
var toEncode bool
|
||||
|
||||
@@ -95,7 +107,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
for i, p := range pol.Value {
|
||||
if !isZero(p.Coeffs[0]) {
|
||||
toEncode = true
|
||||
for _, j := range slotsIndex[i] {
|
||||
for _, j := range mapping[i] {
|
||||
values[j] = p.Coeffs[0]
|
||||
}
|
||||
}
|
||||
@@ -125,7 +137,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
for i, p := range pol.Value {
|
||||
if !isZero(p.Coeffs[0]) {
|
||||
toEncode = true
|
||||
for _, j := range slotsIndex[i] {
|
||||
for _, j := range mapping[i] {
|
||||
values[j] = p.Coeffs[0]
|
||||
}
|
||||
}
|
||||
@@ -171,7 +183,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
|
||||
// Copies the coefficient on the temporary array
|
||||
// according to the slot map index
|
||||
for _, j := range slotsIndex[i] {
|
||||
for _, j := range mapping[i] {
|
||||
values[j] = p.Coeffs[key]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/tuneinsight/lattigo/v4/bfv"
|
||||
"github.com/tuneinsight/lattigo/v4/bgv"
|
||||
"github.com/tuneinsight/lattigo/v4/circuits"
|
||||
"github.com/tuneinsight/lattigo/v4/ring"
|
||||
"github.com/tuneinsight/lattigo/v4/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/utils"
|
||||
@@ -280,9 +279,9 @@ func testLinearTransformation(tc *testContext, t *testing.T) {
|
||||
slotIndex[0] = idx0
|
||||
slotIndex[1] = idx1
|
||||
|
||||
polyVector, err := circuits.NewPolynomialVector([]circuits.Polynomial{
|
||||
NewIntegerPolynomial(coeffs0),
|
||||
NewIntegerPolynomial(coeffs1),
|
||||
polyVector, err := NewPolynomialVector([][]uint64{
|
||||
coeffs0,
|
||||
coeffs1,
|
||||
}, slotIndex)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/bgv"
|
||||
"github.com/tuneinsight/lattigo/v4/circuits"
|
||||
"github.com/tuneinsight/lattigo/v4/ring"
|
||||
"github.com/tuneinsight/lattigo/v4/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/utils"
|
||||
@@ -365,7 +364,7 @@ func testBGVLinearTransformation(tc *bgvTestContext, t *testing.T) {
|
||||
|
||||
slots := values.N()
|
||||
|
||||
slotIndex := make(map[int][]int)
|
||||
mapping := make(map[int][]int)
|
||||
idx0 := make([]int, slots>>1)
|
||||
idx1 := make([]int, slots>>1)
|
||||
for i := 0; i < slots>>1; i++ {
|
||||
@@ -373,17 +372,17 @@ func testBGVLinearTransformation(tc *bgvTestContext, t *testing.T) {
|
||||
idx1[i] = 2*i + 1
|
||||
}
|
||||
|
||||
slotIndex[0] = idx0
|
||||
slotIndex[1] = idx1
|
||||
mapping[0] = idx0
|
||||
mapping[1] = idx1
|
||||
|
||||
polyVector, err := circuits.NewPolynomialVector([]circuits.Polynomial{
|
||||
NewIntegerPolynomial(coeffs0),
|
||||
NewIntegerPolynomial(coeffs1),
|
||||
}, slotIndex)
|
||||
polyVector, err := NewPolynomialVector([][]uint64{
|
||||
coeffs0,
|
||||
coeffs1,
|
||||
}, mapping)
|
||||
require.NoError(t, err)
|
||||
|
||||
TInt := new(big.Int).SetUint64(tc.params.PlaintextModulus())
|
||||
for pol, idx := range slotIndex {
|
||||
for pol, idx := range mapping {
|
||||
for _, i := range idx {
|
||||
values.Coeffs[0][i] = polyVector.Value[pol].EvaluateModP(new(big.Int).SetUint64(values.Coeffs[0][i]), TInt).Uint64()
|
||||
}
|
||||
|
||||
26
circuits/integer/polynomial.go
Normal file
26
circuits/integer/polynomial.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package integer
|
||||
|
||||
import (
|
||||
"github.com/tuneinsight/lattigo/v4/circuits"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
)
|
||||
|
||||
type Polynomial circuits.Polynomial
|
||||
|
||||
func NewPolynomial[T Integer](coeffs []T) Polynomial {
|
||||
return Polynomial(circuits.NewPolynomial(bignum.NewPolynomial(bignum.Monomial, coeffs, nil)))
|
||||
}
|
||||
|
||||
type PolynomialVector circuits.PolynomialVector
|
||||
|
||||
func NewPolynomialVector[T Integer](polys [][]T, mapping map[int][]int) (PolynomialVector, error) {
|
||||
|
||||
ps := make([]bignum.Polynomial, len(polys))
|
||||
|
||||
for i := range ps {
|
||||
ps[i] = bignum.NewPolynomial(bignum.Monomial, polys[i], nil)
|
||||
}
|
||||
|
||||
p, err := circuits.NewPolynomialVector(ps, mapping)
|
||||
return PolynomialVector(p), err
|
||||
}
|
||||
@@ -14,21 +14,14 @@ type PolynomialEvaluator struct {
|
||||
InvariantTensoring bool
|
||||
}
|
||||
|
||||
// NewIntegerPowerBasis is a wrapper of NewPolynomialBasis.
|
||||
// NewPowerBasis is a wrapper of NewPolynomialBasis.
|
||||
// This function creates a new powerBasis from the input ciphertext.
|
||||
// The input ciphertext is treated as the base monomial X used to
|
||||
// generate the other powers X^{n}.
|
||||
func NewIntegerPowerBasis(ct *rlwe.Ciphertext) circuits.PowerBasis {
|
||||
func NewPowerBasis(ct *rlwe.Ciphertext) circuits.PowerBasis {
|
||||
return circuits.NewPowerBasis(ct, bignum.Monomial)
|
||||
}
|
||||
|
||||
// NewIntegerPolynomial is a wrapper of NewPolynomial.
|
||||
// This function creates a new polynomial from the input coefficients.
|
||||
// This polynomial can be evaluated on a ciphertext.
|
||||
func NewIntegerPolynomial[T Integer](coeffs []T) circuits.Polynomial {
|
||||
return circuits.NewPolynomial(bignum.NewPolynomial(bignum.Monomial, coeffs, nil))
|
||||
}
|
||||
|
||||
func NewPolynomialEvaluator(params bgv.Parameters, eval *bgv.Evaluator, InvariantTensoring bool) *PolynomialEvaluator {
|
||||
e := new(PolynomialEvaluator)
|
||||
|
||||
@@ -44,7 +37,18 @@ func NewPolynomialEvaluator(params bgv.Parameters, eval *bgv.Evaluator, Invarian
|
||||
}
|
||||
|
||||
func (eval PolynomialEvaluator) Polynomial(input interface{}, p interface{}, targetScale rlwe.Scale) (opOut *rlwe.Ciphertext, err error) {
|
||||
return circuits.EvaluatePolynomial(eval.PolynomialEvaluator, eval, input, p, targetScale, 1, &simIntegerPolynomialEvaluator{eval.Parameters, eval.InvariantTensoring})
|
||||
|
||||
var pcircuits interface{}
|
||||
switch p := p.(type) {
|
||||
case Polynomial:
|
||||
pcircuits = circuits.Polynomial(p)
|
||||
case PolynomialVector:
|
||||
pcircuits = circuits.PolynomialVector(p)
|
||||
default:
|
||||
pcircuits = p
|
||||
}
|
||||
|
||||
return circuits.EvaluatePolynomial(eval.PolynomialEvaluator, eval, input, pcircuits, targetScale, 1, &simIntegerPolynomialEvaluator{eval.Parameters, eval.InvariantTensoring})
|
||||
}
|
||||
|
||||
type scaleInvariantEvaluator struct {
|
||||
@@ -76,7 +80,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
X := pb.Value
|
||||
|
||||
params := eval.Parameters
|
||||
slotsIndex := pol.SlotsIndex
|
||||
mapping := pol.Mapping
|
||||
slots := params.RingT().N()
|
||||
even := pol.IsEven()
|
||||
odd := pol.IsOdd()
|
||||
@@ -97,7 +101,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
}
|
||||
|
||||
// If an index slot is given (either multiply polynomials or masking)
|
||||
if slotsIndex != nil {
|
||||
if mapping != nil {
|
||||
|
||||
var toEncode bool
|
||||
|
||||
@@ -115,7 +119,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
for i, p := range pol.Value {
|
||||
if c := p.Coeffs[0].Uint64(); c != 0 {
|
||||
toEncode = true
|
||||
for _, j := range slotsIndex[i] {
|
||||
for _, j := range mapping[i] {
|
||||
values[j] = c
|
||||
}
|
||||
}
|
||||
@@ -146,7 +150,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
for i, p := range pol.Value {
|
||||
if c := p.Coeffs[0].Uint64(); c != 0 {
|
||||
toEncode = true
|
||||
for _, j := range slotsIndex[i] {
|
||||
for _, j := range mapping[i] {
|
||||
values[j] = c
|
||||
}
|
||||
}
|
||||
@@ -188,7 +192,7 @@ func (eval PolynomialEvaluator) EvaluatePolynomialVectorFromPowerBasis(targetLev
|
||||
|
||||
// Copies the coefficient on the temporary array
|
||||
// according to the slot map index
|
||||
for _, j := range slotsIndex[i] {
|
||||
for _, j := range mapping[i] {
|
||||
values[j] = c
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,8 +104,8 @@ func (eval PolynomialEvaluator) EvaluatePatersonStockmeyerPolynomialVector(pvEva
|
||||
for i := range tmp {
|
||||
|
||||
polyVec := PolynomialVector{
|
||||
Value: make([]Polynomial, nbPoly),
|
||||
SlotsIndex: poly.SlotsIndex,
|
||||
Value: make([]Polynomial, nbPoly),
|
||||
Mapping: poly.Mapping,
|
||||
}
|
||||
|
||||
// Transposes the polynomial matrix
|
||||
|
||||
@@ -134,11 +134,11 @@ func recursePS(params rlwe.ParameterProvider, logSplit, targetLevel int, p Polyn
|
||||
}
|
||||
|
||||
type PolynomialVector struct {
|
||||
Value []Polynomial
|
||||
SlotsIndex map[int][]int
|
||||
Value []Polynomial
|
||||
Mapping map[int][]int
|
||||
}
|
||||
|
||||
func NewPolynomialVector(polys []Polynomial, slotsIndex map[int][]int) (PolynomialVector, error) {
|
||||
func NewPolynomialVector(polys []bignum.Polynomial, mapping map[int][]int) (PolynomialVector, error) {
|
||||
var maxDeg int
|
||||
var basis bignum.Basis
|
||||
for i := range polys {
|
||||
@@ -158,11 +158,13 @@ func NewPolynomialVector(polys []Polynomial, slotsIndex map[int][]int) (Polynomi
|
||||
|
||||
polyvec := make([]Polynomial, len(polys))
|
||||
|
||||
copy(polyvec, polys)
|
||||
for i := range polyvec {
|
||||
polyvec[i] = NewPolynomial(polys[i])
|
||||
}
|
||||
|
||||
return PolynomialVector{
|
||||
Value: polyvec,
|
||||
SlotsIndex: slotsIndex,
|
||||
Value: polyvec,
|
||||
Mapping: mapping,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -191,12 +193,12 @@ func (p PolynomialVector) Factorize(n int) (polyq, polyr PolynomialVector) {
|
||||
coeffsq[i], coeffsr[i] = p.Factorize(n)
|
||||
}
|
||||
|
||||
return PolynomialVector{Value: coeffsq, SlotsIndex: p.SlotsIndex}, PolynomialVector{Value: coeffsr, SlotsIndex: p.SlotsIndex}
|
||||
return PolynomialVector{Value: coeffsq, Mapping: p.Mapping}, PolynomialVector{Value: coeffsr, Mapping: p.Mapping}
|
||||
}
|
||||
|
||||
type PatersonStockmeyerPolynomialVector struct {
|
||||
Value []PatersonStockmeyerPolynomial
|
||||
SlotsIndex map[int][]int
|
||||
Value []PatersonStockmeyerPolynomial
|
||||
Mapping map[int][]int
|
||||
}
|
||||
|
||||
// GetPatersonStockmeyerPolynomial returns
|
||||
@@ -207,7 +209,7 @@ func (p PolynomialVector) GetPatersonStockmeyerPolynomial(params rlwe.Parameters
|
||||
}
|
||||
|
||||
return PatersonStockmeyerPolynomialVector{
|
||||
Value: Value,
|
||||
SlotsIndex: p.SlotsIndex,
|
||||
Value: Value,
|
||||
Mapping: p.Mapping,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/circuits"
|
||||
"github.com/tuneinsight/lattigo/v4/circuits/float"
|
||||
"github.com/tuneinsight/lattigo/v4/ckks"
|
||||
"github.com/tuneinsight/lattigo/v4/rlwe"
|
||||
@@ -96,7 +95,7 @@ func chebyshevinterpolation() {
|
||||
approxG := bignum.ChebyshevApproximation(g, interval)
|
||||
|
||||
// Map storing which polynomial has to be applied to which slot.
|
||||
slotsIndex := make(map[int][]int)
|
||||
mapping := make(map[int][]int)
|
||||
|
||||
idxF := make([]int, slots>>1)
|
||||
idxG := make([]int, slots>>1)
|
||||
@@ -105,8 +104,8 @@ func chebyshevinterpolation() {
|
||||
idxG[i] = i*2 + 1 // Index with all odd slots
|
||||
}
|
||||
|
||||
slotsIndex[0] = idxF // Assigns index of all even slots to poly[0] = f(x)
|
||||
slotsIndex[1] = idxG // Assigns index of all odd slots to poly[1] = g(x)
|
||||
mapping[0] = idxF // Assigns index of all even slots to poly[0] = f(x)
|
||||
mapping[1] = idxG // Assigns index of all odd slots to poly[1] = g(x)
|
||||
|
||||
// Change of variable
|
||||
if err := evaluator.Mul(ciphertext, 2/(b-a), ciphertext); err != nil {
|
||||
@@ -121,7 +120,7 @@ func chebyshevinterpolation() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
polyVec, err := circuits.NewPolynomialVector([]circuits.Polynomial{circuits.NewPolynomial(approxF), circuits.NewPolynomial(approxG)}, slotsIndex)
|
||||
polyVec, err := float.NewPolynomialVector([]bignum.Polynomial{approxF, approxG}, mapping)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user