From 07ac4e569dc61589dabc80bb8cdd3b608168e8a7 Mon Sep 17 00:00:00 2001 From: Hwang In Tak Date: Thu, 5 Sep 2024 06:13:12 +0000 Subject: [PATCH] feat: Add Gadget/ExternalProduct for LWE --- mktfhe/bootstrap.go | 4 +- mktfhe/mktfhe_test.go | 4 +- mktfhe/product.go | 52 +++++++-------- tfhe/bootstrap.go | 32 ++++----- tfhe/product.go | 150 +++++++++++++++++++++++++++++++++--------- tfhe/tfhe_test.go | 2 +- 6 files changed, 166 insertions(+), 78 deletions(-) diff --git a/mktfhe/bootstrap.go b/mktfhe/bootstrap.go index 8a28ce5..0ce4270 100644 --- a/mktfhe/bootstrap.go +++ b/mktfhe/bootstrap.go @@ -94,7 +94,7 @@ func (e *Evaluator[T]) BlindRotateAssign(ct LWECiphertext[T], lut tfhe.LookUpTab e.SingleKeyEvaluators[i].BlindRotateAssign(e.buffer.ctRotateInputs[i], e.buffer.gadgetLUTs[j], e.buffer.ctAccs[i]) e.SingleKeyEvaluators[i].ToFourierGLWECiphertextAssign(e.buffer.ctAccs[i], e.buffer.ctFourierAccs[i].Value[j]) } - e.ExternalProductAssign(i, e.buffer.ctFourierAccs[i], ctOut, ctOut) + e.ExternalProductGLWEAssign(i, e.buffer.ctFourierAccs[i], ctOut, ctOut) } } } @@ -132,7 +132,7 @@ func (e *Evaluator[T]) BlindRotateParallelAssign(ct LWECiphertext[T], lut tfhe.L for i, ok := range e.PartyBitMap { if ok { - e.ExternalProductAssign(i, e.buffer.ctFourierAccs[i], ctOut, ctOut) + e.ExternalProductGLWEAssign(i, e.buffer.ctFourierAccs[i], ctOut, ctOut) } } } diff --git a/mktfhe/mktfhe_test.go b/mktfhe/mktfhe_test.go index 103c725..8c1f46a 100644 --- a/mktfhe/mktfhe_test.go +++ b/mktfhe/mktfhe_test.go @@ -83,7 +83,7 @@ func TestEvaluator(t *testing.T) { mul := 1 ctMul := enc[0].FourierUniEncrypt([]int{mul}, params.RelinKeyParameters()) - ctOut := eval.HybridProduct(0, ctMul, ct) + ctOut := eval.HybridProductGLWE(0, ctMul, ct) for i, m := range messages { assert.Equal(t, (mul*m)%int(params.MessageModulus()), dec.DecryptGLWE(ctOut)[i]) @@ -96,7 +96,7 @@ func TestEvaluator(t *testing.T) { mul := 1 ctMul := enc[0].SingleKeyEncryptor.EncryptFourierGLev([]int{mul}, params.AccumulatorParameters()) - ctOut := eval.ExternalProduct(0, ctMul, ct) + ctOut := eval.ExternalProductGLWE(0, ctMul, ct) for i, m := range messages { assert.Equal(t, (mul*m)%int(params.MessageModulus()), dec.DecryptGLWE(ctOut)[i]) diff --git a/mktfhe/product.go b/mktfhe/product.go index 4b4b65f..c46f6f0 100644 --- a/mktfhe/product.go +++ b/mktfhe/product.go @@ -4,15 +4,15 @@ import ( "github.com/sp301415/tfhe-go/tfhe" ) -// HybridProduct returns the hybrid product between ctFourierUniEnc and ctGLWE. -func (e *Evaluator[T]) HybridProduct(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE GLWECiphertext[T]) GLWECiphertext[T] { +// HybridProductGLWE returns the hybrid product between ctFourierUniEnc and ctGLWE. +func (e *Evaluator[T]) HybridProductGLWE(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE GLWECiphertext[T]) GLWECiphertext[T] { ctOut := NewGLWECiphertext(e.Parameters) - e.HybridProductAssign(idx, ctFourierUniEnc, ctGLWE, ctOut) + e.HybridProductGLWEAssign(idx, ctFourierUniEnc, ctGLWE, ctOut) return ctOut } -// HybridProductAssign computes the hybrid product between ctFourierUniEnc and ctGLWE and writes it to ctGLWEOut. -func (e *Evaluator[T]) HybridProductAssign(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// HybridProductGLWEAssign computes the hybrid product between ctFourierUniEnc and ctGLWE and writes it to ctGLWEOut. +func (e *Evaluator[T]) HybridProductGLWEAssign(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { eIdx := e.SingleKeyEvaluators[idx] polyDecomposed := e.polyDecomposedBuffer(ctFourierUniEnc.GadgetParameters) @@ -71,7 +71,7 @@ func (e *Evaluator[T]) HybridProductAssign(idx int, ctFourierUniEnc FourierUniEn } // HybridProductAssign computes the hybrid product between ctFourierUniEnc and ctGLWE and adds it to ctGLWEOut. -func (e *Evaluator[T]) HybridProductAddAssign(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +func (e *Evaluator[T]) HybridProductAddGLWEAssign(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { eIdx := e.SingleKeyEvaluators[idx] polyDecomposed := e.polyDecomposedBuffer(ctFourierUniEnc.GadgetParameters) @@ -127,8 +127,8 @@ func (e *Evaluator[T]) HybridProductAddAssign(idx int, ctFourierUniEnc FourierUn } } -// HybridProductSubAssign computes the hybrid product between ctFourierUniEnc and ctGLWE and subtracts it from ctGLWEOut. -func (e *Evaluator[T]) HybridProductSubAssign(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// HybridProductSubGLWEAssign computes the hybrid product between ctFourierUniEnc and ctGLWE and subtracts it from ctGLWEOut. +func (e *Evaluator[T]) HybridProductSubGLWEAssign(idx int, ctFourierUniEnc FourierUniEncryption[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { eIdx := e.SingleKeyEvaluators[idx] polyDecomposed := e.polyDecomposedBuffer(ctFourierUniEnc.GadgetParameters) @@ -184,27 +184,27 @@ func (e *Evaluator[T]) HybridProductSubAssign(idx int, ctFourierUniEnc FourierUn } } -// ExternalProduct returns the external product between ctFourierGLev and ctGLWE. -func (e *Evaluator[T]) ExternalProduct(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE GLWECiphertext[T]) GLWECiphertext[T] { +// ExternalProductGLWE returns the external product between ctFourierGLev and ctGLWE. +func (e *Evaluator[T]) ExternalProductGLWE(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE GLWECiphertext[T]) GLWECiphertext[T] { ctOut := NewGLWECiphertext(e.Parameters) - e.ExternalProductAssign(idx, ctFourierGLev, ctGLWE, ctOut) + e.ExternalProductGLWEAssign(idx, ctFourierGLev, ctGLWE, ctOut) return ctOut } -// ExternalProductAssign computes the external product between ctFourierGLev and ctGLWE and writes it to ctGLWEOut. -func (e *Evaluator[T]) ExternalProductAssign(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// ExternalProductGLWEAssign computes the external product between ctFourierGLev and ctGLWE and writes it to ctGLWEOut. +func (e *Evaluator[T]) ExternalProductGLWEAssign(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { eIdx := e.SingleKeyEvaluators[idx] - eIdx.GadgetProductAssign(ctFourierGLev, ctGLWE.Value[0], e.buffer.ctRelinTransposed[0]) + eIdx.GadgetProductAssignGLWE(ctFourierGLev, ctGLWE.Value[0], e.buffer.ctRelinTransposed[0]) e.buffer.ctRelin.Value[0].CopyFrom(e.buffer.ctRelinTransposed[0].Value[1]) for i, ok := range e.PartyBitMap { if ok { - eIdx.GadgetProductAssign(ctFourierGLev, ctGLWE.Value[i+1], e.buffer.ctRelinTransposed[i+1]) + eIdx.GadgetProductAssignGLWE(ctFourierGLev, ctGLWE.Value[i+1], e.buffer.ctRelinTransposed[i+1]) e.buffer.ctRelin.Value[i+1].CopyFrom(e.buffer.ctRelinTransposed[i+1].Value[1]) } } - e.HybridProductAssign(idx, e.EvaluationKeys[idx].RelinKey, e.buffer.ctRelin, ctGLWEOut) + e.HybridProductGLWEAssign(idx, e.EvaluationKeys[idx].RelinKey, e.buffer.ctRelin, ctGLWEOut) eIdx.PolyEvaluator.AddAssign(ctGLWEOut.Value[0], e.buffer.ctRelinTransposed[0].Value[0], ctGLWEOut.Value[0]) for i, ok := range e.PartyBitMap { @@ -214,20 +214,20 @@ func (e *Evaluator[T]) ExternalProductAssign(idx int, ctFourierGLev tfhe.Fourier } } -// ExternalProductAddAssign computes the external product between ctFourierGLev and ctGLWE and adds it to ctGLWEOut. -func (e *Evaluator[T]) ExternalProductAddAssign(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// ExternalProductAddGLWEAssign computes the external product between ctFourierGLev and ctGLWE and adds it to ctGLWEOut. +func (e *Evaluator[T]) ExternalProductAddGLWEAssign(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { eIdx := e.SingleKeyEvaluators[idx] - eIdx.GadgetProductAssign(ctFourierGLev, ctGLWE.Value[0], e.buffer.ctRelinTransposed[0]) + eIdx.GadgetProductAssignGLWE(ctFourierGLev, ctGLWE.Value[0], e.buffer.ctRelinTransposed[0]) e.buffer.ctRelin.Value[0].CopyFrom(e.buffer.ctRelinTransposed[0].Value[1]) for i, ok := range e.PartyBitMap { if ok { - eIdx.GadgetProductAssign(ctFourierGLev, ctGLWE.Value[i+1], e.buffer.ctRelinTransposed[i+1]) + eIdx.GadgetProductAssignGLWE(ctFourierGLev, ctGLWE.Value[i+1], e.buffer.ctRelinTransposed[i+1]) e.buffer.ctRelin.Value[i+1].CopyFrom(e.buffer.ctRelinTransposed[i+1].Value[1]) } } - e.HybridProductAddAssign(idx, e.EvaluationKeys[idx].RelinKey, e.buffer.ctRelin, ctGLWEOut) + e.HybridProductAddGLWEAssign(idx, e.EvaluationKeys[idx].RelinKey, e.buffer.ctRelin, ctGLWEOut) eIdx.PolyEvaluator.AddAssign(ctGLWEOut.Value[0], e.buffer.ctRelinTransposed[0].Value[0], ctGLWEOut.Value[0]) for i, ok := range e.PartyBitMap { @@ -237,20 +237,20 @@ func (e *Evaluator[T]) ExternalProductAddAssign(idx int, ctFourierGLev tfhe.Four } } -// ExternalProductSubAssign computes the external product between ctFourierGLev and ctGLWE and subtracts it from ctGLWEOut. -func (e *Evaluator[T]) ExternalProductSubAssign(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// ExternalProductSubGLWEAssign computes the external product between ctFourierGLev and ctGLWE and subtracts it from ctGLWEOut. +func (e *Evaluator[T]) ExternalProductSubGLWEAssign(idx int, ctFourierGLev tfhe.FourierGLevCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { eIdx := e.SingleKeyEvaluators[idx] - eIdx.GadgetProductAssign(ctFourierGLev, ctGLWE.Value[0], e.buffer.ctRelinTransposed[0]) + eIdx.GadgetProductAssignGLWE(ctFourierGLev, ctGLWE.Value[0], e.buffer.ctRelinTransposed[0]) e.buffer.ctRelin.Value[0].CopyFrom(e.buffer.ctRelinTransposed[0].Value[1]) for i, ok := range e.PartyBitMap { if ok { - eIdx.GadgetProductAssign(ctFourierGLev, ctGLWE.Value[i+1], e.buffer.ctRelinTransposed[i+1]) + eIdx.GadgetProductAssignGLWE(ctFourierGLev, ctGLWE.Value[i+1], e.buffer.ctRelinTransposed[i+1]) e.buffer.ctRelin.Value[i+1].CopyFrom(e.buffer.ctRelinTransposed[i+1].Value[1]) } } - e.HybridProductSubAssign(idx, e.EvaluationKeys[idx].RelinKey, e.buffer.ctRelin, ctGLWEOut) + e.HybridProductSubGLWEAssign(idx, e.EvaluationKeys[idx].RelinKey, e.buffer.ctRelin, ctGLWEOut) eIdx.PolyEvaluator.AddAssign(ctGLWEOut.Value[0], e.buffer.ctRelinTransposed[0].Value[0], ctGLWEOut.Value[0]) for i, ok := range e.PartyBitMap { diff --git a/tfhe/bootstrap.go b/tfhe/bootstrap.go index a48d3f3..37aa597 100644 --- a/tfhe/bootstrap.go +++ b/tfhe/bootstrap.go @@ -183,7 +183,7 @@ func (e *Evaluator[T]) blindRotateExtendedAssign(ct LWECiphertext[T], lut LookUp a2NSmall, a2NIdx := a2N/e.Parameters.polyExtendFactor, a2N%e.Parameters.polyExtendFactor for k := 0; k < e.Parameters.polyExtendFactor; k++ { - e.GadgetProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[k][0], e.buffer.ctBlockFourierAcc[k]) + e.GadgetProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[k][0], e.buffer.ctBlockFourierAcc[k]) } if a2NIdx == 0 { @@ -209,7 +209,7 @@ func (e *Evaluator[T]) blindRotateExtendedAssign(ct LWECiphertext[T], lut LookUp a2NSmall, a2NIdx := a2N/e.Parameters.polyExtendFactor, a2N%e.Parameters.polyExtendFactor for k := 0; k < e.Parameters.polyExtendFactor; k++ { - e.GadgetProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[j].Value[0], e.buffer.ctAccFourierDecomposed[k][0], e.buffer.ctBlockFourierAcc[k]) + e.GadgetProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[j].Value[0], e.buffer.ctAccFourierDecomposed[k][0], e.buffer.ctBlockFourierAcc[k]) } if a2NIdx == 0 { @@ -251,7 +251,7 @@ func (e *Evaluator[T]) blindRotateExtendedAssign(ct LWECiphertext[T], lut LookUp a2NSmall, a2NIdx := a2N/e.Parameters.polyExtendFactor, a2N%e.Parameters.polyExtendFactor for k := 0; k < e.Parameters.polyExtendFactor; k++ { - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[i*e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[k], e.buffer.ctBlockFourierAcc[k]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[i*e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[k], e.buffer.ctBlockFourierAcc[k]) } if a2NIdx == 0 { @@ -277,7 +277,7 @@ func (e *Evaluator[T]) blindRotateExtendedAssign(ct LWECiphertext[T], lut LookUp a2NSmall, a2NIdx := a2N/e.Parameters.polyExtendFactor, a2N%e.Parameters.polyExtendFactor for k := 0; k < e.Parameters.polyExtendFactor; k++ { - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[k], e.buffer.ctBlockFourierAcc[k]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[k], e.buffer.ctBlockFourierAcc[k]) } if a2NIdx == 0 { @@ -319,13 +319,13 @@ func (e *Evaluator[T]) blindRotateExtendedAssign(ct LWECiphertext[T], lut LookUp a2NSmall, a2NIdx = a2N/e.Parameters.polyExtendFactor, a2N%e.Parameters.polyExtendFactor if a2NIdx == 0 { - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[e.Parameters.lweDimension-e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[e.Parameters.lweDimension-e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(a2NSmall, e.buffer.fMono) e.FourierPolyMulFourierGLWEAssign(e.buffer.ctBlockFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) } else { kk := e.Parameters.polyExtendFactor - a2NIdx - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[e.Parameters.lweDimension-e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[e.Parameters.lweDimension-e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[kk], e.buffer.ctBlockFourierAcc[kk]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[e.Parameters.lweDimension-e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[e.Parameters.lweDimension-e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[kk], e.buffer.ctBlockFourierAcc[kk]) e.FourierEvaluator.MonomialToFourierPolyAssign(a2NSmall+1, e.buffer.fMono) e.FourierPolyMulFourierGLWEAssign(e.buffer.ctBlockFourierAcc[kk], e.buffer.fMono, e.buffer.ctFourierAcc[0]) e.SubFourierGLWEAssign(e.buffer.ctFourierAcc[0], e.buffer.ctBlockFourierAcc[0], e.buffer.ctFourierAcc[0]) @@ -336,13 +336,13 @@ func (e *Evaluator[T]) blindRotateExtendedAssign(ct LWECiphertext[T], lut LookUp a2NSmall, a2NIdx := a2N/e.Parameters.polyExtendFactor, a2N%e.Parameters.polyExtendFactor if a2NIdx == 0 { - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(a2NSmall, e.buffer.fMono) e.FourierPolyMulAddFourierGLWEAssign(e.buffer.ctBlockFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) } else { kk := e.Parameters.polyExtendFactor - a2NIdx - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[kk], e.buffer.ctBlockFourierAcc[kk]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[kk], e.buffer.ctBlockFourierAcc[kk]) e.FourierEvaluator.MonomialToFourierPolyAssign(a2NSmall+1, e.buffer.fMono) e.FourierPolyMulAddFourierGLWEAssign(e.buffer.ctBlockFourierAcc[kk], e.buffer.fMono, e.buffer.ctFourierAcc[0]) e.SubFourierGLWEAssign(e.buffer.ctFourierAcc[0], e.buffer.ctBlockFourierAcc[0], e.buffer.ctFourierAcc[0]) @@ -371,11 +371,11 @@ func (e *Evaluator[T]) blindRotateBlockAssign(ct LWECiphertext[T], lut LookUpTab e.FourierEvaluator.ToFourierPolyAssign(polyDecomposed[k], e.buffer.ctAccFourierDecomposed[0][0][k]) } - e.GadgetProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[0][0], e.buffer.ctBlockFourierAcc[0]) + e.GadgetProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[0][0], e.buffer.ctBlockFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[1]), e.buffer.fMono) e.FourierPolyMulFourierGLWEAssign(e.buffer.ctBlockFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) for j := 1; j < e.Parameters.blockSize; j++ { - e.GadgetProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[j].Value[0], e.buffer.ctAccFourierDecomposed[0][0], e.buffer.ctBlockFourierAcc[0]) + e.GadgetProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[j].Value[0], e.buffer.ctAccFourierDecomposed[0][0], e.buffer.ctBlockFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[j+1]), e.buffer.fMono) e.FourierPolyMulAddFourierGLWEAssign(e.buffer.ctBlockFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) } @@ -392,11 +392,11 @@ func (e *Evaluator[T]) blindRotateBlockAssign(ct LWECiphertext[T], lut LookUpTab } } - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[i*e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[i*e.Parameters.blockSize], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[i*e.Parameters.blockSize+1]), e.buffer.fMono) e.FourierPolyMulFourierGLWEAssign(e.buffer.ctBlockFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) for j := i*e.Parameters.blockSize + 1; j < (i+1)*e.Parameters.blockSize; j++ { - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[j], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctBlockFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[j+1]), e.buffer.fMono) e.FourierPolyMulAddFourierGLWEAssign(e.buffer.ctBlockFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) } @@ -423,7 +423,7 @@ func (e *Evaluator[T]) blindRotateOriginalAssign(ct LWECiphertext[T], lut LookUp e.FourierEvaluator.ToFourierPolyAssign(polyDecomposed[k], e.buffer.ctAccFourierDecomposed[0][0][k]) } - e.GadgetProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[0][0], e.buffer.ctFourierAcc[0]) + e.GadgetProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[0].Value[0], e.buffer.ctAccFourierDecomposed[0][0], e.buffer.ctFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[1]), e.buffer.fMono) e.FourierPolyMulFourierGLWEAssign(e.buffer.ctFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) for j := 0; j < e.Parameters.glweRank+1; j++ { @@ -438,7 +438,7 @@ func (e *Evaluator[T]) blindRotateOriginalAssign(ct LWECiphertext[T], lut LookUp } } - e.ExternalProductFourierDecomposedFourierAssign(e.EvaluationKey.BootstrapKey.Value[i], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctFourierAcc[0]) + e.ExternalProductHoistedFourierGLWEAssign(e.EvaluationKey.BootstrapKey.Value[i], e.buffer.ctAccFourierDecomposed[0], e.buffer.ctFourierAcc[0]) e.FourierEvaluator.MonomialSubOneToFourierPolyAssign(-e.ModSwitch(ct.Value[i+1]), e.buffer.fMono) e.FourierPolyMulFourierGLWEAssign(e.buffer.ctFourierAcc[0], e.buffer.fMono, e.buffer.ctFourierAcc[0]) diff --git a/tfhe/product.go b/tfhe/product.go index ea54eab..828ef16 100644 --- a/tfhe/product.go +++ b/tfhe/product.go @@ -2,17 +2,56 @@ package tfhe import ( "github.com/sp301415/tfhe-go/math/poly" + "github.com/sp301415/tfhe-go/math/vec" ) -// GadgetProduct returns the gadget product between p and ctFourierGLev. -func (e *Evaluator[T]) GadgetProduct(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T]) GLWECiphertext[T] { +// GadgetProductLWE returns the gadget product between c and ctLev. +func (e *Evaluator[T]) GadgetProductLWE(ctLev LevCiphertext[T], c T) LWECiphertext[T] { + ctOut := NewLWECiphertext(e.Parameters) + e.GadgetProductAssignLWE(ctLev, c, ctOut) + return ctOut +} + +// GadgetProductAssignLWE computes the gadget product between c and ctLev and writes it to ctLWEOut. +func (e *Evaluator[T]) GadgetProductAssignLWE(ctLev LevCiphertext[T], c T, ctLWEOut LWECiphertext[T]) { + decomposed := e.decomposedBuffer(ctLev.GadgetParameters) + + e.DecomposeAssign(c, ctLev.GadgetParameters, decomposed) + vec.ScalarMulAssign(ctLev.Value[0].Value, decomposed[0], ctLWEOut.Value) + for i := 1; i < ctLev.GadgetParameters.level; i++ { + vec.ScalarMulAddAssign(ctLev.Value[i].Value, decomposed[i], ctLWEOut.Value) + } +} + +// GadgetProductAddAssignLWE computes the gadget product between c and ctLev and adds it to ctLWEOut. +func (e *Evaluator[T]) GadgetProductAddAssignLWE(ctLev LevCiphertext[T], c T, ctLWEOut LWECiphertext[T]) { + decomposed := e.decomposedBuffer(ctLev.GadgetParameters) + + e.DecomposeAssign(c, ctLev.GadgetParameters, decomposed) + for i := 0; i < ctLev.GadgetParameters.level; i++ { + vec.ScalarMulAddAssign(ctLev.Value[i].Value, decomposed[i], ctLWEOut.Value) + } +} + +// GadgetProductSubAssignLWE computes the gadget product between c and ctLev and subtracts it from ctLWEOut. +func (e *Evaluator[T]) GadgetProductSubAssignLWE(ctLev LevCiphertext[T], c T, ctLWEOut LWECiphertext[T]) { + decomposed := e.decomposedBuffer(ctLev.GadgetParameters) + + e.DecomposeAssign(c, ctLev.GadgetParameters, decomposed) + for i := 0; i < ctLev.GadgetParameters.level; i++ { + vec.ScalarMulSubAssign(ctLev.Value[i].Value, decomposed[i], ctLWEOut.Value) + } +} + +// GadgetProductGLWE returns the gadget product between p and ctFourierGLev. +func (e *Evaluator[T]) GadgetProductGLWE(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T]) GLWECiphertext[T] { ctOut := NewGLWECiphertext(e.Parameters) - e.GadgetProductAssign(ctFourierGLev, p, ctOut) + e.GadgetProductAssignGLWE(ctFourierGLev, p, ctOut) return ctOut } -// GadgetProductAssign computes the gadget product between p and ctFourierGLev and writes it to ctGLWEOut. -func (e *Evaluator[T]) GadgetProductAssign(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T], ctGLWEOut GLWECiphertext[T]) { +// GadgetProductAssignGLWE computes the gadget product between p and ctFourierGLev and writes it to ctGLWEOut. +func (e *Evaluator[T]) GadgetProductAssignGLWE(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T], ctGLWEOut GLWECiphertext[T]) { polyDecomposed := e.polyDecomposedBuffer(ctFourierGLev.GadgetParameters) polyFourierDecomposed := e.polyFourierDecomposedBuffer(ctFourierGLev.GadgetParameters) @@ -31,8 +70,8 @@ func (e *Evaluator[T]) GadgetProductAssign(ctFourierGLev FourierGLevCiphertext[T } } -// GadgetProductAddAssign computes the gadget product between p and ctFourierGLev and adds it to ctGLWEOut. -func (e *Evaluator[T]) GadgetProductAddAssign(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T], ctGLWEOut GLWECiphertext[T]) { +// GadgetProductAddAssignGLWE computes the gadget product between p and ctFourierGLev and adds it to ctGLWEOut. +func (e *Evaluator[T]) GadgetProductAddAssignGLWE(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T], ctGLWEOut GLWECiphertext[T]) { polyDecomposed := e.polyDecomposedBuffer(ctFourierGLev.GadgetParameters) polyFourierDecomposed := e.polyFourierDecomposedBuffer(ctFourierGLev.GadgetParameters) @@ -51,8 +90,8 @@ func (e *Evaluator[T]) GadgetProductAddAssign(ctFourierGLev FourierGLevCiphertex } } -// GadgetProductSubAssign computes the gadget product between p and ctFourierGLev and subtracts it from ctGLWEOut. -func (e *Evaluator[T]) GadgetProductSubAssign(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T], ctGLWEOut GLWECiphertext[T]) { +// GadgetProductSubAssignGLWE computes the gadget product between p and ctFourierGLev and subtracts it from ctGLWEOut. +func (e *Evaluator[T]) GadgetProductSubAssignGLWE(ctFourierGLev FourierGLevCiphertext[T], p poly.Poly[T], ctGLWEOut GLWECiphertext[T]) { polyDecomposed := e.polyDecomposedBuffer(ctFourierGLev.GadgetParameters) polyFourierDecomposed := e.polyFourierDecomposedBuffer(ctFourierGLev.GadgetParameters) @@ -71,37 +110,86 @@ func (e *Evaluator[T]) GadgetProductSubAssign(ctFourierGLev FourierGLevCiphertex } } -// GadgetProductFourierDecomposedFourierAssign computes the gadget product between fourier decomposed p and ctFourierGLev and writes it to ctFourierGLWEOut. -func (e *Evaluator[T]) GadgetProductFourierDecomposedFourierAssign(ctFourierGLev FourierGLevCiphertext[T], pDecomposed []poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { +// GadgetProductHoistedFourierGLWEAssign computes the gadget product between fourier decomposed p and ctFourierGLev and writes it to ctFourierGLWEOut. +func (e *Evaluator[T]) GadgetProductHoistedFourierGLWEAssign(ctFourierGLev FourierGLevCiphertext[T], pDecomposed []poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { e.FourierPolyMulFourierGLWEAssign(ctFourierGLev.Value[0], pDecomposed[0], ctFourierGLWEOut) for i := 1; i < ctFourierGLev.GadgetParameters.level; i++ { e.FourierPolyMulAddFourierGLWEAssign(ctFourierGLev.Value[i], pDecomposed[i], ctFourierGLWEOut) } } -// GadgetProductFourierDecomposedAddFourierAssign computes the gadget product between fourier decomposed p and ctFourierGLev and adds it to ctFourierGLWEOut. -func (e *Evaluator[T]) GadgetProductFourierDecomposedAddFourierAssign(ctFourierGLev FourierGLevCiphertext[T], pDecomposed []poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { +// GadgetProductHoistedAddFourierGLWEAssign computes the gadget product between fourier decomposed p and ctFourierGLev and adds it to ctFourierGLWEOut. +func (e *Evaluator[T]) GadgetProductHoistedAddFourierGLWEAssign(ctFourierGLev FourierGLevCiphertext[T], pDecomposed []poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { for i := 0; i < ctFourierGLev.GadgetParameters.level; i++ { e.FourierPolyMulAddFourierGLWEAssign(ctFourierGLev.Value[i], pDecomposed[i], ctFourierGLWEOut) } } -// GadgetProductFourierDecomposedSubFourierAssign computes the gadget product between fourier decomposed p and ctFourierGLev and subtracts it from ctFourierGLWEOut. -func (e *Evaluator[T]) GadgetProductFourierDecomposedSubFourierAssign(ctFourierGLev FourierGLevCiphertext[T], pDecomposed []poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { +// GadgetProductHoistedSubFourierGLWEAssign computes the gadget product between fourier decomposed p and ctFourierGLev and subtracts it from ctFourierGLWEOut. +func (e *Evaluator[T]) GadgetProductHoistedSubFourierGLWEAssign(ctFourierGLev FourierGLevCiphertext[T], pDecomposed []poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { for i := 0; i < ctFourierGLev.GadgetParameters.level; i++ { e.FourierPolyMulSubFourierGLWEAssign(ctFourierGLev.Value[i], pDecomposed[i], ctFourierGLWEOut) } } -// ExternalProduct returns the external product between ctFourierGGSW and ctGLWE. -func (e *Evaluator[T]) ExternalProduct(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE GLWECiphertext[T]) GLWECiphertext[T] { +// ExternalProductLWE returns the external product between ctGSW and ctLWE. +func (e *Evaluator[T]) ExternalProductLWE(ctGSW GSWCiphertext[T], ctLWE LWECiphertext[T]) LWECiphertext[T] { + ctOut := NewLWECiphertext(e.Parameters) + e.ExternalProductLWEAssign(ctGSW, ctLWE, ctOut) + return ctOut +} + +// ExternalProductLWEAssign computes the external product between ctGSW and ctLWE and writes it to ctOut. +func (e *Evaluator[T]) ExternalProductLWEAssign(ctGSW GSWCiphertext[T], ctLWE LWECiphertext[T], ctLWEOut LWECiphertext[T]) { + decomposed := e.decomposedBuffer(ctGSW.GadgetParameters) + + e.DecomposeAssign(ctLWE.Value[0], ctGSW.GadgetParameters, decomposed) + vec.ScalarMulAssign(ctGSW.Value[0].Value[0].Value, decomposed[0], ctLWEOut.Value) + for j := 1; j < ctGSW.GadgetParameters.level; j++ { + vec.ScalarMulAddAssign(ctGSW.Value[0].Value[j].Value, decomposed[j], ctLWEOut.Value) + } + + for i := 1; i < e.Parameters.DefaultLWEDimension()+1; i++ { + e.DecomposeAssign(ctLWE.Value[i], ctGSW.GadgetParameters, decomposed) + for j := 0; j < ctGSW.GadgetParameters.level; j++ { + vec.ScalarMulAddAssign(ctGSW.Value[i].Value[j].Value, decomposed[j], ctLWEOut.Value) + } + } +} + +// ExternalProductAddLWEAssign computes the external product between ctGSW and ctLWE and adds it to ctLWEOut. +func (e *Evaluator[T]) ExternalProductAddLWEAssign(ctGSW GSWCiphertext[T], ctLWE LWECiphertext[T], ctLWEOut LWECiphertext[T]) { + decomposed := e.decomposedBuffer(ctGSW.GadgetParameters) + + for i := 0; i < e.Parameters.DefaultLWEDimension()+1; i++ { + e.DecomposeAssign(ctLWE.Value[i], ctGSW.GadgetParameters, decomposed) + for j := 0; j < ctGSW.GadgetParameters.level; j++ { + vec.ScalarMulAddAssign(ctGSW.Value[i].Value[j].Value, decomposed[j], ctLWEOut.Value) + } + } +} + +// ExternalProductSubLWEAssign computes the external product between ctGSW and ctLWE and subtracts it from ctLWEOut. +func (e *Evaluator[T]) ExternalProductSubLWEAssign(ctGSW GSWCiphertext[T], ctLWE LWECiphertext[T], ctLWEOut LWECiphertext[T]) { + decomposed := e.decomposedBuffer(ctGSW.GadgetParameters) + + for i := 0; i < e.Parameters.DefaultLWEDimension()+1; i++ { + e.DecomposeAssign(ctLWE.Value[i], ctGSW.GadgetParameters, decomposed) + for j := 0; j < ctGSW.GadgetParameters.level; j++ { + vec.ScalarMulSubAssign(ctGSW.Value[i].Value[j].Value, decomposed[j], ctLWEOut.Value) + } + } +} + +// ExternalProductGLWE returns the external product between ctFourierGGSW and ctGLWE. +func (e *Evaluator[T]) ExternalProductGLWE(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE GLWECiphertext[T]) GLWECiphertext[T] { ctOut := NewGLWECiphertext(e.Parameters) - e.ExternalProductAssign(ctFourierGGSW, ctGLWE, ctOut) + e.ExternalProductGLWEAssign(ctFourierGGSW, ctGLWE, ctOut) return ctOut } -// ExternalProductAssign computes the external product between ctFourierGGSW and ctGLWE and writes it to ctOut. -func (e *Evaluator[T]) ExternalProductAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// ExternalProductGLWEAssign computes the external product between ctFourierGGSW and ctGLWE and writes it to ctOut. +func (e *Evaluator[T]) ExternalProductGLWEAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { polyDecomposed := e.polyDecomposedBuffer(ctFourierGGSW.GadgetParameters) e.DecomposePolyAssign(ctGLWE.Value[0], ctFourierGGSW.GadgetParameters, polyDecomposed) @@ -122,8 +210,8 @@ func (e *Evaluator[T]) ExternalProductAssign(ctFourierGGSW FourierGGSWCiphertext } } -// ExternalProductAddAssign computes the external product between ctFourierGGSW and ctGLWE and adds it to ctGLWEOut. -func (e *Evaluator[T]) ExternalProductAddAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// ExternalProductAddGLWEAssign computes the external product between ctFourierGGSW and ctGLWE and adds it to ctGLWEOut. +func (e *Evaluator[T]) ExternalProductAddGLWEAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { polyDecomposed := e.polyDecomposedBuffer(ctFourierGGSW.GadgetParameters) e.DecomposePolyAssign(ctGLWE.Value[0], ctFourierGGSW.GadgetParameters, polyDecomposed) @@ -144,8 +232,8 @@ func (e *Evaluator[T]) ExternalProductAddAssign(ctFourierGGSW FourierGGSWCiphert } } -// ExternalProductSubAssign computes the external product between ctFourierGGSW and ctGLWE and subtracts it from ctGLWEOut. -func (e *Evaluator[T]) ExternalProductSubAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { +// ExternalProductSubGLWEAssign computes the external product between ctFourierGGSW and ctGLWE and subtracts it from ctGLWEOut. +func (e *Evaluator[T]) ExternalProductSubGLWEAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWE, ctGLWEOut GLWECiphertext[T]) { polyDecomposed := e.polyDecomposedBuffer(ctFourierGGSW.GadgetParameters) e.DecomposePolyAssign(ctGLWE.Value[0], ctFourierGGSW.GadgetParameters, polyDecomposed) @@ -166,8 +254,8 @@ func (e *Evaluator[T]) ExternalProductSubAssign(ctFourierGGSW FourierGGSWCiphert } } -// ExternalProductFourierDecomposedFourierAssign computes the external product between ctFourierGGSW and fourier decomposed ctGLWE and writes it to ctFourierGLWEOut. -func (e *Evaluator[T]) ExternalProductFourierDecomposedFourierAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWEDecomposed [][]poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { +// ExternalProductHoistedFourierGLWEAssign computes the external product between ctFourierGGSW and fourier decomposed ctGLWE and writes it to ctFourierGLWEOut. +func (e *Evaluator[T]) ExternalProductHoistedFourierGLWEAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWEDecomposed [][]poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { e.FourierPolyMulFourierGLWEAssign(ctFourierGGSW.Value[0].Value[0], ctGLWEDecomposed[0][0], ctFourierGLWEOut) for j := 1; j < ctFourierGGSW.GadgetParameters.level; j++ { e.FourierPolyMulAddFourierGLWEAssign(ctFourierGGSW.Value[0].Value[j], ctGLWEDecomposed[0][j], ctFourierGLWEOut) @@ -180,8 +268,8 @@ func (e *Evaluator[T]) ExternalProductFourierDecomposedFourierAssign(ctFourierGG } } -// ExternalProductFourierDecomposedAddFourierAssign computes the external product between ctFourierGGSW and fourier decomposed ctGLWE and adds it to ctFourierGLWEOut. -func (e *Evaluator[T]) ExternalProductFourierDecomposedAddFourierAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWEDecomposed [][]poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { +// ExternalProductHoistedAddFourierGLWEAssign computes the external product between ctFourierGGSW and fourier decomposed ctGLWE and adds it to ctFourierGLWEOut. +func (e *Evaluator[T]) ExternalProductHoistedAddFourierGLWEAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWEDecomposed [][]poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { for i := 0; i < e.Parameters.glweRank+1; i++ { for j := 0; j < ctFourierGGSW.GadgetParameters.level; j++ { e.FourierPolyMulAddFourierGLWEAssign(ctFourierGGSW.Value[i].Value[j], ctGLWEDecomposed[i][j], ctFourierGLWEOut) @@ -189,8 +277,8 @@ func (e *Evaluator[T]) ExternalProductFourierDecomposedAddFourierAssign(ctFourie } } -// ExternalProductFourierDecomposedSubFourierAssign computes the external product between ctFourierGGSW and fourier decomposed ctGLWE and subtracts it from ctFourierGLWEOut. -func (e *Evaluator[T]) ExternalProductFourierDecomposedSubFourierAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWEDecomposed [][]poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { +// ExternalProductHoistedSubFourierGLWEAssign computes the external product between ctFourierGGSW and fourier decomposed ctGLWE and subtracts it from ctFourierGLWEOut. +func (e *Evaluator[T]) ExternalProductHoistedSubFourierGLWEAssign(ctFourierGGSW FourierGGSWCiphertext[T], ctGLWEDecomposed [][]poly.FourierPoly, ctFourierGLWEOut FourierGLWECiphertext[T]) { for i := 0; i < e.Parameters.glweRank+1; i++ { for j := 0; j < ctFourierGGSW.GadgetParameters.level; j++ { e.FourierPolyMulSubFourierGLWEAssign(ctFourierGGSW.Value[i].Value[j], ctGLWEDecomposed[i][j], ctFourierGLWEOut) @@ -211,5 +299,5 @@ func (e *Evaluator[T]) CMux(ctFourierGGSW FourierGGSWCiphertext[T], ct0, ct1 GLW func (e *Evaluator[T]) CMuxAssign(ctFourierGGSW FourierGGSWCiphertext[T], ct0, ct1, ctOut GLWECiphertext[T]) { ctOut.CopyFrom(ct0) e.SubGLWEAssign(ct1, ct0, e.buffer.ctCMux) - e.ExternalProductAddAssign(ctFourierGGSW, e.buffer.ctCMux, ctOut) + e.ExternalProductAddGLWEAssign(ctFourierGGSW, e.buffer.ctCMux, ctOut) } diff --git a/tfhe/tfhe_test.go b/tfhe/tfhe_test.go index 4ae8970..4d8ba8a 100644 --- a/tfhe/tfhe_test.go +++ b/tfhe/tfhe_test.go @@ -118,7 +118,7 @@ func TestEvaluator(t *testing.T) { mul := 2 ctMul := enc.EncryptFourierGGSW([]int{mul}, params.KeySwitchParameters()) - ctOut := eval.ExternalProduct(ctMul, ct) + ctOut := eval.ExternalProductGLWE(ctMul, ct) for i, m := range messages { assert.Equal(t, mul*m, enc.DecryptGLWE(ctOut)[i])