Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241782 views
1
/*********************************************************************
2
3
(c) Copyright 2006-2010 Salman Baig and Chris Hall
4
5
This file is part of ELLFF
6
7
ELLFF is free software: you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation, either version 3 of the License, or
10
(at your option) any later version.
11
12
ELLFF is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
16
17
You should have received a copy of the GNU General Public License
18
along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
*********************************************************************/
21
22
//
23
// helper routines for L-function computations
24
//
25
// - induced ordering on elements of: F_p[x], F_q, F_q[x]
26
// - converting elements to unsigned longs: F_p[x], F_q(, F_q[x])
27
// - enumerating elements: F_p[x], F_q(, F_q[x])
28
// - evaluating elements of F_q[x] at elements of F_q
29
// - exponentiation in F_q^*
30
31
#include <assert.h>
32
#include <stdio.h>
33
#include <stdlib.h>
34
#include <string.h>
35
#include <math.h>
36
#include <NTL/ZZX.h>
37
#include <NTL/lzz_p.h>
38
#include <NTL/lzz_pE.h>
39
#include <NTL/lzz_pX.h>
40
#include <NTL/lzz_pEX.h>
41
#include <NTL/lzz_pXFactoring.h>
42
#include <NTL/lzz_pX.h>
43
44
#include "helper.h"
45
#include "lzz_pEExtra.h"
46
47
NTL_CLIENT
48
49
///////////////////////////////////////////////////////////////////////////
50
51
zz_pEExtraInfoPtr zz_pEExtraInfo = NULL;
52
53
///////////////////////////////////////////////////////////////////////////
54
55
zz_pEExtraInfoT::zz_pEExtraInfoT(int precompute_inverses,
56
int precompute_square_roots, int precompute_legendre_char,
57
int precompute_pth_frobenius_map)
58
{
59
int p = zz_p::modulus();
60
q = to_long(zz_pE::cardinality());
61
62
ref_count = 1;
63
64
inv_table = precompute_inverses ? new invTable(q) : NULL;
65
root_table = precompute_square_roots ? new rootTable(q) : NULL;
66
legendre_table = precompute_legendre_char ? new legendreChar(q) : NULL;
67
frob_map = precompute_pth_frobenius_map ? new frobeniusMap(q) : NULL;
68
69
// precompute a non-square in F_q
70
zz_pE x, y;
71
do {
72
x = random_zz_pE();
73
} while(x == 0 || legendre_char(x) == 1);
74
non_square = x;
75
76
// precompute image of basis 1,x^1,...,x^{d-1} under Frobenius
77
frob_of_basis = new zz_pE[zz_pE::degree()];
78
x = 0;
79
SetCoeff(x.LoopHole(), 1, 1);
80
frob_of_basis[0] = 1;
81
for (int i = 1; i < zz_pE::degree(); i++) {
82
power(y, x, i);
83
power(frob_of_basis[i], y, p);
84
}
85
}
86
87
zz_pEExtraInfoT::~zz_pEExtraInfoT()
88
{
89
if (inv_table != NULL) delete inv_table;
90
if (root_table != NULL) delete root_table;
91
if (legendre_table != NULL) delete legendre_table;
92
if (frob_map != NULL) delete frob_map;
93
94
delete [] frob_of_basis;
95
}
96
97
void CopyPointer(zz_pEExtraInfoPtr& dst, zz_pEExtraInfoPtr src)
98
{
99
if (src == dst) return;
100
101
if (dst) {
102
dst->ref_count--;
103
104
if (dst->ref_count < 0)
105
Error("internal error: negative zz_pEExtraInfoT ref_count");
106
107
if (dst->ref_count == 0) delete dst;
108
}
109
110
if (src) {
111
if (src->ref_count == NTL_MAX_LONG)
112
Error("internal error: zz_pEExtraInfoT ref_count overflow");
113
114
src->ref_count++;
115
}
116
117
dst = src;
118
}
119
120
///////////////////////////////////////////////////////////////////////////
121
// table of square roots
122
///////////////////////////////////////////////////////////////////////////
123
124
zz_pEExtraInfoT::rootTable::rootTable(long q)
125
{
126
zz_pE x, x_sqr;
127
x = 0;
128
table = new zz_pE[q];
129
do {
130
x_sqr = sqr(x);
131
table[to_ulong(x_sqr)] = x;
132
} while (inc(x) == NO_CARRY);
133
}
134
135
zz_pEExtraInfoT::rootTable::~rootTable()
136
{
137
delete table;
138
}
139
140
///////////////////////////////////////////////////////////////////////////
141
// compute square root
142
///////////////////////////////////////////////////////////////////////////
143
144
zz_pE zz_pEExtraInfoT::square_root(zz_pE& x)
145
{
146
if (root_table != NULL)
147
return root_table->table[to_ulong(x)];
148
149
if (q % 4 == 3)
150
return power(x, (q+1)/4);
151
152
zz_pE r, s, v, w;
153
154
// compute square root using Tonelli-Shanks
155
long e;
156
int ord_2;
157
for (e = (q-1)/2, ord_2 = 1; e % 2 == 0; ord_2++)
158
e /= 2;
159
160
v = power(non_square, e);
161
r = power(x, (e+1)/2);
162
163
int i;
164
while (1) {
165
s = r*r/x;
166
for (i = 0; s != 1; i++)
167
s = sqr(s);
168
assert(i < ord_2);
169
170
if (i == 0)
171
return r;
172
173
w = v;
174
while (i++ < ord_2-1)
175
w = sqr(w);
176
r = r*w;
177
}
178
179
assert(r*r == x);
180
181
return r;
182
}
183
184
///////////////////////////////////////////////////////////////////////////
185
// compute Legendre character
186
///////////////////////////////////////////////////////////////////////////
187
188
int zz_pEExtraInfoT::legendre_char(zz_pE& x)
189
{
190
if (legendre_table != NULL)
191
return legendre_table->table[to_ulong(x)];
192
193
static zz_pE y;
194
195
assert(x != 0);
196
y = power(x, (q-1)/2);
197
assert(y == 1 || y == -1);
198
199
return (y == 1);
200
}
201
202
///////////////////////////////////////////////////////////////////////////
203
// table of Legendre character values
204
///////////////////////////////////////////////////////////////////////////
205
206
zz_pEExtraInfoT::legendreChar::legendreChar(long q)
207
{
208
zz_pE x, y;
209
table = (char*)malloc(sizeof(char)*q);
210
memset(table, 0, sizeof(char)*q);
211
x = 0;
212
while (inc(x) == NO_CARRY) { // loop over non-zero values
213
y = x*x;
214
table[to_ulong(y)] = 1; // 1 square, 0 non-square (or 0)
215
}
216
}
217
218
zz_pEExtraInfoT::legendreChar::~legendreChar()
219
{
220
free(table);
221
}
222
223
///////////////////////////////////////////////////////////////////////////
224
// table of multiplicative inverses
225
///////////////////////////////////////////////////////////////////////////
226
227
zz_pEExtraInfoT::invTable::invTable(long q)
228
{
229
zz_pE x;
230
table = new zz_pE[q];
231
while (inc(x) == NO_CARRY) // loop over non-zero values
232
table[to_ulong(x)] = 1/x;
233
}
234
235
zz_pEExtraInfoT::invTable::~invTable()
236
{
237
delete table;
238
}
239
240
///////////////////////////////////////////////////////////////////////////
241
// pth Frobenius map
242
///////////////////////////////////////////////////////////////////////////
243
244
// y = x^p
245
246
void zz_pEExtraInfoT::frobenius(zz_pE&x, zz_pE&y)
247
{
248
zz_pE z;
249
zz_pX f = x.LoopHole();
250
for (int i = 0; i <= deg(f); i++)
251
z += coeff(f, i) * frob_of_basis[i];
252
y = z;
253
}
254
255
unsigned long zz_pEExtraInfoT::frobenius(unsigned long x)
256
{
257
if (frob_map != NULL)
258
return frob_map->map[x];
259
260
zz_pE _x, _y;
261
262
from_ulong(x, _x);
263
frobenius(_x, _y);
264
return to_ulong(_y);
265
}
266
267
zz_pEExtraInfoT::frobeniusMap::frobeniusMap(long q)
268
{
269
zz_pE x, y;
270
int p = zz_p::modulus();
271
272
map = (unsigned long*)malloc(sizeof(unsigned long)*q);
273
do {
274
power(y, x, p);
275
map[to_ulong(x)] = to_ulong(y);
276
} while (inc(x) == NO_CARRY);
277
}
278
279
zz_pEExtraInfoT::frobeniusMap::~frobeniusMap()
280
{
281
free(map);
282
}
283
284
///////////////////////////////////////////////////////////////////////////
285
286
zz_pEExtraContext::zz_pEExtraContext(int precompute_inverses,
287
int precompute_square_roots, int precompute_legendre_char,
288
int precompute_pth_frobenius_map)
289
{
290
ptr = new zz_pEExtraInfoT(precompute_inverses,
291
precompute_square_roots,
292
precompute_legendre_char,
293
precompute_pth_frobenius_map);
294
}
295
296
zz_pEExtraContext::zz_pEExtraContext(const zz_pEExtraContext& a)
297
{
298
ptr = NULL;
299
CopyPointer(ptr, a.ptr);
300
}
301
302
zz_pEExtraContext& zz_pEExtraContext::operator=(const zz_pEExtraContext& a)
303
{
304
CopyPointer(ptr, a.ptr);
305
return *this;
306
}
307
308
zz_pEExtraContext::~zz_pEExtraContext()
309
{
310
CopyPointer(ptr, NULL);
311
}
312
313
void zz_pEExtraContext::save()
314
{
315
CopyPointer(ptr, zz_pEExtraInfo);
316
}
317
318
void zz_pEExtraContext::restore() const
319
{
320
CopyPointer(zz_pEExtraInfo, ptr);
321
}
322
323
324