Skip to content

Commit

Permalink
feat: Add ManyLUTParameters
Browse files Browse the repository at this point in the history
  • Loading branch information
sp301415 committed Jan 2, 2025
1 parent f67d570 commit eade093
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 175 deletions.
94 changes: 47 additions & 47 deletions xtfhe/manylut_bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
//
// Panics if len(f) > LUTCount.
func (e *ManyLUTEvaluator[T]) GenLookUpTable(f []func(int) int) tfhe.LookUpTable[T] {
lutOut := tfhe.NewLookUpTable(e.Parameters)
lutOut := tfhe.NewLookUpTable(e.Parameters.baseParameters)
e.GenLookUpTableAssign(f, lutOut)
return lutOut
}
Expand All @@ -21,15 +21,15 @@ func (e *ManyLUTEvaluator[T]) GenLookUpTable(f []func(int) int) tfhe.LookUpTable
//
// Panics if len(f) > LUTCount.
func (e *ManyLUTEvaluator[T]) GenLookUpTableAssign(f []func(int) int, lutOut tfhe.LookUpTable[T]) {
e.GenLookUpTableCustomAssign(f, e.Parameters.MessageModulus(), e.Parameters.Scale(), lutOut)
e.GenLookUpTableCustomAssign(f, e.Parameters.baseParameters.MessageModulus(), e.Parameters.baseParameters.Scale(), lutOut)
}

// GenLookUpTableFull generates a lookup table based on function f.
// Output of f is encoded as-is.
//
// Panics if len(f) > LUTCount.
func (e *ManyLUTEvaluator[T]) GenLookUpTableFull(f []func(int) T) tfhe.LookUpTable[T] {
lutOut := tfhe.NewLookUpTable(e.Parameters)
lutOut := tfhe.NewLookUpTable(e.Parameters.baseParameters)
e.GenLookUpTableFullAssign(f, lutOut)
return lutOut
}
Expand All @@ -39,15 +39,15 @@ func (e *ManyLUTEvaluator[T]) GenLookUpTableFull(f []func(int) T) tfhe.LookUpTab
//
// Panics if len(f) > LUTCount.
func (e *ManyLUTEvaluator[T]) GenLookUpTableFullAssign(f []func(int) T, lutOut tfhe.LookUpTable[T]) {
e.GenLookUpTableFullCustomAssign(f, e.Parameters.MessageModulus(), lutOut)
e.GenLookUpTableFullCustomAssign(f, e.Parameters.baseParameters.MessageModulus(), lutOut)
}

// GenLookUpTableCustom generates a lookup table based on function f using custom messageModulus and scale.
// Input and output of f is cut by messageModulus.
//
// Panics if len(f) > LUTCount.
func (e *ManyLUTEvaluator[T]) GenLookUpTableCustom(f []func(int) int, messageModulus, scale T) tfhe.LookUpTable[T] {
lutOut := tfhe.NewLookUpTable(e.Parameters)
lutOut := tfhe.NewLookUpTable(e.Parameters.baseParameters)
e.GenLookUpTableCustomAssign(f, messageModulus, scale, lutOut)
return lutOut
}
Expand All @@ -70,7 +70,7 @@ func (e *ManyLUTEvaluator[T]) GenLookUpTableCustomAssign(f []func(int) int, mess
//
// Panics if len(f) > LUTCount.
func (e *ManyLUTEvaluator[T]) GenLookUpTableFullCustom(f []func(int) T, messageModulus, scale T) tfhe.LookUpTable[T] {
lutOut := tfhe.NewLookUpTable(e.Parameters)
lutOut := tfhe.NewLookUpTable(e.Parameters.baseParameters)
e.GenLookUpTableFullAssign(f, lutOut)
return lutOut
}
Expand All @@ -80,28 +80,28 @@ func (e *ManyLUTEvaluator[T]) GenLookUpTableFullCustom(f []func(int) T, messageM
//
// Panics if len(f) > LUTCount.
func (e *ManyLUTEvaluator[T]) GenLookUpTableFullCustomAssign(f []func(int) T, messageModulus T, lutOut tfhe.LookUpTable[T]) {
if len(f) > e.LUTCount() {
if len(f) > e.Parameters.lutCount {
panic("Number of functions exceeds LUTCount")
}

y := make([]T, e.lutCount)
y := make([]T, e.Parameters.lutCount)

for x := 0; x < int(messageModulus); x++ {
start := num.DivRound(x*e.Parameters.LookUpTableSize(), int(messageModulus))
end := num.DivRound((x+1)*e.Parameters.LookUpTableSize(), int(messageModulus))
start := num.DivRound(x*e.Parameters.baseParameters.LookUpTableSize(), int(messageModulus))
end := num.DivRound((x+1)*e.Parameters.baseParameters.LookUpTableSize(), int(messageModulus))
for i := range f {
y[i] = f[i](x)
}
for xx := start; xx < end; xx += e.lutCount {
for i := 0; i < e.lutCount; i++ {
for xx := start; xx < end; xx += e.Parameters.lutCount {
for i := 0; i < e.Parameters.lutCount; i++ {
lutOut.Value[xx+i] = y[i]
}
}
}

offset := num.DivRound(e.Parameters.LookUpTableSize(), int(2*messageModulus))
offset := num.DivRound(e.Parameters.baseParameters.LookUpTableSize(), int(2*messageModulus))
vec.RotateInPlace(lutOut.Value, -offset)
for i := e.Parameters.LookUpTableSize() - offset; i < e.Parameters.LookUpTableSize(); i++ {
for i := e.Parameters.baseParameters.LookUpTableSize() - offset; i < e.Parameters.baseParameters.LookUpTableSize(); i++ {
lutOut.Value[i] = -lutOut.Value[i]
}
}
Expand All @@ -126,9 +126,9 @@ func (e *ManyLUTEvaluator[T]) BootstrapFuncAssign(ct tfhe.LWECiphertext[T], f []

// BootstrapLUT returns a bootstrapped LWE ciphertext with respect to given LUT.
func (e *ManyLUTEvaluator[T]) BootstrapLUT(ct tfhe.LWECiphertext[T], lut tfhe.LookUpTable[T]) []tfhe.LWECiphertext[T] {
ctOut := make([]tfhe.LWECiphertext[T], e.lutCount)
for i := 0; i < e.lutCount; i++ {
ctOut[i] = tfhe.NewLWECiphertext(e.Parameters)
ctOut := make([]tfhe.LWECiphertext[T], e.Parameters.lutCount)
for i := 0; i < e.Parameters.lutCount; i++ {
ctOut[i] = tfhe.NewLWECiphertext(e.Parameters.baseParameters)
}
e.BootstrapLUTAssign(ct, lut, ctOut)
return ctOut
Expand All @@ -139,16 +139,16 @@ func (e *ManyLUTEvaluator[T]) BootstrapLUT(ct tfhe.LWECiphertext[T], lut tfhe.Lo
// If len(ctOut) > LUTCount, only the first LUTCount elements are written.
// Panics if len(ctOut) < LUTCount.
func (e *ManyLUTEvaluator[T]) BootstrapLUTAssign(ct tfhe.LWECiphertext[T], lut tfhe.LookUpTable[T], ctOut []tfhe.LWECiphertext[T]) {
switch e.Parameters.BootstrapOrder() {
switch e.Parameters.baseParameters.BootstrapOrder() {
case tfhe.OrderKeySwitchBlindRotate:
e.KeySwitchForBootstrapAssign(ct, e.buffer.ctKeySwitchForBootstrap)
e.BlindRotateAssign(e.buffer.ctKeySwitchForBootstrap, lut, e.buffer.ctRotate)
for i := 0; i < e.lutCount; i++ {
for i := 0; i < e.Parameters.lutCount; i++ {
e.buffer.ctRotate.ToLWECiphertextAssign(i, ctOut[i])
}
case tfhe.OrderBlindRotateKeySwitch:
e.BlindRotateAssign(ct, lut, e.buffer.ctRotate)
for i := 0; i < e.lutCount; i++ {
for i := 0; i < e.Parameters.lutCount; i++ {
e.buffer.ctRotate.ToLWECiphertextAssign(i, e.buffer.ctExtract)
e.KeySwitchForBootstrapAssign(e.buffer.ctExtract, ctOut[i])
}
Expand All @@ -157,20 +157,20 @@ func (e *ManyLUTEvaluator[T]) BootstrapLUTAssign(ct tfhe.LWECiphertext[T], lut t

// ModSwitch switches the modulus of x from Q to 2 * LookUpTableSize.
func (e *ManyLUTEvaluator[T]) ModSwitch(x T) int {
return int(num.DivRoundBits(x, e.Parameters.LogQ()-e.Parameters.LogPolyDegree()-1+e.logLUTCount) << e.logLUTCount)
return int(num.DivRoundBits(x, e.Parameters.baseParameters.LogQ()-e.Parameters.baseParameters.LogPolyDegree()-1+e.Parameters.logLUTCount) << e.Parameters.logLUTCount)
}

// BlindRotate returns the blind rotation of LWE ciphertext with respect to LUT.
func (e *ManyLUTEvaluator[T]) BlindRotate(ct tfhe.LWECiphertext[T], lut tfhe.LookUpTable[T]) tfhe.GLWECiphertext[T] {
ctOut := tfhe.NewGLWECiphertext(e.Parameters)
ctOut := tfhe.NewGLWECiphertext(e.Parameters.baseParameters)
e.BlindRotateAssign(ct, lut, ctOut)
return ctOut
}

// BlindRotateAssign computes the blind rotation of LWE ciphertext with respect to LUT, and writes it to ctOut.
func (e *ManyLUTEvaluator[T]) BlindRotateAssign(ct tfhe.LWECiphertext[T], lut tfhe.LookUpTable[T], ctOut tfhe.GLWECiphertext[T]) {
switch {
case e.Parameters.BlockSize() > 1:
case e.Parameters.baseParameters.BlockSize() > 1:
e.blindRotateBlockAssign(ct, lut, ctOut)
default:
e.blindRotateOriginalAssign(ct, lut, ctOut)
Expand All @@ -180,50 +180,50 @@ func (e *ManyLUTEvaluator[T]) BlindRotateAssign(ct tfhe.LWECiphertext[T], lut tf
// blindRotateBlockAssign computes the blind rotation when PolyDegree = LookUpTableSize and BlockSize > 1.
// This is equivalent to the blind rotation algorithm using block binary keys, as explained in https://eprint.iacr.org/2023/958.
func (e *ManyLUTEvaluator[T]) blindRotateBlockAssign(ct tfhe.LWECiphertext[T], lut tfhe.LookUpTable[T], ctOut tfhe.GLWECiphertext[T]) {
polyDecomposed := e.Decomposer.PolyDecomposedBuffer(e.Parameters.BlindRotateParameters())
polyDecomposed := e.Decomposer.PolyDecomposedBuffer(e.Parameters.baseParameters.BlindRotateParameters())

vec.CopyAssign(lut.Value, ctOut.Value[0].Coeffs)
e.PolyEvaluator.MonomialMulPolyInPlace(ctOut.Value[0], -e.ModSwitch(ct.Value[0]))
for i := 1; i < e.Parameters.GLWERank()+1; i++ {
for i := 1; i < e.Parameters.baseParameters.GLWERank()+1; i++ {
ctOut.Value[i].Clear()
}

e.Decomposer.DecomposePolyAssign(ctOut.Value[0], e.Parameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.BlindRotateParameters().Level(); k++ {
e.Decomposer.DecomposePolyAssign(ctOut.Value[0], e.Parameters.baseParameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.baseParameters.BlindRotateParameters().Level(); k++ {
e.PolyEvaluator.ToFourierPolyAssign(polyDecomposed[k], e.buffer.ctAccFourierDecomposed[0][k])
}

e.GadgetProductFourierDecomposedFourierGLWEAssign(e.EvaluationKey.BlindRotateKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc)
e.PolyEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[1]), e.buffer.fMono)
e.FourierPolyMulFourierGLWEAssign(e.buffer.ctBlockFourierAcc, e.buffer.fMono, e.buffer.ctFourierAcc)
for j := 1; j < e.Parameters.BlockSize(); j++ {
for j := 1; j < e.Parameters.baseParameters.BlockSize(); j++ {
e.GadgetProductFourierDecomposedFourierGLWEAssign(e.EvaluationKey.BlindRotateKey.Value[j].Value[0], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc)
e.PolyEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[j+1]), e.buffer.fMono)
e.FourierPolyMulAddFourierGLWEAssign(e.buffer.ctBlockFourierAcc, e.buffer.fMono, e.buffer.ctFourierAcc)
}

for j := 0; j < e.Parameters.GLWERank()+1; j++ {
for j := 0; j < e.Parameters.baseParameters.GLWERank()+1; j++ {
e.PolyEvaluator.ToPolyAddAssignUnsafe(e.buffer.ctFourierAcc.Value[j], ctOut.Value[j])
}

for i := 1; i < e.Parameters.BlockCount(); i++ {
for j := 0; j < e.Parameters.GLWERank()+1; j++ {
e.Decomposer.DecomposePolyAssign(ctOut.Value[j], e.Parameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.BlindRotateParameters().Level(); k++ {
for i := 1; i < e.Parameters.baseParameters.BlockCount(); i++ {
for j := 0; j < e.Parameters.baseParameters.GLWERank()+1; j++ {
e.Decomposer.DecomposePolyAssign(ctOut.Value[j], e.Parameters.baseParameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.baseParameters.BlindRotateParameters().Level(); k++ {
e.PolyEvaluator.ToFourierPolyAssign(polyDecomposed[k], e.buffer.ctAccFourierDecomposed[j][k])
}
}

e.ExternalProductFourierDecomposedFourierGLWEAssign(e.EvaluationKey.BlindRotateKey.Value[i*e.Parameters.BlockSize()], e.buffer.ctAccFourierDecomposed, e.buffer.ctBlockFourierAcc)
e.PolyEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[i*e.Parameters.BlockSize()+1]), e.buffer.fMono)
e.ExternalProductFourierDecomposedFourierGLWEAssign(e.EvaluationKey.BlindRotateKey.Value[i*e.Parameters.baseParameters.BlockSize()], e.buffer.ctAccFourierDecomposed, e.buffer.ctBlockFourierAcc)
e.PolyEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[i*e.Parameters.baseParameters.BlockSize()+1]), e.buffer.fMono)
e.FourierPolyMulFourierGLWEAssign(e.buffer.ctBlockFourierAcc, e.buffer.fMono, e.buffer.ctFourierAcc)
for j := i*e.Parameters.BlockSize() + 1; j < (i+1)*e.Parameters.BlockSize(); j++ {
for j := i*e.Parameters.baseParameters.BlockSize() + 1; j < (i+1)*e.Parameters.baseParameters.BlockSize(); j++ {
e.ExternalProductFourierDecomposedFourierGLWEAssign(e.EvaluationKey.BlindRotateKey.Value[j], e.buffer.ctAccFourierDecomposed, e.buffer.ctBlockFourierAcc)
e.PolyEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[j+1]), e.buffer.fMono)
e.FourierPolyMulAddFourierGLWEAssign(e.buffer.ctBlockFourierAcc, e.buffer.fMono, e.buffer.ctFourierAcc)
}

for j := 0; j < e.Parameters.GLWERank()+1; j++ {
for j := 0; j < e.Parameters.baseParameters.GLWERank()+1; j++ {
e.PolyEvaluator.ToPolyAddAssignUnsafe(e.buffer.ctFourierAcc.Value[j], ctOut.Value[j])
}
}
Expand All @@ -232,30 +232,30 @@ func (e *ManyLUTEvaluator[T]) blindRotateBlockAssign(ct tfhe.LWECiphertext[T], l
// blindRotateOriginalAssign computes the blind rotation when PolyDegree = LookUpTableSize and BlockSize = 1.
// This is equivalent to the original blind rotation algorithm.
func (e *ManyLUTEvaluator[T]) blindRotateOriginalAssign(ct tfhe.LWECiphertext[T], lut tfhe.LookUpTable[T], ctOut tfhe.GLWECiphertext[T]) {
polyDecomposed := e.Decomposer.PolyDecomposedBuffer(e.Parameters.BlindRotateParameters())
polyDecomposed := e.Decomposer.PolyDecomposedBuffer(e.Parameters.baseParameters.BlindRotateParameters())

vec.CopyAssign(lut.Value, ctOut.Value[0].Coeffs)
e.PolyEvaluator.MonomialMulPolyInPlace(ctOut.Value[0], -e.ModSwitch(ct.Value[0]))
for i := 1; i < e.Parameters.GLWERank()+1; i++ {
for i := 1; i < e.Parameters.baseParameters.GLWERank()+1; i++ {
ctOut.Value[i].Clear()
}

e.Decomposer.DecomposePolyAssign(ctOut.Value[0], e.Parameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.BlindRotateParameters().Level(); k++ {
e.Decomposer.DecomposePolyAssign(ctOut.Value[0], e.Parameters.baseParameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.baseParameters.BlindRotateParameters().Level(); k++ {
e.PolyEvaluator.ToFourierPolyAssign(polyDecomposed[k], e.buffer.ctAccFourierDecomposed[0][k])
}

e.GadgetProductFourierDecomposedFourierGLWEAssign(e.EvaluationKey.BlindRotateKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctFourierAcc)
e.PolyEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[1]), e.buffer.fMono)
e.FourierPolyMulFourierGLWEAssign(e.buffer.ctFourierAcc, e.buffer.fMono, e.buffer.ctFourierAcc)
for j := 0; j < e.Parameters.GLWERank()+1; j++ {
for j := 0; j < e.Parameters.baseParameters.GLWERank()+1; j++ {
e.PolyEvaluator.ToPolyAddAssignUnsafe(e.buffer.ctFourierAcc.Value[j], ctOut.Value[j])
}

for i := 1; i < e.Parameters.LWEDimension(); i++ {
for j := 0; j < e.Parameters.GLWERank()+1; j++ {
e.Decomposer.DecomposePolyAssign(ctOut.Value[j], e.Parameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.BlindRotateParameters().Level(); k++ {
for i := 1; i < e.Parameters.baseParameters.LWEDimension(); i++ {
for j := 0; j < e.Parameters.baseParameters.GLWERank()+1; j++ {
e.Decomposer.DecomposePolyAssign(ctOut.Value[j], e.Parameters.baseParameters.BlindRotateParameters(), polyDecomposed)
for k := 0; k < e.Parameters.baseParameters.BlindRotateParameters().Level(); k++ {
e.PolyEvaluator.ToFourierPolyAssign(polyDecomposed[k], e.buffer.ctAccFourierDecomposed[j][k])
}
}
Expand All @@ -264,7 +264,7 @@ func (e *ManyLUTEvaluator[T]) blindRotateOriginalAssign(ct tfhe.LWECiphertext[T]
e.PolyEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[i+1]), e.buffer.fMono)
e.FourierPolyMulFourierGLWEAssign(e.buffer.ctFourierAcc, e.buffer.fMono, e.buffer.ctFourierAcc)

for j := 0; j < e.Parameters.GLWERank()+1; j++ {
for j := 0; j < e.Parameters.baseParameters.GLWERank()+1; j++ {
e.PolyEvaluator.ToPolyAddAssignUnsafe(e.buffer.ctFourierAcc.Value[j], ctOut.Value[j])
}
}
Expand Down
62 changes: 22 additions & 40 deletions xtfhe/manylut_evaluator.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
package xtfhe

import (
"github.com/sp301415/tfhe-go/math/num"
"github.com/sp301415/tfhe-go/math/poly"
"github.com/sp301415/tfhe-go/tfhe"
)

// ManyLUTEvaluator wraps around [tfhe.Evaluator], and implements PBSManyLUT algorithm.
// For more details, see https://eprint.iacr.org/2021/729.
type ManyLUTEvaluator[T tfhe.TorusInt] struct {
// Evaluator is an embedded Evaluator for this ManyLUTEvaluator.
*tfhe.Evaluator[T]

// lutCount is the number of LUTs to evaluate at once.
lutCount int
// logLUTCount equals log2(lutCount).
logLUTCount int
// Parameters is the parameters for this ManyLUTEvaluator.
Parameters ManyLUTParameters[T]

// buffer is the buffer values for this ManyLUTEvaluator.
buffer manyLUTEvaluationBuffer[T]
Expand Down Expand Up @@ -43,62 +41,46 @@ type manyLUTEvaluationBuffer[T tfhe.TorusInt] struct {
}

// NewManyLUTEvaluator creates a new ManyLUTEvaluator.
//
// Panics when PolyDegree does not equal LookUpTableSize,
// or when lutCount is not a power of 2.
func NewManyLUTEvaluator[T tfhe.TorusInt](params tfhe.Parameters[T], lutCount int, evk tfhe.EvaluationKey[T]) *ManyLUTEvaluator[T] {
switch {
case params.PolyDegree() != params.LookUpTableSize():
panic("PolyDegree must equal LookUpTableSize")
case !num.IsPowerOfTwo(lutCount):
panic("lutCount not power of two")
}

func NewManyLUTEvaluator[T tfhe.TorusInt](params ManyLUTParameters[T], evk tfhe.EvaluationKey[T]) *ManyLUTEvaluator[T] {
return &ManyLUTEvaluator[T]{
Evaluator: tfhe.NewEvaluator(params, evk),
Evaluator: tfhe.NewEvaluator(params.baseParameters, evk),

lutCount: lutCount,
logLUTCount: num.Log2(lutCount),
Parameters: params,

buffer: newManyLUTEvaluationBuffer(params),
}
}

// newManyLUTEvaluationBuffer creates a new manyLUTEvaluationBuffer.
func newManyLUTEvaluationBuffer[T tfhe.TorusInt](params tfhe.Parameters[T]) manyLUTEvaluationBuffer[T] {
ctAccFourierDecomposed := make([][]poly.FourierPoly, params.GLWERank()+1)
for i := 0; i < params.GLWERank()+1; i++ {
ctAccFourierDecomposed[i] = make([]poly.FourierPoly, params.BlindRotateParameters().Level())
for j := 0; j < params.BlindRotateParameters().Level(); j++ {
ctAccFourierDecomposed[i][j] = poly.NewFourierPoly(params.PolyDegree())
func newManyLUTEvaluationBuffer[T tfhe.TorusInt](params ManyLUTParameters[T]) manyLUTEvaluationBuffer[T] {
ctAccFourierDecomposed := make([][]poly.FourierPoly, params.baseParameters.GLWERank()+1)
for i := 0; i < params.baseParameters.GLWERank()+1; i++ {
ctAccFourierDecomposed[i] = make([]poly.FourierPoly, params.baseParameters.BlindRotateParameters().Level())
for j := 0; j < params.baseParameters.BlindRotateParameters().Level(); j++ {
ctAccFourierDecomposed[i][j] = poly.NewFourierPoly(params.baseParameters.PolyDegree())
}
}

return manyLUTEvaluationBuffer[T]{
ctFourierAcc: tfhe.NewFourierGLWECiphertext(params),
ctBlockFourierAcc: tfhe.NewFourierGLWECiphertext(params),
ctFourierAcc: tfhe.NewFourierGLWECiphertext(params.baseParameters),
ctBlockFourierAcc: tfhe.NewFourierGLWECiphertext(params.baseParameters),
ctAccFourierDecomposed: ctAccFourierDecomposed,
fMono: poly.NewFourierPoly(params.PolyDegree()),
fMono: poly.NewFourierPoly(params.baseParameters.PolyDegree()),

ctRotate: tfhe.NewGLWECiphertext(params),
ctExtract: tfhe.NewLWECiphertextCustom[T](params.GLWEDimension()),
ctKeySwitchForBootstrap: tfhe.NewLWECiphertextCustom[T](params.LWEDimension()),
ctRotate: tfhe.NewGLWECiphertext(params.baseParameters),
ctExtract: tfhe.NewLWECiphertextCustom[T](params.baseParameters.GLWEDimension()),
ctKeySwitchForBootstrap: tfhe.NewLWECiphertextCustom[T](params.baseParameters.LWEDimension()),

lut: tfhe.NewLookUpTable(params),
lut: tfhe.NewLookUpTable(params.baseParameters),
}
}

// ShallowCopy returns a shallow copy of this Evaluator.
// Returned Evaluator is safe for concurrent use.
func (e *ManyLUTEvaluator[T]) ShallowCopy() *ManyLUTEvaluator[T] {
return &ManyLUTEvaluator[T]{
Evaluator: e.Evaluator.ShallowCopy(),
lutCount: e.lutCount,
buffer: newManyLUTEvaluationBuffer(e.Parameters),
Evaluator: e.Evaluator.ShallowCopy(),
Parameters: e.Parameters,
buffer: newManyLUTEvaluationBuffer(e.Parameters),
}
}

// LUTCount returns the number of LUTs to evaluate at once.
func (e *ManyLUTEvaluator[T]) LUTCount() int {
return e.lutCount
}
Loading

0 comments on commit eade093

Please sign in to comment.