From eb5a8f31f6094c8113bcfb11610bff71aaf36ec1 Mon Sep 17 00:00:00 2001 From: Hwang In Tak Date: Tue, 8 Oct 2024 06:53:07 +0000 Subject: [PATCH] feat: Add Permute GLWE/FourierGLWE ops --- mktfhe/fourier_glwe_ops.go | 47 ++++++++++++++++++++++++++++++++++++++ mktfhe/glwe_ops.go | 47 ++++++++++++++++++++++++++++++++++++++ tfhe/fourier_glwe_ops.go | 47 ++++++++++++++++++++++++++++++++++++++ tfhe/glwe_ops.go | 12 ++++++++++ 4 files changed, 153 insertions(+) diff --git a/mktfhe/fourier_glwe_ops.go b/mktfhe/fourier_glwe_ops.go index c841e78..45065e3 100644 --- a/mktfhe/fourier_glwe_ops.go +++ b/mktfhe/fourier_glwe_ops.go @@ -157,3 +157,50 @@ func (e *Evaluator[T]) FourierPolyMulSubFourierGLWEAssign(ct0 FourierGLWECiphert e.PolyEvaluator.MulSubFourierPolyAssign(ct0.Value[i], fp, ctOut.Value[i]) } } + +// PermuteGLWEAssign computes ctOut = ct0(X^d). +// +// ct0 and ctOut should not overlap. For inplace permutation, +// use [*Evaluator.PermuteFourierGLWEInPlace]. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteFourierGLWEAssign(ct0 FourierGLWECiphertext[T], d int, ctOut FourierGLWECiphertext[T]) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermuteFourierPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} + +// PermuteGLWEInPlace computes ct0 = ct0(X^d). +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteFourierGLWEInPlace(ct0 FourierGLWECiphertext[T], d int) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermuteFourierPolyInPlace(ct0.Value[i], d) + } +} + +// PermuteAddGLWEAssign computes ctOut += ct0(X^d). +// +// ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteAddFourierGLWEAssign(ct0 FourierGLWECiphertext[T], d int, ctOut FourierGLWECiphertext[T]) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermuteAddFourierPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} + +// PermuteSubGLWEAssign computes ctOut -= ct0(X^d). +// +// ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteSubFourierGLWEAssign(ct0 FourierGLWECiphertext[T], d int, ctOut FourierGLWECiphertext[T]) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermuteSubFourierPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} diff --git a/mktfhe/glwe_ops.go b/mktfhe/glwe_ops.go index 7193033..b939b99 100644 --- a/mktfhe/glwe_ops.go +++ b/mktfhe/glwe_ops.go @@ -201,3 +201,50 @@ func (e *Evaluator[T]) MonomialMulSubGLWEAssign(ct0 GLWECiphertext[T], d int, ct e.BaseSingleKeyEvaluator.PolyEvaluator.MonomialMulSubPolyAssign(ct0.Value[i], d, ctOut.Value[i]) } } + +// PermuteGLWEAssign computes ctOut = ct0(X^d). +// +// ct0 and ctOut should not overlap. For inplace permutation, +// use [*Evaluator.PermuteGLWEInPlace]. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut GLWECiphertext[T]) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermutePolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} + +// PermuteGLWEInPlace computes ct0 = ct0(X^d). +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteGLWEInPlace(ct0 GLWECiphertext[T], d int) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermutePolyInPlace(ct0.Value[i], d) + } +} + +// PermuteAddGLWEAssign computes ctOut += ct0(X^d). +// +// ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteAddGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut GLWECiphertext[T]) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermuteAddPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} + +// PermuteSubGLWEAssign computes ctOut -= ct0(X^d). +// +// ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteSubGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut GLWECiphertext[T]) { + for i := 0; i < e.Parameters.GLWERank()+1; i++ { + e.PolyEvaluator.PermuteSubPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} diff --git a/tfhe/fourier_glwe_ops.go b/tfhe/fourier_glwe_ops.go index 4a47e6f..accacb4 100644 --- a/tfhe/fourier_glwe_ops.go +++ b/tfhe/fourier_glwe_ops.go @@ -160,3 +160,50 @@ func (e *Evaluator[T]) FourierPolyMulSubFourierGLWEAssign(ct0 FourierGLWECiphert e.PolyEvaluator.MulSubFourierPolyAssign(ct0.Value[i], fp, ctOut.Value[i]) } } + +// PermuteGLWEAssign computes ctOut = ct0(X^d). +// +// ct0 and ctOut should not overlap. For inplace permutation, +// use [*Evaluator.PermuteFourierGLWEInPlace]. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteFourierGLWEAssign(ct0 FourierGLWECiphertext[T], d int, ctOut FourierGLWECiphertext[T]) { + for i := 0; i < e.Parameters.glweRank+1; i++ { + e.PolyEvaluator.PermuteFourierPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} + +// PermuteGLWEInPlace computes ct0 = ct0(X^d). +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteFourierGLWEInPlace(ct0 FourierGLWECiphertext[T], d int) { + for i := 0; i < e.Parameters.glweRank+1; i++ { + e.PolyEvaluator.PermuteFourierPolyInPlace(ct0.Value[i], d) + } +} + +// PermuteAddGLWEAssign computes ctOut += ct0(X^d). +// +// ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteAddFourierGLWEAssign(ct0 FourierGLWECiphertext[T], d int, ctOut FourierGLWECiphertext[T]) { + for i := 0; i < e.Parameters.glweRank+1; i++ { + e.PolyEvaluator.PermuteAddFourierPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} + +// PermuteSubGLWEAssign computes ctOut -= ct0(X^d). +// +// ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. +func (e *Evaluator[T]) PermuteSubFourierGLWEAssign(ct0 FourierGLWECiphertext[T], d int, ctOut FourierGLWECiphertext[T]) { + for i := 0; i < e.Parameters.glweRank+1; i++ { + e.PolyEvaluator.PermuteSubFourierPolyAssign(ct0.Value[i], d, ctOut.Value[i]) + } +} diff --git a/tfhe/glwe_ops.go b/tfhe/glwe_ops.go index 34f52f2..85a98dc 100644 --- a/tfhe/glwe_ops.go +++ b/tfhe/glwe_ops.go @@ -213,6 +213,9 @@ func (e *Evaluator[T]) PermuteGLWE(ct0 GLWECiphertext[T], d int) GLWECiphertext[ // // ct0 and ctOut should not overlap. For inplace permutation, // use [*Evaluator.PermuteGLWEInPlace]. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. func (e *Evaluator[T]) PermuteGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut GLWECiphertext[T]) { for i := 0; i < e.Parameters.glweRank+1; i++ { e.PolyEvaluator.PermutePolyAssign(ct0.Value[i], d, ctOut.Value[i]) @@ -220,6 +223,9 @@ func (e *Evaluator[T]) PermuteGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut GLW } // PermuteGLWEInPlace computes ct0 = ct0(X^d). +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. func (e *Evaluator[T]) PermuteGLWEInPlace(ct0 GLWECiphertext[T], d int) { for i := 0; i < e.Parameters.glweRank+1; i++ { e.PolyEvaluator.PermutePolyInPlace(ct0.Value[i], d) @@ -229,6 +235,9 @@ func (e *Evaluator[T]) PermuteGLWEInPlace(ct0 GLWECiphertext[T], d int) { // PermuteAddGLWEAssign computes ctOut += ct0(X^d). // // ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. func (e *Evaluator[T]) PermuteAddGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut GLWECiphertext[T]) { for i := 0; i < e.Parameters.glweRank+1; i++ { e.PolyEvaluator.PermuteAddPolyAssign(ct0.Value[i], d, ctOut.Value[i]) @@ -238,6 +247,9 @@ func (e *Evaluator[T]) PermuteAddGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut // PermuteSubGLWEAssign computes ctOut -= ct0(X^d). // // ct0 and ctOut should not overlap. +// +// Panics when d is not odd. +// This is because the permutation is not bijective when d is even. func (e *Evaluator[T]) PermuteSubGLWEAssign(ct0 GLWECiphertext[T], d int, ctOut GLWECiphertext[T]) { for i := 0; i < e.Parameters.glweRank+1; i++ { e.PolyEvaluator.PermuteSubPolyAssign(ct0.Value[i], d, ctOut.Value[i])