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
#include <assert.h>
23
#include <fstream>
24
#include <iostream>
25
#include <sstream>
26
using std::ostringstream;
27
#include <NTL/lzz_p.h>
28
#include <NTL/lzz_pE.h>
29
#include <NTL/lzz_pX.h>
30
#include <NTL/ZZ.h>
31
32
#include "helper.h"
33
#include "lzz_pEExtra.h"
34
35
NTL_CLIENT
36
37
static long gcd(long a, long b)
38
{
39
if (b < 0) return gcd(a, -b);
40
if (a < b) return gcd(b, a);
41
if (b == 0) return a;
42
return gcd(b, a%b);
43
44
}
45
46
// suppose d divides q-1 and let chi : F_q^* --> Z/d be the
47
// composition of x|-->x^{(q-1)/d} and a chosen isomorphism
48
// F_q^*/F_q^{*d} --> Z/d;
49
// let z1,z2 be independent generic elements
50
// satisfying z1^d=z2^d=1. we calculate the 'abstract'
51
// Jacobi sum
52
//
53
// J(d,q) = sum_{x!=0,1} z1^{chi(x)}*z2^{chi(1-x)}
54
//
55
// we return the result as a (d x d) array of ZZ's
56
// (i.e. ZZ[d][d]).
57
//
58
// - we canonically choose the isomorphism used to construct
59
// chi
60
// - a different choice of chi leads to J(d,q) with z1,z2
61
// replaced by z1^e,z2^e, for some e in (Z/d)^*.
62
// - by choosing dth roots of unity z1,z2, we get an actual
63
// Jacobi sum
64
65
void jacobi_sum(ZZ ***sum, long d)
66
{
67
long q, e;
68
q = to_long(zz_pE::cardinality());
69
70
assert((q-1) % d == 0);
71
e = (q-1)/d;
72
73
// find an element x so x^{(q-1)/d} generates mu_d
74
zz_pE x, y, z;
75
x = 1;
76
while (true) {
77
int r;
78
r = inc(x);
79
assert(r == NO_CARRY);
80
81
power(y, x, e);
82
power(z, y, d);
83
assert(z == 1);
84
85
int i;
86
z = y;
87
for (i = 1; z != 1; i++)
88
z *= y;
89
assert(d % i == 0);
90
91
if (i < d)
92
continue;
93
94
break;
95
}
96
97
// enumerate elements of mu_d
98
unsigned long ul_mu[d];
99
100
y = 1;
101
power(z, x, e);
102
for (int i = 0; i < d; i++) {
103
assert((i == 0 && y == 1) || (i != 0 && y != 1));
104
ul_mu[i] = to_ulong(y);
105
y *= z;
106
}
107
108
// calculate log of Artin character y|-->y^{(q-1)/d_}
109
unsigned long ul_y;
110
int log[q];
111
112
x = 1;
113
do {
114
power(y, x, e);
115
power(z, y, d);
116
assert(z == 1);
117
118
ul_y = to_ulong(y);
119
120
int i;
121
for (i = 0; i < d; i++)
122
if (ul_mu[i] == ul_y)
123
break;
124
assert(i < d);
125
126
log[to_ulong(x)] = i;
127
} while (inc(x) == NO_CARRY);
128
129
for (int i = 0; i < d; i++)
130
for (int j = 0; j < d; j++)
131
sum[i][j][0] = 0;
132
133
// compute Jacobi sum as element in Z[z]/(z^d-1)
134
unsigned long u1, u2;
135
long l1, l2;
136
x = 0;
137
do {
138
// if (true) {
139
// add(y, x, 1);
140
// mul(z, y, -1);
141
// } else {
142
sub(y, x, 1);
143
mul(z, y, -1);
144
// }
145
146
if (x == 0 || z == 0)
147
continue;
148
149
u1 = to_ulong(x);
150
u2 = to_ulong(z);
151
152
l1 = log[u1];
153
l2 = log[u2];
154
sum[l1][l2][0]++;
155
} while (inc(x) == NO_CARRY);
156
}
157
158
#ifdef MAIN
159
int main(int argc, char **argv)
160
{
161
long p, m, e1, e2, d, s, i;
162
ofstream output;
163
164
if (argc != 6) {
165
cerr << "Usage: " << argv[0] << " p m e1 e2 d\n";
166
return -1;
167
}
168
169
p = atol(argv[1]);
170
m = atol(argv[2]);
171
e1 = atol(argv[3]);
172
e2 = atol(argv[4]);
173
d = atol(argv[5]);
174
175
assert(d % p != 0);
176
177
init_NTL_ff(p, m, 1, 1, 1);
178
179
ZZ sum[d];
180
181
jacobi_sum(sum, e1, e2, d);
182
183
for (int i = 0; i < d; i++) {
184
if (i)
185
cout << ", ";
186
cout << sum[i];
187
}
188
cout << endl;
189
190
return 0;
191
}
192
193
#endif
194
195