mirror of
https://github.com/tuneinsight/lattigo.git
synced 2025-09-13 03:27:14 +00:00
refactored examples
This commit is contained in:
@@ -1,234 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/cmplx"
|
||||
"time"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/core/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/he"
|
||||
"github.com/tuneinsight/lattigo/v4/he/hefloat"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
)
|
||||
|
||||
func example() {
|
||||
|
||||
var start time.Time
|
||||
var err error
|
||||
|
||||
// Schemes parameters are created from scratch
|
||||
params, err := hefloat.NewParametersFromLiteral(
|
||||
hefloat.ParametersLiteral{
|
||||
LogN: 14,
|
||||
LogQ: []int{55, 40, 40, 40, 40, 40, 40, 40},
|
||||
LogP: []int{45, 45},
|
||||
LogDefaultScale: 40,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println(" INSTANTIATING SCHEME ")
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
kgen := rlwe.NewKeyGenerator(params)
|
||||
|
||||
sk := kgen.GenSecretKeyNew()
|
||||
|
||||
encryptor := rlwe.NewEncryptor(params, sk)
|
||||
decryptor := rlwe.NewDecryptor(params, sk)
|
||||
encoder := hefloat.NewEncoder(params)
|
||||
evk := rlwe.NewMemEvaluationKeySet(kgen.GenRelinearizationKeyNew(sk))
|
||||
evaluator := hefloat.NewEvaluator(params, evk)
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
logSlots := params.LogMaxSlots()
|
||||
slots := 1 << logSlots
|
||||
|
||||
fmt.Println()
|
||||
fmt.Printf("Scheme parameters: logN = %d, logSlots = %d, logQP = %f, levels = %d, scale= %f, noise = %T %v \n", params.LogN(), logSlots, params.LogQP(), params.MaxLevel()+1, params.DefaultScale().Float64(), params.Xe(), params.Xe())
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println(" PLAINTEXT CREATION ")
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
r := float64(16)
|
||||
|
||||
pi := 3.141592653589793
|
||||
|
||||
values := make([]complex128, slots)
|
||||
for i := range values {
|
||||
values[i] = complex(2*pi, 0)
|
||||
}
|
||||
|
||||
plaintext := hefloat.NewPlaintext(params, params.MaxLevel())
|
||||
plaintext.Scale = plaintext.Scale.Div(rlwe.NewScale(r))
|
||||
if err := encoder.Encode(values, plaintext); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println(" ENCRYPTION ")
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
ciphertext, err := encryptor.EncryptNew(plaintext)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
printDebug(params, ciphertext, values, decryptor, encoder)
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("===============================================")
|
||||
fmt.Printf(" EVALUATION OF i*x on %d values\n", slots)
|
||||
fmt.Println("===============================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
if err := evaluator.Mul(ciphertext, 1i, ciphertext); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
for i := range values {
|
||||
values[i] *= 1i
|
||||
}
|
||||
|
||||
printDebug(params, ciphertext, values, decryptor, encoder)
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("===============================================")
|
||||
fmt.Printf(" EVALUATION of x/r on %d values\n", slots)
|
||||
fmt.Println("===============================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
ciphertext.Scale = ciphertext.Scale.Mul(rlwe.NewScale(r))
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
for i := range values {
|
||||
values[i] /= complex(r, 0)
|
||||
}
|
||||
|
||||
printDebug(params, ciphertext, values, decryptor, encoder)
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("===============================================")
|
||||
fmt.Printf(" EVALUATION of e^x on %d values\n", slots)
|
||||
fmt.Println("===============================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
coeffs := []complex128{
|
||||
1.0,
|
||||
1.0,
|
||||
1.0 / 2,
|
||||
1.0 / 6,
|
||||
1.0 / 24,
|
||||
1.0 / 120,
|
||||
1.0 / 720,
|
||||
1.0 / 5040,
|
||||
}
|
||||
|
||||
// We create a new polynomial, with the standard basis [1, x, x^2, ...], with no interval.
|
||||
poly := bignum.NewPolynomial(bignum.Monomial, coeffs, nil)
|
||||
|
||||
polyEval := hefloat.NewPolynomialEvaluator(params, evaluator)
|
||||
|
||||
if ciphertext, err = polyEval.Evaluate(ciphertext, poly, ciphertext.Scale); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
for i := range values {
|
||||
values[i] = cmplx.Exp(values[i])
|
||||
}
|
||||
|
||||
printDebug(params, ciphertext, values, decryptor, encoder)
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("===============================================")
|
||||
fmt.Printf(" EVALUATION of x^r on %d values\n", slots)
|
||||
fmt.Println("===============================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
monomialBasis := he.NewPowerBasis(ciphertext, bignum.Monomial)
|
||||
if err = monomialBasis.GenPower(int(r), false, evaluator); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ciphertext = monomialBasis.Value[int(r)]
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
for i := range values {
|
||||
values[i] = cmplx.Pow(values[i], complex(r, 0))
|
||||
}
|
||||
|
||||
printDebug(params, ciphertext, values, decryptor, encoder)
|
||||
|
||||
fmt.Println()
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println(" DECRYPTION & DECODING ")
|
||||
fmt.Println("=========================================")
|
||||
fmt.Println()
|
||||
|
||||
start = time.Now()
|
||||
|
||||
fmt.Printf("Done in %s \n", time.Since(start))
|
||||
|
||||
printDebug(params, ciphertext, values, decryptor, encoder)
|
||||
|
||||
}
|
||||
|
||||
func printDebug(params hefloat.Parameters, ciphertext *rlwe.Ciphertext, valuesWant []complex128, decryptor *rlwe.Decryptor, encoder *hefloat.Encoder) (valuesTest []complex128) {
|
||||
|
||||
valuesTest = make([]complex128, ciphertext.Slots())
|
||||
|
||||
if err := encoder.Decode(decryptor.DecryptNew(ciphertext), valuesTest); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Printf("Level: %d (logQ = %d)\n", ciphertext.Level(), params.LogQLvl(ciphertext.Level()))
|
||||
fmt.Printf("Scale: 2^%f\n", math.Log2(ciphertext.Scale.Float64()))
|
||||
fmt.Printf("ValuesTest: %6.10f %6.10f %6.10f %6.10f...\n", valuesTest[0], valuesTest[1], valuesTest[2], valuesTest[3])
|
||||
fmt.Printf("ValuesWant: %6.10f %6.10f %6.10f %6.10f...\n", valuesWant[0], valuesWant[1], valuesWant[2], valuesWant[3])
|
||||
fmt.Println()
|
||||
|
||||
precStats := hefloat.GetPrecisionStats(params, encoder, nil, valuesWant, valuesTest, 0, false)
|
||||
|
||||
fmt.Println(precStats.String())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
example()
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/core/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/he/hefloat"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/sampling"
|
||||
)
|
||||
|
||||
func chebyshevinterpolation() {
|
||||
|
||||
var err error
|
||||
|
||||
// This example packs random 8192 float64 values in the range [-8, 8]
|
||||
// and approximates the function f = 1/(exp(-x) + 1) over the range [-8, 8]
|
||||
// for the even slots and the function g = f * (1-f) over the range [-8, 8]
|
||||
// for the odd slots.
|
||||
// The result is then parsed and compared to the expected result.
|
||||
|
||||
// Scheme params are taken directly from the proposed defaults
|
||||
params, err := hefloat.NewParametersFromLiteral(
|
||||
hefloat.ParametersLiteral{
|
||||
LogN: 14,
|
||||
LogQ: []int{55, 40, 40, 40, 40, 40, 40, 40},
|
||||
LogP: []int{45, 45},
|
||||
LogDefaultScale: 40,
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
encoder := hefloat.NewEncoder(params)
|
||||
|
||||
// Keys
|
||||
kgen := rlwe.NewKeyGenerator(params)
|
||||
sk, pk := kgen.GenKeyPairNew()
|
||||
|
||||
// Encryptor
|
||||
encryptor := rlwe.NewEncryptor(params, pk)
|
||||
|
||||
// Decryptor
|
||||
decryptor := rlwe.NewDecryptor(params, sk)
|
||||
|
||||
// Evaluator with relinearization key
|
||||
evaluator := hefloat.NewEvaluator(params, rlwe.NewMemEvaluationKeySet(kgen.GenRelinearizationKeyNew(sk)))
|
||||
|
||||
// Values to encrypt
|
||||
slots := params.MaxSlots()
|
||||
values := make([]float64, slots)
|
||||
for i := range values {
|
||||
values[i] = sampling.RandFloat64(-8, 8)
|
||||
}
|
||||
|
||||
fmt.Printf("Scheme parameters: logN = %d, logQ = %f, levels = %d, scale= %f, noise = %T %v \n",
|
||||
params.LogN(), params.LogQP(), params.MaxLevel()+1, params.DefaultScale().Float64(), params.Xe(), params.Xe())
|
||||
|
||||
fmt.Println()
|
||||
fmt.Printf("Values : %6f %6f %6f %6f...\n",
|
||||
round(values[0]), round(values[1]), round(values[2]), round(values[3]))
|
||||
fmt.Println()
|
||||
|
||||
// Plaintext creation and encoding process
|
||||
plaintext := hefloat.NewPlaintext(params, params.MaxLevel())
|
||||
if err := encoder.Encode(values, plaintext); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Encryption process
|
||||
var ciphertext *rlwe.Ciphertext
|
||||
ciphertext, err = encryptor.EncryptNew(plaintext)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
a, b := -8.0, 8.0
|
||||
deg := 63
|
||||
|
||||
fmt.Printf("Evaluation of the function f(x) for even slots and g(x) for odd slots in the range [%0.2f, %0.2f] (degree of approximation: %d)\n", a, b, deg)
|
||||
|
||||
// Evaluation process
|
||||
// We approximate f(x) in the range [-8, 8] with a Chebyshev interpolant of 33 coefficients (degree 32).
|
||||
|
||||
interval := bignum.Interval{
|
||||
Nodes: deg,
|
||||
A: *new(big.Float).SetFloat64(a),
|
||||
B: *new(big.Float).SetFloat64(b),
|
||||
}
|
||||
|
||||
approxF := bignum.ChebyshevApproximation(f, interval)
|
||||
approxG := bignum.ChebyshevApproximation(g, interval)
|
||||
|
||||
// Map storing which polynomial has to be applied to which slot.
|
||||
mapping := make(map[int][]int)
|
||||
|
||||
idxF := make([]int, slots>>1)
|
||||
idxG := make([]int, slots>>1)
|
||||
for i := 0; i < slots>>1; i++ {
|
||||
idxF[i] = i * 2 // Index with all even slots
|
||||
idxG[i] = i*2 + 1 // Index with all odd slots
|
||||
}
|
||||
|
||||
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 {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := evaluator.Add(ciphertext, (-a-b)/(b-a), ciphertext); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := evaluator.Rescale(ciphertext, ciphertext); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
polyVec, err := hefloat.NewPolynomialVector([]bignum.Polynomial{approxF, approxG}, mapping)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
polyEval := hefloat.NewPolynomialEvaluator(params, evaluator)
|
||||
|
||||
// We evaluate the interpolated Chebyshev interpolant on the ciphertext
|
||||
if ciphertext, err = polyEval.Evaluate(ciphertext, polyVec, ciphertext.Scale); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println("Done... Consumed levels:", params.MaxLevel()-ciphertext.Level())
|
||||
|
||||
// Computation of the reference values
|
||||
for i := 0; i < slots>>1; i++ {
|
||||
values[i*2] = f(values[i*2])
|
||||
values[i*2+1] = g(values[i*2+1])
|
||||
}
|
||||
|
||||
// Print results and comparison
|
||||
printDebug(params, ciphertext, values, decryptor, encoder)
|
||||
|
||||
}
|
||||
|
||||
func f(x float64) float64 {
|
||||
return 1 / (math.Exp(-x) + 1)
|
||||
}
|
||||
|
||||
func g(x float64) float64 {
|
||||
return f(x) * (1 - f(x))
|
||||
}
|
||||
|
||||
func round(x float64) float64 {
|
||||
return math.Round(x*100000000) / 100000000
|
||||
}
|
||||
|
||||
func printDebug(params hefloat.Parameters, ciphertext *rlwe.Ciphertext, valuesWant []float64, decryptor *rlwe.Decryptor, encoder *hefloat.Encoder) (valuesTest []float64) {
|
||||
|
||||
valuesTest = make([]float64, 1<<ciphertext.LogDimensions.Cols)
|
||||
|
||||
if err := encoder.Decode(decryptor.DecryptNew(ciphertext), valuesTest); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
fmt.Printf("Level: %d (logQ = %d)\n", ciphertext.Level(), params.LogQLvl(ciphertext.Level()))
|
||||
fmt.Printf("Scale: 2^%f\n", math.Log2(ciphertext.Scale.Float64()))
|
||||
fmt.Printf("ValuesTest: %6.10f %6.10f %6.10f %6.10f...\n", valuesTest[0], valuesTest[1], valuesTest[2], valuesTest[3])
|
||||
fmt.Printf("ValuesWant: %6.10f %6.10f %6.10f %6.10f...\n", valuesWant[0], valuesWant[1], valuesWant[2], valuesWant[3])
|
||||
fmt.Println()
|
||||
|
||||
precStats := hefloat.GetPrecisionStats(params, encoder, nil, valuesWant, valuesTest, 0, false)
|
||||
|
||||
fmt.Println(precStats.String())
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func main() {
|
||||
chebyshevinterpolation()
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
// Package main implements an example of smooth function approximation using Chebyshev polynomial interpolation.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/core/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/he/hefloat"
|
||||
"github.com/tuneinsight/lattigo/v4/ring"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/sampling"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var params hefloat.Parameters
|
||||
|
||||
// 128-bit secure parameters enabling depth-7 circuits.
|
||||
// LogN:14, LogQP: 431.
|
||||
if params, err = hefloat.NewParametersFromLiteral(
|
||||
hefloat.ParametersLiteral{
|
||||
LogN: 14, // log2(ring degree)
|
||||
LogQ: []int{55, 45, 45, 45, 45, 45, 45, 45}, // log2(primes Q) (ciphertext modulus)
|
||||
LogP: []int{61}, // log2(primes P) (auxiliary modulus)
|
||||
LogDefaultScale: 45, // log2(scale)
|
||||
RingType: ring.ConjugateInvariant,
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Key Generator
|
||||
kgen := rlwe.NewKeyGenerator(params)
|
||||
|
||||
// Secret Key
|
||||
sk := kgen.GenSecretKeyNew()
|
||||
|
||||
// Encoder
|
||||
ecd := hefloat.NewEncoder(params)
|
||||
|
||||
// Encryptor
|
||||
enc := rlwe.NewEncryptor(params, sk)
|
||||
|
||||
// Decryptor
|
||||
dec := rlwe.NewDecryptor(params, sk)
|
||||
|
||||
// Relinearization Key
|
||||
rlk := kgen.GenRelinearizationKeyNew(sk)
|
||||
|
||||
// Evaluation Key Set with the Relinearization Key
|
||||
evk := rlwe.NewMemEvaluationKeySet(rlk)
|
||||
|
||||
// Evaluator
|
||||
eval := hefloat.NewEvaluator(params, evk)
|
||||
|
||||
// Samples values in [-K, K]
|
||||
K := 25.0
|
||||
|
||||
// Allocates a plaintext at the max level.
|
||||
pt := hefloat.NewPlaintext(params, params.MaxLevel())
|
||||
|
||||
// Vector of plaintext values
|
||||
values := make([]float64, pt.Slots())
|
||||
|
||||
// Populates the vector of plaintext values
|
||||
for i := range values {
|
||||
values[i] = sampling.RandFloat64(-K, K)
|
||||
}
|
||||
|
||||
// Encodes the vector of plaintext values
|
||||
if err = ecd.Encode(values, pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Encrypts the vector of plaintext values
|
||||
var ct *rlwe.Ciphertext
|
||||
if ct, err = enc.EncryptNew(pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sigmoid := func(x float64) (y float64) {
|
||||
return 1 / (math.Exp(-x) + 1)
|
||||
}
|
||||
|
||||
// Chebyhsev approximation of the sigmoid in the domain [-K, K] of degree 63.
|
||||
poly := hefloat.NewPolynomial(GetChebyshevPoly(K, 63, sigmoid))
|
||||
|
||||
// Instantiates the polynomial evaluator
|
||||
polyEval := hefloat.NewPolynomialEvaluator(params, eval)
|
||||
|
||||
// Retrieves the change of basis y = scalar * x + constant
|
||||
scalar, constant := poly.ChangeOfBasis()
|
||||
|
||||
// Performes the change of basis Standard -> Chebyshev
|
||||
if err := eval.Mul(ct, scalar, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := eval.Add(ct, constant, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := eval.Rescale(ct, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Evaluates the polynomial
|
||||
if ct, err = polyEval.Evaluate(ct, poly, params.DefaultScale()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allocates a vector for the reference values and
|
||||
// evaluates the same circuit on the plaintext values
|
||||
want := make([]float64, ct.Slots())
|
||||
for i := range want {
|
||||
want[i], _ = poly.Evaluate(values[i])[0].Float64()
|
||||
//want[i] = sigmoid(values[i])
|
||||
}
|
||||
|
||||
// Decrypts and print the stats about the precision.
|
||||
PrintPrecisionStats(params, ct, want, ecd, dec)
|
||||
}
|
||||
|
||||
// GetChebyshevPoly returns the Chebyshev polynomial approximation of f the
|
||||
// in the interval [-K, K] for the given degree.
|
||||
func GetChebyshevPoly(K float64, degree int, f64 func(x float64) (y float64)) bignum.Polynomial {
|
||||
|
||||
FBig := func(x *big.Float) (y *big.Float) {
|
||||
xF64, _ := x.Float64()
|
||||
return new(big.Float).SetPrec(x.Prec()).SetFloat64(f64(xF64))
|
||||
}
|
||||
|
||||
var prec uint = 128
|
||||
|
||||
interval := bignum.Interval{
|
||||
A: *bignum.NewFloat(-K, prec),
|
||||
B: *bignum.NewFloat(K, prec),
|
||||
Nodes: degree,
|
||||
}
|
||||
|
||||
// Returns the polynomial.
|
||||
return bignum.ChebyshevApproximation(FBig, interval)
|
||||
}
|
||||
|
||||
// PrintPrecisionStats decrypts, decodes and prints the precision stats of a ciphertext.
|
||||
func PrintPrecisionStats(params hefloat.Parameters, ct *rlwe.Ciphertext, want []float64, ecd *hefloat.Encoder, dec *rlwe.Decryptor) {
|
||||
|
||||
var err error
|
||||
|
||||
// Decrypts the vector of plaintext values
|
||||
pt := dec.DecryptNew(ct)
|
||||
|
||||
// Decodes the plaintext
|
||||
have := make([]float64, ct.Slots())
|
||||
if err = ecd.Decode(pt, have); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Pretty prints some values
|
||||
fmt.Printf("Have: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%20.15f ", have[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
fmt.Printf("Want: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%20.15f ", want[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
// Pretty prints the precision stats
|
||||
fmt.Println(hefloat.GetPrecisionStats(params, ecd, dec, have, want, 0, false).String())
|
||||
}
|
||||
211
examples/single_party/applications/reals_sigmoid_minimax/main.go
Normal file
211
examples/single_party/applications/reals_sigmoid_minimax/main.go
Normal file
@@ -0,0 +1,211 @@
|
||||
// Package main implements an example of smooth function approximation using minimax polynomial interpolation.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/core/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/he/hefloat"
|
||||
"github.com/tuneinsight/lattigo/v4/ring"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/sampling"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var params hefloat.Parameters
|
||||
|
||||
// 128-bit secure parameters enabling depth-7 circuits.
|
||||
// LogN:14, LogQP: 431.
|
||||
if params, err = hefloat.NewParametersFromLiteral(
|
||||
hefloat.ParametersLiteral{
|
||||
LogN: 14, // log2(ring degree)
|
||||
LogQ: []int{55, 45, 45, 45, 45, 45, 45, 45}, // log2(primes Q) (ciphertext modulus)
|
||||
LogP: []int{61}, // log2(primes P) (auxiliary modulus)
|
||||
LogDefaultScale: 45, // log2(scale)
|
||||
RingType: ring.ConjugateInvariant,
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Key Generator
|
||||
kgen := rlwe.NewKeyGenerator(params)
|
||||
|
||||
// Secret Key
|
||||
sk := kgen.GenSecretKeyNew()
|
||||
|
||||
// Encoder
|
||||
ecd := hefloat.NewEncoder(params)
|
||||
|
||||
// Encryptor
|
||||
enc := rlwe.NewEncryptor(params, sk)
|
||||
|
||||
// Decryptor
|
||||
dec := rlwe.NewDecryptor(params, sk)
|
||||
|
||||
// Relinearization Key
|
||||
rlk := kgen.GenRelinearizationKeyNew(sk)
|
||||
|
||||
// Evaluation Key Set with the Relinearization Key
|
||||
evk := rlwe.NewMemEvaluationKeySet(rlk)
|
||||
|
||||
// Evaluator
|
||||
eval := hefloat.NewEvaluator(params, evk)
|
||||
|
||||
// Samples values in [-K, K]
|
||||
K := 25.0
|
||||
|
||||
// Allocates a plaintext at the max level.
|
||||
pt := hefloat.NewPlaintext(params, params.MaxLevel())
|
||||
|
||||
// Vector of plaintext values
|
||||
values := make([]float64, pt.Slots())
|
||||
|
||||
// Populates the vector of plaintext values
|
||||
for i := range values {
|
||||
values[i] = sampling.RandFloat64(-K, K)
|
||||
}
|
||||
|
||||
// Encodes the vector of plaintext values
|
||||
if err = ecd.Encode(values, pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Encrypts the vector of plaintext values
|
||||
var ct *rlwe.Ciphertext
|
||||
if ct, err = enc.EncryptNew(pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
sigmoid := func(x float64) (y float64) {
|
||||
return 1 / (math.Exp(-x) + 1)
|
||||
}
|
||||
|
||||
// Minimax approximation of the sigmoid in the domain [-K, K] of degree 63.
|
||||
poly := hefloat.NewPolynomial(GetMinimaxPoly(K, 63, sigmoid))
|
||||
|
||||
// Instantiates the polynomial evaluator
|
||||
polyEval := hefloat.NewPolynomialEvaluator(params, eval)
|
||||
|
||||
// Retrieves the change of basis y = scalar * x + constant
|
||||
scalar, constant := poly.ChangeOfBasis()
|
||||
|
||||
// Performes the change of basis Standard -> Chebyshev
|
||||
if err := eval.Mul(ct, scalar, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := eval.Add(ct, constant, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := eval.Rescale(ct, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Evaluates the polynomial
|
||||
if ct, err = polyEval.Evaluate(ct, poly, params.DefaultScale()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allocates a vector for the reference values and
|
||||
// evaluates the same circuit on the plaintext values
|
||||
want := make([]float64, ct.Slots())
|
||||
for i := range want {
|
||||
want[i], _ = poly.Evaluate(values[i])[0].Float64()
|
||||
//want[i] = sigmoid(values[i])
|
||||
}
|
||||
|
||||
// Decrypts and print the stats about the precision.
|
||||
PrintPrecisionStats(params, ct, want, ecd, dec)
|
||||
}
|
||||
|
||||
// GetMinimaxPoly returns the minimax polynomial approximation of f the
|
||||
// in the interval [-K, K] for the given degree.
|
||||
func GetMinimaxPoly(K float64, degree int, f64 func(x float64) (y float64)) bignum.Polynomial {
|
||||
|
||||
FBig := func(x *big.Float) (y *big.Float) {
|
||||
xF64, _ := x.Float64()
|
||||
return new(big.Float).SetPrec(x.Prec()).SetFloat64(f64(xF64))
|
||||
}
|
||||
|
||||
// Bit-precision of the arbitrary precision arithmetic used by the minimax solver
|
||||
var prec uint = 160
|
||||
|
||||
// Minimax (Remez) approximation of sigmoid
|
||||
r := bignum.NewRemez(bignum.RemezParameters{
|
||||
// Function to Approximate
|
||||
Function: FBig,
|
||||
|
||||
// Polynomial basis of the approximation
|
||||
Basis: bignum.Chebyshev,
|
||||
|
||||
// Approximation in [A, B] of degree Nodes.
|
||||
Intervals: []bignum.Interval{
|
||||
{
|
||||
A: *bignum.NewFloat(-K, prec),
|
||||
B: *bignum.NewFloat(K, prec),
|
||||
Nodes: degree,
|
||||
},
|
||||
},
|
||||
|
||||
// Bit-precision of the solver
|
||||
Prec: prec,
|
||||
|
||||
// Scan step for root finding
|
||||
ScanStep: bignum.NewFloat(1/16.0, prec),
|
||||
// Optimizes the scan-step for root finding
|
||||
OptimalScanStep: true,
|
||||
})
|
||||
|
||||
// Max 10 iters, and normalized min/max error of 1e-15
|
||||
fmt.Printf("Minimax Approximation of Degree %d\n", degree)
|
||||
r.Approximate(10, 1e-15)
|
||||
fmt.Println()
|
||||
|
||||
// Shoes the coeffs with 50 decimals of precision
|
||||
fmt.Printf("Minimax Chebyshev Coefficients [%f, %f]\n", -K, K)
|
||||
r.ShowCoeffs(16)
|
||||
fmt.Println()
|
||||
|
||||
// Shows the min and max error with 50 decimals of precision
|
||||
fmt.Println("Minimax Error")
|
||||
r.ShowError(16)
|
||||
fmt.Println()
|
||||
|
||||
// Returns the polynomial.
|
||||
return bignum.NewPolynomial(bignum.Chebyshev, r.Coeffs, [2]float64{-K, K})
|
||||
}
|
||||
|
||||
// PrintPrecisionStats decrypts, decodes and prints the precision stats of a ciphertext.
|
||||
func PrintPrecisionStats(params hefloat.Parameters, ct *rlwe.Ciphertext, want []float64, ecd *hefloat.Encoder, dec *rlwe.Decryptor) {
|
||||
|
||||
var err error
|
||||
|
||||
// Decrypts the vector of plaintext values
|
||||
pt := dec.DecryptNew(ct)
|
||||
|
||||
// Decodes the plaintext
|
||||
have := make([]float64, ct.Slots())
|
||||
if err = ecd.Decode(pt, have); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Pretty prints some values
|
||||
fmt.Printf("Have: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%20.15f ", have[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
fmt.Printf("Want: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%20.15f ", want[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
// Pretty prints the precision stats
|
||||
fmt.Println(hefloat.GetPrecisionStats(params, ecd, dec, have, want, 0, false).String())
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
// Package main implements an example of vectorized polynomial evaluation.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/core/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/he/hefloat"
|
||||
"github.com/tuneinsight/lattigo/v4/ring"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/sampling"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var params hefloat.Parameters
|
||||
|
||||
// 128-bit secure parameters enabling depth-7 circuits.
|
||||
// LogN:14, LogQP: 431.
|
||||
if params, err = hefloat.NewParametersFromLiteral(
|
||||
hefloat.ParametersLiteral{
|
||||
LogN: 14, // log2(ring degree)
|
||||
LogQ: []int{55, 45, 45, 45, 45, 45, 45, 45}, // log2(primes Q) (ciphertext modulus)
|
||||
LogP: []int{61}, // log2(primes P) (auxiliary modulus)
|
||||
LogDefaultScale: 45, // log2(scale)
|
||||
RingType: ring.ConjugateInvariant,
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Key Generator
|
||||
kgen := rlwe.NewKeyGenerator(params)
|
||||
|
||||
// Secret Key
|
||||
sk := kgen.GenSecretKeyNew()
|
||||
|
||||
// Encoder
|
||||
ecd := hefloat.NewEncoder(params)
|
||||
|
||||
// Encryptor
|
||||
enc := rlwe.NewEncryptor(params, sk)
|
||||
|
||||
// Decryptor
|
||||
dec := rlwe.NewDecryptor(params, sk)
|
||||
|
||||
// Relinearization Key
|
||||
rlk := kgen.GenRelinearizationKeyNew(sk)
|
||||
|
||||
// Evaluation Key Set with the Relinearization Key
|
||||
evk := rlwe.NewMemEvaluationKeySet(rlk)
|
||||
|
||||
// Evaluator
|
||||
eval := hefloat.NewEvaluator(params, evk)
|
||||
|
||||
// Samples values in [-K, K]
|
||||
K := 25.0
|
||||
|
||||
// Allocates a plaintext at the max level.
|
||||
pt := hefloat.NewPlaintext(params, params.MaxLevel())
|
||||
|
||||
// Vector of plaintext values
|
||||
values := make([]float64, pt.Slots())
|
||||
|
||||
// Populates the vector of plaintext values
|
||||
for i := range values {
|
||||
values[i] = sampling.RandFloat64(-K, K)
|
||||
}
|
||||
|
||||
// Encodes the vector of plaintext values
|
||||
if err = ecd.Encode(values, pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Encrypts the vector of plaintext values
|
||||
var ct *rlwe.Ciphertext
|
||||
if ct, err = enc.EncryptNew(pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// f(x)
|
||||
sigmoid := func(x float64) (y float64) {
|
||||
return 1 / (math.Exp(-x) + 1)
|
||||
}
|
||||
|
||||
// g0(x) = f'(x) * (f(x)-0)
|
||||
g0 := func(x float64) (y float64) {
|
||||
y = sigmoid(x)
|
||||
return y * (1 - y) * (y - 0)
|
||||
}
|
||||
|
||||
// g1(x) = f'(x) * (f(x)-1)
|
||||
g1 := func(x float64) (y float64) {
|
||||
y = sigmoid(x)
|
||||
return y * (1 - y) * (y - 1)
|
||||
}
|
||||
|
||||
// Defines on which slots g0(x) and g1(x) have to be evaluated
|
||||
even := make([]int, ct.Slots()>>1) // List of all even slots
|
||||
odd := make([]int, ct.Slots()>>1) // List of all odd slots
|
||||
for i := 0; i < ct.Slots()>>1; i++ {
|
||||
even[i] = 2 * i
|
||||
odd[i] = 2*i + 1
|
||||
}
|
||||
|
||||
mapping := map[int][]int{
|
||||
0: even, // g0(x) is evaluated on all even slots
|
||||
1: odd, // g1(x) is evaluated on all odd slots
|
||||
}
|
||||
|
||||
// Vectorized Chebyhsev approximation of g0(x) and g1(x) in the domain [-K, K] of degree 63.
|
||||
var polys hefloat.PolynomialVector
|
||||
if polys, err = hefloat.NewPolynomialVector([]bignum.Polynomial{
|
||||
GetChebyshevPoly(K, 63, g0),
|
||||
GetChebyshevPoly(K, 63, g1),
|
||||
}, mapping); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Instantiates the polynomial evaluator
|
||||
polyEval := hefloat.NewPolynomialEvaluator(params, eval)
|
||||
|
||||
// Retrieves the vectorized change of basis y = scalar * x + constant
|
||||
scalar, constant := polys.ChangeOfBasis(ct.Slots())
|
||||
|
||||
// Performes the vectorized change of basis Standard -> Chebyshev
|
||||
if err := eval.Mul(ct, scalar, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := eval.Add(ct, constant, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := eval.Rescale(ct, ct); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Evaluates the vectorized polynomial
|
||||
if ct, err = polyEval.Evaluate(ct, polys, params.DefaultScale()); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allocates a vector for the reference values
|
||||
want := make([]float64, ct.Slots())
|
||||
for i := 0; i < ct.Slots()>>1; i++ {
|
||||
want[2*i+0], _ = polys.Value[0].Evaluate(values[2*i+0])[0].Float64()
|
||||
want[2*i+1], _ = polys.Value[1].Evaluate(values[2*i+1])[0].Float64()
|
||||
//want[2*i+0] = sigmoidDerivLabel0(values[2*i+0])
|
||||
//want[2*i+1] = sigmoidDerivLabel1(values[2*i+1])
|
||||
}
|
||||
|
||||
// Decrypts and print the stats about the precision.
|
||||
PrintPrecisionStats(params, ct, want, ecd, dec)
|
||||
}
|
||||
|
||||
// GetChebyshevPoly returns the Chebyshev polynomial approximation of f the
|
||||
// in the interval [-K, K] for the given degree.
|
||||
func GetChebyshevPoly(K float64, degree int, f64 func(x float64) (y float64)) bignum.Polynomial {
|
||||
|
||||
FBig := func(x *big.Float) (y *big.Float) {
|
||||
xF64, _ := x.Float64()
|
||||
return new(big.Float).SetPrec(x.Prec()).SetFloat64(f64(xF64))
|
||||
}
|
||||
|
||||
var prec uint = 128
|
||||
|
||||
interval := bignum.Interval{
|
||||
A: *bignum.NewFloat(-K, prec),
|
||||
B: *bignum.NewFloat(K, prec),
|
||||
Nodes: degree,
|
||||
}
|
||||
|
||||
// Returns the polynomial.
|
||||
return bignum.ChebyshevApproximation(FBig, interval)
|
||||
}
|
||||
|
||||
// PrintPrecisionStats decrypts, decodes and prints the precision stats of a ciphertext.
|
||||
func PrintPrecisionStats(params hefloat.Parameters, ct *rlwe.Ciphertext, want []float64, ecd *hefloat.Encoder, dec *rlwe.Decryptor) {
|
||||
|
||||
var err error
|
||||
|
||||
// Decrypts the vector of plaintext values
|
||||
pt := dec.DecryptNew(ct)
|
||||
|
||||
// Decodes the plaintext
|
||||
have := make([]float64, ct.Slots())
|
||||
if err = ecd.Decode(pt, have); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Pretty prints some values
|
||||
fmt.Printf("Have: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%20.15f ", have[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
fmt.Printf("Want: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%20.15f ", want[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
// Pretty prints the precision stats
|
||||
fmt.Println(hefloat.GetPrecisionStats(params, ecd, dec, have, want, 0, false).String())
|
||||
}
|
||||
111
examples/single_party/templates/int/main.go
Normal file
111
examples/single_party/templates/int/main.go
Normal file
@@ -0,0 +1,111 @@
|
||||
// Package main is a template encrypted modular arithmetic integers, with a set of example parameters, key generation, encoding, encryption, decryption and decoding.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/core/rlwe"
|
||||
"github.com/tuneinsight/lattigo/v4/he/heint"
|
||||
"github.com/tuneinsight/lattigo/v4/utils"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
var params heint.Parameters
|
||||
|
||||
// 128-bit secure parameters enabling depth-7 circuits.
|
||||
// LogN:14, LogQP: 431.
|
||||
if params, err = heint.NewParametersFromLiteral(
|
||||
heint.ParametersLiteral{
|
||||
LogN: 14, // log2(ring degree)
|
||||
LogQ: []int{55, 45, 45, 45, 45, 45, 45, 45}, // log2(primes Q) (ciphertext modulus)
|
||||
LogP: []int{61}, // log2(primes P) (auxiliary modulus)
|
||||
PlaintextModulus: 0x10001, // log2(scale)
|
||||
}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Key Generator
|
||||
kgen := rlwe.NewKeyGenerator(params)
|
||||
|
||||
// Secret Key
|
||||
sk := kgen.GenSecretKeyNew()
|
||||
|
||||
// Encoder
|
||||
ecd := heint.NewEncoder(params)
|
||||
|
||||
// Encryptor
|
||||
enc := rlwe.NewEncryptor(params, sk)
|
||||
|
||||
// Decryptor
|
||||
dec := rlwe.NewDecryptor(params, sk)
|
||||
|
||||
// Vector of plaintext values
|
||||
values := make([]uint64, params.MaxSlots())
|
||||
|
||||
// Source for sampling random plaintext values (not cryptographically secure)
|
||||
/* #nosec G404 */
|
||||
r := rand.New(rand.NewSource(0))
|
||||
|
||||
// Populates the vector of plaintext values
|
||||
T := params.PlaintextModulus()
|
||||
for i := range values {
|
||||
values[i] = r.Uint64() % T
|
||||
}
|
||||
|
||||
// Allocates a plaintext at the max level.
|
||||
// Default rlwe.MetaData:
|
||||
// - IsBatched = true (slots encoding)
|
||||
// - Scale = params.DefaultScale()
|
||||
pt := heint.NewPlaintext(params, params.MaxLevel())
|
||||
|
||||
// Encodes the vector of plaintext values
|
||||
if err = ecd.Encode(values, pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Encrypts the vector of plaintext values
|
||||
var ct *rlwe.Ciphertext
|
||||
if ct, err = enc.EncryptNew(pt); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Allocates a vector for the reference values
|
||||
want := make([]uint64, params.MaxSlots())
|
||||
copy(want, values)
|
||||
|
||||
PrintPrecisionStats(params, ct, want, ecd, dec)
|
||||
}
|
||||
|
||||
// PrintPrecisionStats decrypts, decodes and prints the precision stats of a ciphertext.
|
||||
func PrintPrecisionStats(params heint.Parameters, ct *rlwe.Ciphertext, want []uint64, ecd *heint.Encoder, dec *rlwe.Decryptor) {
|
||||
|
||||
var err error
|
||||
|
||||
// Decrypts the vector of plaintext values
|
||||
pt := dec.DecryptNew(ct)
|
||||
|
||||
// Decodes the plaintext
|
||||
have := make([]uint64, params.MaxSlots())
|
||||
if err = ecd.Decode(pt, have); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Pretty prints some values
|
||||
fmt.Printf("Have: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%d ", have[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
fmt.Printf("Want: ")
|
||||
for i := 0; i < 4; i++ {
|
||||
fmt.Printf("%d ", want[i])
|
||||
}
|
||||
fmt.Printf("...\n")
|
||||
|
||||
if !utils.EqualSlice(want, have) {
|
||||
panic("wrong result: bad decryption or encrypted/plaintext circuits do not match")
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ func main() {
|
||||
var params hefloat.Parameters
|
||||
|
||||
// 128-bit secure parameters enabling depth-7 circuits.
|
||||
// LogN:14, LogQP: 431.
|
||||
if params, err = hefloat.NewParametersFromLiteral(
|
||||
hefloat.ParametersLiteral{
|
||||
LogN: 14, // log2(ring degree)
|
||||
10
examples/single_party/templates/reals/main_test.go
Normal file
10
examples/single_party/templates/reals/main_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipped in -short mode")
|
||||
}
|
||||
main()
|
||||
}
|
||||
10
examples/single_party/tutorials/reals/main_test.go
Normal file
10
examples/single_party/tutorials/reals/main_test.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestMain(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipped in -short mode")
|
||||
}
|
||||
main()
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
package hefloat
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/tuneinsight/lattigo/v4/he"
|
||||
"github.com/tuneinsight/lattigo/v4/utils/bignum"
|
||||
)
|
||||
@@ -29,3 +31,25 @@ func NewPolynomialVector(polys []bignum.Polynomial, mapping map[int][]int) (Poly
|
||||
p, err := he.NewPolynomialVector(polys, mapping)
|
||||
return PolynomialVector(p), err
|
||||
}
|
||||
|
||||
func (p PolynomialVector) ChangeOfBasis(slots int) (scalar, constant []*big.Float) {
|
||||
|
||||
scalar = make([]*big.Float, slots)
|
||||
constant = make([]*big.Float, slots)
|
||||
|
||||
for i := 0; i < slots; i++ {
|
||||
scalar[i] = new(big.Float)
|
||||
constant[i] = new(big.Float)
|
||||
}
|
||||
|
||||
for i := range p.Mapping {
|
||||
m := p.Mapping[i]
|
||||
s, c := p.Value[i].ChangeOfBasis()
|
||||
for _, j := range m {
|
||||
scalar[j] = s
|
||||
constant[j] = c
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user