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