1 #ifndef TFHE_TEST_ENVIRONMENT
2 /* ***************************************************
3 TGSW fft operations
4 *************************************************** */
5
6 #include <cstdlib>
7 #include <iostream>
8 #include <random>
9 #include <cassert>
10 #include <ccomplex>
11 #include "tfhe_core.h"
12 #include "numeric_functions.h"
13 #include "lweparams.h"
14 #include "lwekey.h"
15 #include "lwesamples.h"
16 #include "lwe-functions.h"
17 #include "tlwe_functions.h"
18 #include "tgsw_functions.h"
19 #include "polynomials_arithmetic.h"
20 #include "lagrangehalfc_arithmetic.h"
21 #include "lwebootstrappingkey.h"
22
23 using namespace std;
24 #else
25 #undef EXPORT
26 #define EXPORT
27 #endif
28
29
30 //constructor content
init_TGswSampleFFT(TGswSampleFFT * obj,const TGswParams * params)31 EXPORT void init_TGswSampleFFT(TGswSampleFFT *obj, const TGswParams *params) {
32 const int32_t k = params->tlwe_params->k;
33 const int32_t l = params->l;
34 TLweSampleFFT *all_samples = new_TLweSampleFFT_array((k + 1) * l, params->tlwe_params);
35 new(obj) TGswSampleFFT(params, all_samples);
36 }
37
38 //destructor content
destroy_TGswSampleFFT(TGswSampleFFT * obj)39 EXPORT void destroy_TGswSampleFFT(TGswSampleFFT *obj) {
40 int32_t k = obj->k;
41 int32_t l = obj->l;
42 delete_TLweSampleFFT_array((k + 1) * l, obj->all_samples);
43 obj->~TGswSampleFFT();
44 }
45
46
47 // For all the kpl TLWE samples composing the TGSW sample
48 // It computes the inverse FFT of the coefficients of the TLWE sample
tGswToFFTConvert(TGswSampleFFT * result,const TGswSample * source,const TGswParams * params)49 EXPORT void tGswToFFTConvert(TGswSampleFFT *result, const TGswSample *source, const TGswParams *params) {
50 const int32_t kpl = params->kpl;
51
52 for (int32_t p = 0; p < kpl; p++)
53 tLweToFFTConvert(result->all_samples + p, source->all_sample + p, params->tlwe_params);
54 }
55
56 // For all the kpl TLWE samples composing the TGSW sample
57 // It computes the FFT of the coefficients of the TLWEfft sample
tGswFromFFTConvert(TGswSample * result,const TGswSampleFFT * source,const TGswParams * params)58 EXPORT void tGswFromFFTConvert(TGswSample *result, const TGswSampleFFT *source, const TGswParams *params) {
59 const int32_t kpl = params->kpl;
60
61 for (int32_t p = 0; p < kpl; p++)
62 tLweFromFFTConvert(result->all_sample + p, source->all_samples + p, params->tlwe_params);
63 }
64
65
66
67 // result = result + H
tGswFFTAddH(TGswSampleFFT * result,const TGswParams * params)68 EXPORT void tGswFFTAddH(TGswSampleFFT *result, const TGswParams *params) {
69 const int32_t k = params->tlwe_params->k;
70 const int32_t l = params->l;
71
72 for (int32_t j = 0; j < l; j++) {
73 Torus32 hj = params->h[j];
74 for (int32_t i = 0; i <= k; i++)
75 LagrangeHalfCPolynomialAddTorusConstant(&result->sample[i][j].a[i], hj);
76 }
77
78 }
79
80 // result = list of TLWE (0,0)
tGswFFTClear(TGswSampleFFT * result,const TGswParams * params)81 EXPORT void tGswFFTClear(TGswSampleFFT *result, const TGswParams *params) {
82 const int32_t kpl = params->kpl;
83
84 for (int32_t p = 0; p < kpl; p++)
85 tLweFFTClear(result->all_samples + p, params->tlwe_params);
86 }
87
88 // External product (*): accum = gsw (*) accum
tGswFFTExternMulToTLwe(TLweSample * accum,const TGswSampleFFT * gsw,const TGswParams * params)89 EXPORT void tGswFFTExternMulToTLwe(TLweSample *accum, const TGswSampleFFT *gsw, const TGswParams *params) {
90 const TLweParams *tlwe_params = params->tlwe_params;
91 const int32_t k = tlwe_params->k;
92 const int32_t l = params->l;
93 const int32_t kpl = params->kpl;
94 const int32_t N = tlwe_params->N;
95 //TODO attention, improve these new/delete...
96 IntPolynomial *deca = new_IntPolynomial_array(kpl, N); //decomposed accumulator
97 LagrangeHalfCPolynomial *decaFFT = new_LagrangeHalfCPolynomial_array(kpl, N); //fft version
98 TLweSampleFFT *tmpa = new_TLweSampleFFT(tlwe_params);
99
100 for (int32_t i = 0; i <= k; i++)
101 tGswTorus32PolynomialDecompH(deca + i * l, accum->a + i, params);
102 for (int32_t p = 0; p < kpl; p++)
103 IntPolynomial_ifft(decaFFT + p, deca + p);
104
105 tLweFFTClear(tmpa, tlwe_params);
106 for (int32_t p = 0; p < kpl; p++) {
107 tLweFFTAddMulRTo(tmpa, decaFFT + p, gsw->all_samples + p, tlwe_params);
108 }
109 tLweFromFFTConvert(accum, tmpa, tlwe_params);
110
111 delete_TLweSampleFFT(tmpa);
112 delete_LagrangeHalfCPolynomial_array(kpl, decaFFT);
113 delete_IntPolynomial_array(kpl, deca);
114 }
115
116 // result = (X^ai -1)*bki
117 /*
118 //This function is not used, but may become handy in a future release
119 //
120 EXPORT void tGswFFTMulByXaiMinusOne(TGswSampleFFT* result, const int32_t ai, const TGswSampleFFT* bki, const TGswParams* params) {
121 const TLweParams* tlwe_params=params->tlwe_params;
122 const int32_t k = tlwe_params->k;
123 //const int32_t l = params->l;
124 const int32_t kpl = params->kpl;
125 const int32_t N = tlwe_params->N;
126 //on calcule x^ai-1 en fft
127 //TODO attention, this prevents parallelization...
128 //TODO: parallelization
129 static LagrangeHalfCPolynomial* xaim1=new_LagrangeHalfCPolynomial(N);
130 LagrangeHalfCPolynomialSetXaiMinusOne(xaim1,ai);
131 for (int32_t p=0; p<kpl; p++) {
132 const LagrangeHalfCPolynomial* in_s = bki->all_samples[p].a;
133 LagrangeHalfCPolynomial* out_s = result->all_samples[p].a;
134 for (int32_t j=0; j<=k; j++)
135 LagrangeHalfCPolynomialMul(&out_s[j], xaim1, &in_s[j]);
136 }
137 }
138 */
139
140 //-------------------------------------------------------------------------------------
141 // autogenerated memory-related functions
142 //-------------------------------------------------------------------------------------
143
144 USE_DEFAULT_CONSTRUCTOR_DESTRUCTOR_IMPLEMENTATIONS1(TGswSampleFFT, TGswParams);
145
146 //
147 //----------------------------------------------------------------------------------------
148
149
150
151
152
153
154
155 #if 0
156 // BOOTSTRAPPING (as in CGGI16b - algo 3)
157 // - modswitch: torus coefs multiplied by N/2
158 // - set the test vector
159 // - blind rotation by the phase
160 // - sample extract
161 // - keyswitch
162 EXPORT void tfhe_bootstrapFFT(LweSample* result, const LweBootstrappingKeyFFT* bk, Torus32 mu1, Torus32 mu0, const LweSample* x){
163 const Torus32 ab=(mu1+mu0)/2;
164 const Torus32 aa = mu0-ab; // aa=(mu1-mu0)/2;
165 const TGswParams* bk_params = bk->bk_params;
166 const TLweParams* accum_params = bk_params->tlwe_params;
167 const LweParams* extract_params = &accum_params->extracted_lweparams;
168 const LweParams* in_out_params = bk->in_out_params;
169 const int32_t n=in_out_params->n;
170 const int32_t N=accum_params->N;
171 const int32_t Ns2=N/2;
172 const int32_t Nx2= 2*N;
173
174
175 // Set the test vector (aa + aaX + ... + aaX^{N/2-1} -aaX^{N/2} - ... -aaX^{N-1})*X^{b}
176 TorusPolynomial* testvect=new_TorusPolynomial(N);
177 TorusPolynomial* testvectbis=new_TorusPolynomial(N);
178
179 int32_t barb=modSwitchFromTorus32(x->b,Nx2);
180 //je definis le test vector (multiplié par a inclus !
181 for (int32_t i=0;i<Ns2;i++)
182 testvect->coefsT[i]=aa;
183 for (int32_t i=Ns2;i<N;i++)
184 testvect->coefsT[i]=-aa;
185 torusPolynomialMulByXai(testvectbis, barb, testvect);
186
187
188
189 // Accumulateur acc = fft((0, testvect))
190 TLweSample* acc = new_TLweSample(accum_params);
191
192 // acc will be used for tfhe_bootstrapFFT, acc1=acc will be used for tfhe_bootstrap
193 tLweNoiselessTrivial(acc, testvectbis, accum_params);
194
195 TGswSample* temp = new_TGswSample(bk_params);
196 TGswSampleFFT* tempFFT = new_TGswSampleFFT(bk_params);
197
198
199 // Blind rotation
200 //NICOLAS: j'ai ajouté ce bloc
201 #ifndef NDEBUG
202 TorusPolynomial* phase = new_TorusPolynomial(N);
203 int32_t correctOffset = barb;
204 cout << "starting the test..." << endl;
205 #endif
206 // the index 1 is given when we don't use the fft
207 for (int32_t i=0; i<n; i++) {
208 int32_t bara=modSwitchFromTorus32(-x->a[i],Nx2);
209
210 if (bara!=0) {
211 tGswFFTMulByXaiMinusOne(tempFFT, bara, bk->bkFFT+i, bk_params);
212 tGswFFTAddH(tempFFT, bk_params);
213 tGswFFTExternMulToTLwe(acc, tempFFT, bk_params);
214 }
215
216 //NICOLAS: et surtout, j'ai ajouté celui-ci!
217 #ifndef NDEBUG
218 tLwePhase(phase,acc,debug_accum_key); //celui-ci, c'est la phase de acc (FFT)
219 if (debug_in_key->key[i]==1) correctOffset = (correctOffset+bara)%Nx2;
220 torusPolynomialMulByXai(testvectbis, correctOffset, testvect); //celui-ci, c'est la phase idéale (calculée sans bruit avec la clé privée)
221 for (int32_t j=0; j<N; j++) {
222 printf("Iteration %d, index %d: phase %d vs noiseless %d\n",i,j,phase->coefsT[j], testvectbis->coefsT[j]);
223 }
224 #endif
225
226 }
227
228
229 // Sample extract
230 LweSample* u = new_LweSample(extract_params);
231 tLweExtractLweSample(u, acc, extract_params, accum_params);
232 u->b += ab;
233
234
235 // KeySwitching
236 lweKeySwitch(result, bk->ks, u);
237
238
239
240 delete_LweSample(u);
241 delete_TGswSampleFFT(tempFFT);
242 delete_TGswSample(temp);
243 delete_TLweSample(acc);
244 delete_TorusPolynomial(testvectbis);
245 delete_TorusPolynomial(testvect);
246 }
247 #endif
248
249 #undef INCLUDE_ALL
250