-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathij_vector.cpp
339 lines (268 loc) · 7.6 KB
/
ij_vector.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
#include"ij_vector.h"
void ijvec_set_i(ij_vec& v, GF2X& vec_i)
{
v=GF2X_to_uint64_t(vec_i);
}
void ijvec_set_j(ij_vec& v, GF2X& vec_j, long I)
{
GF2X f=vec_j;
f=LeftShift(f,I);
v=GF2X_to_uint64_t(vec_j);
}
void ijvec_set_i_j(ij_vec& v, GF2X& vec_i, GF2X& vec_j, long I)
{
ij_vec ii,jj;
ijvec_set_i(ii,vec_i);
ijvec_set_j(jj,vec_j,I);
v=ii+jj;
}
void ijvec_set_zero(ij_vec& v)
{
v=0;
}
/* void ijvec_get_i(GF2X& vec_i, ij_vec v, long I)
{
for future purpose
}
void ijvec_get_j(GF2X& vec_j, ij_vec v, long I)
{
for future purpose
}
void ijvec_get_i_j(GF2X& vec_i, GF2X& vec_j, ij_vec v v, long I)
{
for future purpose
}*/
// Return a strict higher bound on the position, given the degree bounds
// I and J.
ijpos_t ijvec_get_max_pos(long I, long J)
{
GF2X f;
set(f);
f=LeftShift(f,I+J);
return GF2X_to_uint64_t(f);
}
// Return the position corresponding to an (i,j)-vector.
ijpos_t ijvec_get_pos(ij_vec& v, long I, long J)
{
return v;
}
// Return the starting position of the line corresponding to j.
// Once i is known, just add the offset ijvec_get_offset(i, I) to compute the
// full position of the vector (i,j).
ijpos_t ijvec_get_start_pos(GF2X& vec_j, long I, long J)
{
GF2X f;
f=vec_j;
f=LeftShift(f,I);
return GF2X_to_uint64_t(f);
}
// Return the position offset corresponding to i.
ijpos_t ijvec_get_offset(GF2X& vec_i, unsigned I)
{
GF2X f;
f=vec_i;
return GF2X_to_uint64_t(f);
}
ij_vec ijvec_add(ij_vec v,ij_vec j)
{
GF2X vec=uint64_t_to_GF2X(v);
GF2X b=uint64_t_to_GF2X(j);
GF2X a;
add(a,vec,j);
ij_vec res=GF2X_to_uint64_t(a);
return res;
}
// Convert a position to an (i,j)-vector.
// Return 1 if successful.
/* int ijvec_set_pos(ij_vec& v, ijpos_t pos, long I, long J)
{
for future purpose
}*/
ij_vec ijvec_mul_ti(ij_vec v,long I )
{
ij_vec res;
GF2X f=uint64_t_to_GF2X(v);
f=LeftShift(f,I);
res=GF2X_to_uint64_t(f);
return res;
}
void ij_set_ti(GF2X& f,long i)
{
GF2X t;
set(t);
t=LeftShift(t,i);
f=t;
t.kill();
}
int ij_monic_set_next_return(GF2X& f,GF2X& vec_j,long j)
{
uint32_t temp=GF2X_to_uint32_t(vec_j);
temp=temp+1;
f=uint32_t_to_GF2X(temp);
return (int)temp;
}
void ij_monic_set_next(GF2X& f,GF2X& vec_j,long j)
{
uint32_t temp=GF2X_to_uint32_t(vec_j);
temp=temp+1;
f=uint32_t_to_GF2X(temp);
}
int ij_set_next_return (GF2X& f,GF2X& vec_i,long i)
{
uint32_t temp=GF2X_to_uint32_t(vec_i);
temp=temp+1;
f=uint32_t_to_GF2X(temp);
return (int)temp;
}
void ij_set_next(GF2X& f,GF2X& vec_i,long i)
{
uint32_t temp=GF2X_to_uint32_t(vec_i);
temp=temp+1;
f=uint32_t_to_GF2X(temp);
}
int ij_in_fp(GF2X& vec_i)
{
long d=deg(vec_i);
if(d<=0)
return 1;
else
return 0;
}
/* Basis of the p-lattice seen as a GF(p)-vector space of (i,j)-vectors.
*****************************************************************************/
// Fill the basis with the vectors (i*t^k, j*t^k) as long as their degrees
// stay below the given bounds.
long fill_gap(ij_vec *v, GF2X& vec_i, GF2X& vec_j,long max_deg_i, long max_deg_j, long I)
{
long deg_i = deg(vec_i);
long deg_j = deg(vec_j);
long d_i = max_deg_i - deg_i;
long d_j = max_deg_j - deg_j;
long n = deg_i < 0 ? d_j : min(d_i, d_j);
if (n <= 0)
return 0;
GF2X ii, jj;
ii=vec_i;
jj=vec_j;
ijvec_set_i_j(v[0], ii, jj, I);
for (int k = 1; k < n; ++k)
v[k]=ijvec_mul_ti(v[k-1], 1);
return n;
}
unsigned fill_euclid(ij_vec *v, GF2X& vec_i, GF2X& vec_j,long max_deg_i,long max_deg_j, long I)
{
if ((deg(vec_i) < max_deg_i) && (deg(vec_j) < max_deg_j))
{
GF2X ii, jj;
ii=vec_i;
jj=vec_j;
ijvec_set_i_j(v[0], ii, jj, I);
return 1;
}
return 0;
}
// Compute the (i,j)-basis of a given p-lattice.
// Small case.
void ijbasis_compute_small(Vec<GF2X>& basis, Vec<GF2X>& adjustment_basis,
small_ideal_t& gothp, GF2X lambda,long I, long J)
{
long L = gothp.degq;
// First the canonical basis:
// Basis is { ( q*t^k, 0 ) : k in [0..I-L-1] } join
// { (lambda*t^k mod q, t^k) : k in [0..J-1] }.
// The J vectors are not stored, however.
long k = 0;
basis[k]=gothp.q;
while (++k < I-L)
basis[k]=LeftShift(basis[k-1], 1);
basis[k]=lambda;
while (++k < I+J-L)
basis[k]=(LeftShift(basis[k-1],1)) % basis[0];
// Transform the second part into triangular instead of diagonal (on
// the j part) and construct the adjustment part.
GF2 one, two;
one=1;
two=0;
for (unsigned k = 0; k < J; ++k)
adjustment_basis[k]=basis[I-L+k]*two;
for (unsigned k = I-L+1; k < I+J-L; ++k)
basis[k]=basis[k]+basis[k-1];
}
void specific_euclid_char2(Vec<ij_vec>& basis, unsigned *basis_dim,unsigned I, unsigned J,
Vec<ij_vec>& euclid, unsigned *euclid_dim,unsigned hatI,unsigned hatJ,
GF2X& alpha_0, GF2X& beta_0,
GF2X& alpha_1, GF2X& beta_1)
{
uint64_t v0, v1;
uint32_t alpha0,alpha1,beta0,beta1;
alpha0=GF2X_to_uint32_t(alpha_0);
alpha1=GF2X_to_uint32_t(alpha_1);
beta0 =GF2X_to_uint32_t(beta_0);
beta1 =GF2X_to_uint32_t(beta_1);
v0= alpha0 | ((uint64_t)beta0 << 32);
v1 = alpha1 | ((uint64_t)beta1 << 32);
long da0, da1;
da0 = deg(alpha_0);
da1 = deg(alpha_1);
GF2X f=uint64_t_to_GF2X(v1);
while (deg(f) < 32+J && da1 >= 0)
{
// alpha0 = alpha0 mod alpha1 (and betas follow)
uint64_t mask = ((1U<<(da0+1))-1) ^ ((1U<<da1)-1);
uint64_t shiftv1 = v1 << (da0-da1);
uint64_t mask1 = -(uint64_t)1;
uint64_t maskbit = 1U<<da0;
do {
v0 ^= shiftv1 & mask1;
if (!(v0 & mask))
break;
maskbit >>= 1;
mask1 = (v0 & maskbit) ? (-(uint64_t)1) : 0;
shiftv1 >>= 1;
} while (1);
uint64_t_swap(&v0, &v1);
da0 = da1;
f=uint64_t_to_GF2X(v1);
da1 =deg(f);
// fill gap
uint32_t al1, be1;
al1 =(uint32_t)v1;
be1 = (uint32_t)(((uint32_t)v1)+1);
GF2X al_1,be_1;
al_1=uint32_t_to_GF2X(al1);
be_1=uint32_t_to_GF2X(be1);
Vec<ij_vec>::iterator bs = basis.begin() ;
Vec<ij_vec>::iterator eu = euclid.begin() ;
*basis_dim += fill_gap (bs +*basis_dim, al_1, be_1,
min(da0, (long)I), J, I);
//if (euclid != NULL)
*euclid_dim += fill_euclid(eu+*euclid_dim, al_1, be_1,
hatI, hatJ, hatI);
}
}
// Compute the (i,j)-basis of a given p-lattice.
// Large case.
void ijbasis_compute_large(Vec<ij_vec>& basis, unsigned *basis_dim,
unsigned I, unsigned J,
Vec<ij_vec>& euclid, unsigned *euclid_dim,
unsigned hatI, unsigned hatJ,
large_ideal_t *gothp, GF2X lambda)
{
// Basis is obtained from an Euclidian algorithm on
// (p, 0) and (lambda, 1).
GF2X alpha_0, beta_0, alpha_1, beta_1;
alpha_0=gothp->p;
clear(beta_0);
alpha_1=lambda;
set(beta_1);
*basis_dim = fill_gap(basis.begin(), alpha_1, beta_1, I, J, I);
*euclid_dim = fill_euclid(euclid.begin(), alpha_1, beta_1, hatI, hatJ, hatI);
specific_euclid_char2(basis, basis_dim, I, J,
euclid, euclid_dim, hatI, hatJ,
alpha_0, beta_0, alpha_1, beta_1);
}