Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
241818 views
1
#include <stdlib.h>
2
#include <stdio.h>
3
#include <ctype.h>
4
#include <math.h>
5
#include <time.h>
6
#include <string.h>
7
#include <limits.h>
8
#include <unistd.h>
9
#include "gmp.h"
10
#include "mpzutil.h"
11
#include "cstd.h"
12
13
/*
14
Copyright 2007 Andrew V. Sutherland
15
16
This file is part of smalljac.
17
18
smalljac is free software: you can redistribute it and/or modify
19
it under the terms of the GNU General Public License as published by
20
the Free Software Foundation, either version 2 of the License, or
21
(at your option) any later version.
22
23
smalljac is distributed in the hope that it will be useful,
24
but WITHOUT ANY WARRANTY; without even the implied warranty of
25
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26
GNU General Public License for more details.
27
28
You should have received a copy of the GNU General Public License
29
along with smalljac. If not, see <http://www.gnu.org/licenses/>.
30
*/
31
32
// This module is a grab-bag of stuff, not all of which has anything to do with
33
// large integer arithmetic (mpx). This module should be split up and refined
34
35
36
#define MPZ_MAX_TINY_PRIME 251
37
#define MPZ_MAX_TINY_INTEGER 255
38
#define MPZ_TINY_PRIMES 54
39
40
41
#define _abs(a) ((a)<0?-(a):(a))
42
43
#define expr_valid_op(op) ((op) == 'E' || (op) == 'e' || (op) == '*' || (op) == '+' || (op) == '-')
44
45
static mpz_t mpz_util_primorial;
46
unsigned short mpz_util_primes[MPZ_SMALL_PRIMES+1];
47
unsigned short mpz_util_prime_index[MPZ_MAX_SMALL_INTEGER+1];
48
static mpz_t mpz_util_max_prime;
49
static mpz_t _mpz_temp;
50
static unsigned char mpz_small_factors[MPZ_MAX_SMALL_INTEGER+1];
51
unsigned short mpz_small_primorial_map[MPZ_SMALL_PRIMORIAL]; // i-th entry is 0 if gcd(i,MPZ_SMALL_PRIMORIAL)>1, otherwise it indicates that i is the k-th integer in F_P*, where 1 is the 1st.
52
53
int mpz_max_primorial_w;
54
unsigned long mpz_primorials[MPZ_MAX_PRIMORIAL_W+1];
55
unsigned long mpz_primorial_phis[MPZ_MAX_PRIMORIAL_W+1];
56
wheel_t mpz_small_wheels[MPZ_SMALL_PRIMORIAL_W+1];
57
58
static unsigned char _wheel_gaps0[1] = { 1 }; // The trivial wheel - every number is relatively prime to 1
59
static unsigned char _wheel_gaps1[2] = { 2 }; // The first wheel - odd numbers
60
static unsigned char _small_map[MPZ_MAX_SMALL_INTEGER+1];
61
62
#define MPZ_PP_TABSIZE 28
63
64
static struct {
65
unsigned short i0, i1, i2; // m0 contains product of primes with index in (i0,i1], m covers (i0,i2] and m = m0*m1
66
unsigned short unsused;
67
unsigned long b; // any composite below b contains a prime factor with index <= i2
68
mpz_t m0, m;
69
} _pptab[MPZ_PP_TABSIZE];
70
71
unsigned long _mpz_randomf (mpz_t o, mpz_t N, mpz_t factors[], mpz_ftree_t factor_trees[], unsigned long w);
72
int mpz_pollard_rho (mpz_t d, mpz_t n);
73
74
static gmp_randstate_t mpz_util_rands;
75
static int mpz_util_inited;
76
77
void mpz_util_init ()
78
{
79
unsigned char *mp, *np;
80
unsigned i, j, k, n, p, maxp, w, gap, maxgap;
81
unsigned long x;
82
unsigned char *_small_map;
83
84
if ( mpz_util_inited ) return;
85
mpz_init (_mpz_temp);
86
87
// i-th entry of small factors array holds a prime divisor of i for composite i, 0 o.w.
88
for ( i = 2 ; i <= MPZ_MAX_TINY_PRIME ; ) {
89
n = MPZ_MAX_SMALL_INTEGER / i;
90
for ( j = 2 ; j <= n ; j++ ) {
91
mpz_small_factors[i*j] = (unsigned char)i;
92
}
93
i++;
94
while ( mpz_small_factors[i] ) i++;
95
}
96
97
// run through them in reverse order so that array holds the smallest prime divisor - more convenient for factoring
98
for ( i = MPZ_MAX_TINY_PRIME ; i >= 2 ; ) {
99
n = MPZ_MAX_SMALL_INTEGER / i;
100
for ( j = 2 ; j <= n ; j++ ) {
101
mpz_small_factors[i*j] = (unsigned char)i;
102
}
103
i--;
104
while ( mpz_small_factors[i] ) i--;
105
}
106
107
mpz_primorials[0] = 1;
108
mpz_primorial_phis[0] = 1;
109
mpz_primorials[1] = 2;
110
mpz_primorial_phis[1] = 1;
111
mpz_small_wheels[0].n = 1;
112
mpz_small_wheels[0].phi = 1;
113
mpz_small_wheels[0].gaps = _wheel_gaps0;
114
mpz_small_wheels[1].n = 2;
115
mpz_small_wheels[1].phi = 1;
116
mpz_small_wheels[1].gaps = _wheel_gaps1;
117
_small_map = (unsigned char *) mem_alloc (MPZ_MAX_SMALL_INTEGER+1);
118
_small_map[1] = 1; // roll the first to prime the pump
119
_small_map[3] = 1;
120
mpz_util_primes[1] = 2;
121
for ( i = 2 ; i <= MPZ_SMALL_PRIMORIAL_W ; i++ ) {
122
for ( mp = _small_map+2 ; ! *mp ; mp++ ); // find first marked entry > 1 in previous map
123
*mp; // must be the next prime. clear it.
124
p = mp-_small_map;
125
mpz_util_primes[i] = p;
126
mpz_small_wheels[i].n = mpz_primorials[i] = mpz_primorials[i-1]*p;
127
mpz_small_wheels[i].phi = mpz_primorial_phis[i] = mpz_primorial_phis[i-1]*(p-1);
128
mp = _small_map+mpz_primorials[i-1] +1;
129
for ( k = 1 ; k < p ; k++ ) { // roll the previous wheel (p-1) more times
130
for ( j = 0 ; j < mpz_primorial_phis[i-1] ; j++ ) { *mp = 1; mp += mpz_small_wheels[i-1].gaps[j]; }
131
}
132
if ( mp != _small_map+mpz_primorials[i]+1 ) { err_printf ("mpz_util_init: primorial wheel alignment error\n"); exit (0); }
133
*mp = 1; // mark primorial+1 entry to bound last gap
134
np = _small_map+mpz_primorials[i];
135
for ( mp = _small_map+p ; mp < np ; mp += p ) *mp = 0; // clear the multiples of p
136
mpz_small_wheels[i].gaps = (unsigned char *) mem_alloc(mpz_primorial_phis[i]+4); // make alloc big enough to avoid small alloc error
137
maxgap = 0;
138
for ( mp = _small_map+1, j = 0 ; j < mpz_primorial_phis[i] ; j++ ) {
139
for ( np = mp+1 ; ! *np ; np++ );
140
gap = np-mp;
141
if ( gap > maxgap ) {
142
maxgap = gap;
143
if ( gap > UCHAR_MAX ) { err_printf ("gap %d too large to store in primorial wheel %d\n", gap, i); exit (0); }
144
}
145
mpz_small_wheels[i].gaps[j] = gap;
146
mp = np;
147
}
148
if ( np != _small_map+mpz_primorials[i]+1 ) { err_printf ("mpz_util_init: primorial wheel alignment error\n"); exit (0); }
149
mpz_small_wheels[i].maxgap = maxgap;
150
dbg_printf ("Wheel %d, maxgap %d\n", i, maxgap);
151
}
152
w = --i;
153
// roll last wheel across rest of the small map
154
mp = _small_map+mpz_primorials[w]+1;
155
np = _small_map+MPZ_MAX_SMALL_INTEGER;
156
while ( mp < np ) {
157
for ( j = 0 ; j < mpz_primorial_phis[w] ; j++ ) {
158
mp += mpz_small_wheels[w].gaps[j];
159
if ( mp >= np ) break;
160
*mp = 1;
161
}
162
}
163
// now sieve for primes up to MPZ_MAX_SMALL_INTEGER
164
maxp = (unsigned) floor(sqrt((double)MPZ_MAX_SMALL_INTEGER));
165
mp = _small_map + mpz_util_primes[i];
166
for (;;) {
167
mp++;
168
while ( ! *mp ) mp++;
169
p = mp-_small_map;
170
if ( p > maxp ) break;
171
mpz_util_primes[++i] = p;
172
for ( j = 0, k=1 ; ; j++ ) {
173
if ( j == mpz_small_wheels[w].phi ) j = 0;
174
k += mpz_small_wheels[w].gaps[j];
175
if ( k*p > MPZ_MAX_SMALL_INTEGER ) break;
176
_small_map[k*p] = 0;
177
}
178
}
179
mp = _small_map+mpz_util_primes[i]+1;
180
for (;;) {
181
while ( ! *mp ) mp++;
182
if ( mp >= np ) break;
183
mpz_util_primes[++i] = mp-_small_map;
184
mp++;
185
}
186
if ( i != MPZ_SMALL_PRIMES || mpz_util_primes[i] != MPZ_MAX_SMALL_PRIME ) { err_printf ("Error sieving small primes\n"); exit (0); }
187
mem_free (_small_map);
188
189
// index primes
190
for ( i = 1 ; i <= MPZ_SMALL_PRIMES ; i++ ) mpz_util_prime_index[mpz_util_primes[i]] = i;
191
// spread prime indexes to get pi(n) table
192
for ( i = 0, j = 0 ; i <= MPZ_MAX_SMALL_INTEGER ; i++ ) {
193
if ( mpz_util_prime_index[i] ) {
194
j = mpz_util_prime_index[i];
195
} else {
196
mpz_util_prime_index[i] = j;
197
}
198
}
199
200
// Compute various primorials and prime products
201
mpz_init2 (mpz_util_primorial, 94027); // the big Kahuna - the product of all small primes
202
mpz_set_ui (mpz_util_primorial, 1);
203
for ( i = 1 ; i <= MPZ_TINY_PRIMES ; i++ ) {
204
if ( i > MPZ_SMALL_PRIMORIAL_W && i <= MPZ_MAX_PRIMORIAL_W ) {
205
mpz_primorials[i] = mpz_primorials[i-1]*mpz_util_primes[i];
206
mpz_primorial_phis[i] = mpz_primorial_phis[i-1]*(mpz_util_primes[i]-1);
207
}
208
mpz_mul_ui (mpz_util_primorial, mpz_util_primorial, mpz_util_primes[i]);
209
}
210
211
// early gcd gaps are smaller
212
for ( j = 0 ; j < MPZ_PP_TABSIZE ; j++ ) {
213
if ( j < 2 ) {
214
n = 64;
215
} else if ( j < 4 ) {
216
n = 128;
217
} else {
218
n = 256;
219
}
220
mpz_init2 (_pptab[j].m0,n/2*16); mpz_init2 (_pptab[j].m,n*16);
221
mpz_set_ui (_pptab[j].m0, 1); mpz_set_ui (_pptab[j].m, 1);
222
_pptab[j].i0 = i-1;
223
if ( i+256 < MPZ_SMALL_PRIMES ) {
224
_pptab[j].i1 = i+n/2-1; // note top of range is closed
225
_pptab[j].i2 = i+n-1;
226
_pptab[j].b = (unsigned long)mpz_util_primes[_pptab[j].i2+1]*(unsigned long)mpz_util_primes[_pptab[j].i2+1];
227
for ( k = 0 ; k < n/8 ; k++ ) {
228
x = (unsigned long)mpz_util_primes[i]*(unsigned long)mpz_util_primes[i+1]*(unsigned long)mpz_util_primes[i+2]*(unsigned long)mpz_util_primes[i+3];
229
mpz_mul_ui (_pptab[j].m0, _pptab[j].m0, x);
230
i += 4;
231
}
232
mpz_set (_pptab[j].m, _pptab[j].m0);
233
for ( k = 0 ; k < n/8 ; k++ ) {
234
x = (unsigned long)mpz_util_primes[i]*(unsigned long)mpz_util_primes[i+1]*(unsigned long)mpz_util_primes[i+2]*(unsigned long)mpz_util_primes[i+3];
235
mpz_mul_ui (_pptab[j].m, _pptab[j].m, x);
236
i += 4;
237
}
238
} else {
239
_pptab[j].i2 = MPZ_SMALL_PRIMES;
240
_pptab[j].i1 = _pptab[j].i0 + (_pptab[j].i2-_pptab[j].i0) / 2;
241
_pptab[j].b = 0xFFFFFFFF;
242
while ( i <= _pptab[j].i1 ) mpz_mul_ui (_pptab[j].m0, _pptab[j].m0, mpz_util_primes[i++]);
243
mpz_set (_pptab[j].m, _pptab[j].m0);
244
while ( i <= _pptab[j].i2 ) mpz_mul_ui (_pptab[j].m, _pptab[j].m, mpz_util_primes[i++]);
245
}
246
mpz_mul (mpz_util_primorial, mpz_util_primorial, _pptab[j].m);
247
}
248
if ( i <= MPZ_SMALL_PRIMES ) { err_printf ("Initializion alignment problem computing prime products, only %d small primes used\n", i); exit (0); }
249
250
// roll small primorial wheel to create map of integers mod MPZ_MAX_SMALL_PRIMORIAL
251
w = MPZ_SMALL_PRIMORIAL_W;
252
for ( j = 0, k = 1; j < mpz_small_wheels[w].phi ; j++ ) {
253
mpz_small_primorial_map[k] = j+1;
254
k += mpz_small_wheels[w].gaps[j];
255
}
256
257
gmp_randinit_default (mpz_util_rands);
258
x = (((unsigned long)gethostid())<<32) + getpid();
259
x *= time(0);
260
//x=42; //uncomment if you want to fix the seed for debugging
261
gmp_randseed_ui (mpz_util_rands, x);
262
mpz_util_inited = 1;
263
}
264
265
266
int ui_is_small_prime (unsigned long p)
267
{
268
if ( ! p || p > MPZ_MAX_SMALL_PRIME ) return 0;
269
if ( ! mpz_util_inited ) mpz_util_init();
270
return ( mpz_util_primes[mpz_util_prime_index[p]] == p ? 1 : 0 );
271
}
272
273
int ui_is_prime (unsigned long p)
274
{
275
static mpz_t P;
276
static int init;
277
278
if ( p <= MPZ_MAX_SMALL_PRIME ) return ui_is_small_prime(p);
279
if ( ! init ) { mpz_init(P); init = 1; }
280
mpz_set_ui(P,p);
281
return mpz_probab_prime_p(P,5);
282
}
283
284
unsigned long ui_small_prime (unsigned long n)
285
{
286
if ( ! n || n > MPZ_SMALL_PRIMES ) { err_printf ("Invalid request for small prime - %d > %d\n", n, MPZ_SMALL_PRIMES); exit (0); }
287
if ( ! mpz_util_inited ) mpz_util_init();
288
return mpz_util_primes[n];
289
}
290
291
292
unsigned long ui_small_prime_index (unsigned long n) // returns pi(n) for n <= MPZ_MAX_SMALL_INTEGER
293
{
294
if ( n > MPZ_MAX_SMALL_PRIME ) { err_printf ("Invalid request for small prime index %d > %d\n", n, MPZ_MAX_SMALL_INTEGER); exit (0); }
295
if ( ! mpz_util_inited ) mpz_util_init();
296
return mpz_util_prime_index[n];
297
}
298
299
300
unsigned long ui_primorial (int w) // returns P_w = the w_th primorial or 0 if P_w > ULONG_MAX
301
{
302
if ( w > MPZ_MAX_PRIMORIAL_W ) { err_printf ("Requested primorial P_%d is too large\n", w); exit(0); }
303
if ( ! mpz_util_inited ) mpz_util_init();
304
return mpz_primorials[w];
305
}
306
307
308
unsigned long ui_primorial_phi (int w) // returns the phi(P_w) or 0 if P_w > ULONG_MAX
309
{
310
if ( w > MPZ_MAX_PRIMORIAL_W ) { err_printf ("Requested primorial P_%d is too large\n", w); exit(0); }
311
if ( ! mpz_util_inited ) mpz_util_init();
312
return mpz_primorial_phis[w];
313
}
314
315
unsigned long ui_phi (unsigned long n)
316
{
317
unsigned long p[MPZ_MAX_UI_PP_FACTORS];
318
unsigned long h[MPZ_MAX_UI_PP_FACTORS];
319
unsigned long m;
320
int i, j, w;
321
322
w = ui_factor(p,h,n);
323
for ( m = 1, i = 0 ; i < w ; i++ ) {
324
m *= (p[i]-1);
325
for ( j = 1 ; j < h[i] ; j++ ) m *= p[i];
326
}
327
return m;
328
}
329
330
// returns explicit upper bound on pi(n) = (x/log x)(1+3/(2log x)) based on Shoup p.91 (from Rosser and Schoenfeld)
331
unsigned long ui_pi_bound (unsigned long n)
332
{
333
double x,y;
334
335
if ( n < 59 ) return 18;
336
y = log((double)n);
337
x = (double) n / y;
338
x *= (1.0 + 3.0/(2.0*y));
339
return ((unsigned long)ceil(x));
340
}
341
342
wheel_t *primorial_wheel_alloc (int w)
343
{
344
wheel_t *wheel;
345
char *map, *mp, *np;
346
unsigned char *small_gaps, gap;
347
unsigned long i, j, k, p, small_phi;
348
349
if ( w <= MPZ_SMALL_PRIMORIAL_W ) return mpz_small_wheels+w;
350
if ( w > MPZ_MAX_WHEEL_W ) {err_printf ("Requested wheel exceeds MPZ_MAX_WHEEL_W %d > %d\n", w, MPZ_MAX_WHEEL_W); exit (0); }
351
wheel = (wheel_t*)mem_alloc (sizeof(*wheel));
352
wheel->n = mpz_primorials[w];
353
wheel->phi = mpz_primorial_phis[w];
354
wheel->gaps = (unsigned char *)mem_alloc (mpz_primorial_phis[w]);
355
map = (char *)mem_alloc (wheel->n+1);
356
np = map + wheel->n + 1;
357
*np = 1; // end marker to bound the last gap;
358
small_phi = mpz_small_wheels[MPZ_SMALL_PRIMORIAL_W].phi;
359
small_gaps = mpz_small_wheels[MPZ_SMALL_PRIMORIAL_W].gaps;
360
for ( i = MPZ_SMALL_PRIMORIAL_W+1 ; i <= w ; i++ ) {
361
p = mpz_util_primes[i];
362
mp = map+p;
363
j = 0;
364
while ( mp < np ) { // wheel the prime over the map
365
*mp = 1;
366
if ( j == small_phi ) j = 0;
367
mp += p*small_gaps[j++];
368
}
369
}
370
// compute the gaps by rolling the small wheel and skipping marked entries
371
gap = 0;
372
i = j = 0;
373
mp = map+1;
374
while ( mp < np ) {
375
if ( j == small_phi ) j = 0;
376
mp += small_gaps[j];
377
gap += small_gaps[j];
378
if ( ! *mp ) {
379
wheel->gaps[i++] = gap;
380
if ( gap > wheel->maxgap ) wheel->maxgap = gap;
381
gap = 0;
382
}
383
j++;
384
}
385
if ( mp != np) { err_printf ("wheel alignment error creating wheel for w = %d, %d != %d\n", w, mp-map, np-map); exit (0); }
386
if ( i != wheel->phi-1 ) { err_printf ("gap count error creating wheel for w = %d, %d != %d\n", w, i, wheel->phi); exit (0); }
387
wheel->gaps[i] = 2; // the last gap is always 2
388
return wheel;
389
}
390
391
392
void primorial_wheel_free (wheel_t *wheel)
393
{
394
if ( wheel->n <= MPZ_SMALL_PRIMORIAL ) return;
395
mem_free (wheel->gaps);
396
mem_free (wheel);
397
}
398
399
/*
400
Fast prime enumeration for p <= L < 2^32 based on a wheeled sieve.
401
The powers flag simply indicates that instead of returning p, return the largest power q=p^h bounded by L - enumeration is still ordered by p and only one power of p is returned.
402
*/
403
prime_enum_ctx_t *fast_prime_enum_start (unsigned start, unsigned L, int powers)
404
{
405
prime_enum_ctx_t *ctx;
406
unsigned char *mp, *np;
407
unsigned long k, m;
408
unsigned i, n, p, gap;
409
410
if ( start > L ) { err_printf ("Invalid prime enumeration, start must be less than L\n"); exit (0); }
411
if ( ! mpz_util_inited ) mpz_util_init();
412
if ( L > MPZ_MAX_ENUM_PRIME ) { err_printf ("Attempted prime enumeration too large %d > %d = MPZ_MAX_ENUM_PRIME\n", L, MPZ_MAX_ENUM_PRIME); exit (0); }
413
ctx = (prime_enum_ctx_t *) mem_alloc (sizeof(*ctx));
414
p = mpz_util_primes[MPZ_SMALL_PRIMORIAL_W+1];
415
// if ( L < p*p ) L = p*p; // make sure initial ctx->w is greater than MPZ_SMALL_PRIMORIAL_W
416
ctx->L = L;
417
ctx->powers = powers; // indicates prime power enumeration
418
ctx->h = ui_len(L); // 2^h <= L <=2^{h+1}
419
for ( i = 2 ; i <= ctx->h ; i++ ) {
420
n = (unsigned) floor(pow((double)L,1.0/(double)i)); // n^i <= L < (n+1)^i
421
ctx->r[i] = mpz_util_prime_index[n]; // r(i) = pi(L^{1/i})
422
if ( ! powers ) break;
423
}
424
ctx->wheel = primorial_wheel_alloc (MPZ_SMALL_PRIMORIAL_W);
425
ctx->w = ctx->r[2]; // p_w <= L^{1/2} < p_{w+1} so it suffices to sieve by the first w primes
426
ctx->wv = (unsigned int*)mem_alloc ((ctx->w+1)*sizeof(*ctx->wv)); // the entry wv[i] stores the value of the i-th prime modulo MPZ_SMALL_PRIMORIAL = ctx->wheel->n
427
ctx->wi = (unsigned int*)mem_alloc ((ctx->w+1)*sizeof(*ctx->wi)); // the entry wi[i] stores the index of the next wheel gap for the i-th prime - see below
428
for ( i =1; i <= ctx->w ; i++ ) ctx->wv[i] = mpz_util_primes[i]; // these values aren't necessarily reduced mod MPZ_SMALL_PRIMORIAL, but that's ok, the code below doesn't assume this
429
ctx->map = (unsigned char*)mem_alloc(ctx->wheel->n);
430
np = ctx->map+ctx->wheel->n;
431
/*
432
The only relevant entries of our map are ones relatively prime to MPZ_SMALL_PRIMORIAL, since we enumerate the map via the wheel.
433
Thus we only need to sieve multiples of primes whose index lies in [MPZ_SMALL_PRIMORIAL_W+1,ctx->w] and we only need to worry
434
about those multiples which are relatively prime to MPZ_SMALL_PRIMORIAL. Thus for each prime, we effectively use the same wheel
435
to enumerate these multiples. The value wi[i] holds the index into the wheel for the i-th prime.
436
437
If the starting point is far from 0, we can skip ahead by starting at the first multiple of MPZ_SMALL_PRIMORIAL below start, call it n.
438
For simplicity, we avoid special code for the first ctx->w primes by always forcing enumeration of the first w primes
439
For each prime p <= ctx->w we need to compute the least multiple kp > start where k is relatively prime to MPZ_SMALL_PRIMORIAL
440
and then set wv[i] = kp - n and set wi[i] = index of gap between k and next integer relatively prime to MPZ_SMALL_PRIMORIAL in wheel.
441
442
To keep this simple, we set m to the first multiple of p*MPZ_SMALL_PRIMORIAL below start, set wv[i] = p, wi[i] = 0 and roll forward from there.
443
*/
444
if ( start > 2 ) {
445
// This is a bit awkward but removes the need for any conditional code in fast_prime_enum to handle startup.
446
// We want to enumerate just up to the greatest prime below start. To facilitate this we backup start as required
447
n = ui_len(start);
448
for ( k = 2 ;; k += n ) {
449
if ( k > start ) k = start;
450
mpz_set_ui (_mpz_temp, start-k);
451
mpz_nextprime (_mpz_temp, _mpz_temp);
452
if ( mpz_cmp_ui(_mpz_temp,start) < 0 ) break;
453
}
454
do {
455
m = mpz_get_ui(_mpz_temp);
456
mpz_nextprime (_mpz_temp, _mpz_temp);
457
} while ( mpz_cmp_ui(_mpz_temp,start) < 0 );
458
start = m;
459
} else {
460
start = 0;
461
}
462
if ( start > MPZ_SMALL_PRIMORIAL && start > mpz_util_primes[ctx->w] ) {
463
n = (start/MPZ_SMALL_PRIMORIAL) * MPZ_SMALL_PRIMORIAL;
464
for ( i = MPZ_SMALL_PRIMORIAL_W+1 ; i <= ctx->w ; i++ ) {
465
p = mpz_util_primes[i];
466
ctx->wv[i] = p;
467
m = _ui_ceil_ratio(n,p)*(unsigned long)p; // m is the least multiple of p >= n - could be > 2^32
468
m /= p;
469
k = m % MPZ_SMALL_PRIMORIAL;
470
while ( ! mpz_small_primorial_map[k] ) k++; // find least k >= m%MPZ_SMALL_PRIMORIAL relatively prime to MPZ_SMALL_PRIMORIAL
471
m = (unsigned long)p*((m/MPZ_SMALL_PRIMORIAL)*MPZ_SMALL_PRIMORIAL+k) - n;
472
ctx->wv[i] = (unsigned) m;
473
ctx->wi[i] = mpz_small_primorial_map[k]-1; // gap index i gives gap between (i+1)st and (i+2)nd integers relatively prime to MPZ_SMALL_PRIMORIAL
474
}
475
ctx->pi = MPZ_SMALL_PRIMES; // just need to make it bigger than ctx->w and MPZ_SMALL_PRIMORIAL_W
476
ctx->p = n-1;
477
} else {
478
ctx->pi = 1;
479
ctx->p = 0;
480
}
481
ctx->j = ctx->wheel->phi-1;
482
/*
483
for ( i = MPZ_SMALL_PRIMORIAL_W+1 ; i <= ctx->w ; i++ ) {
484
p = mpz_util_primes[i];
485
mp = ctx->map+ctx->wv[i];
486
while ( mp < np ) {
487
*mp = 1;
488
gap = p*ctx->wheel->gaps[ctx->wi[i]++];
489
if ( ctx->wi[i] == ctx->wheel->phi ) ctx->wi[i] = 0;
490
ctx->wv[i] += gap;
491
mp += gap;
492
}
493
ctx->wv[i] -= ctx->wheel->n;
494
}
495
ctx->mp = ctx->map + 1;
496
*/
497
if ( start ) {
498
while ( (p=fast_prime_enum(ctx)) < start );
499
if ( p != start ) { err_printf ("Unable to find start prime, p = %u, start = %u, L = %u\n", p, start, L); exit (0); }
500
}
501
return ctx;
502
}
503
504
505
unsigned fast_prime_enum (prime_enum_ctx_t *ctx)
506
{
507
register unsigned gap;
508
509
// The first ctx->w primes need to be enumerated seperately, since they have all been sieved out of the map
510
// Note that if ctx->w > MPZ_SMALL_PRIMORIAL this means the first map is effectively empty, but that's ok.
511
// Prime powers are only relevant for the first ctx->w primes since ctx->w was chosen to ensure pi(ctx->w)^2 > L
512
if ( ctx->pi <= ctx->w || ctx->pi <= MPZ_SMALL_PRIMORIAL_W ) {
513
register unsigned i, p, q;
514
q = mpz_util_primes[ctx->pi++];
515
if ( q > ctx->L ) return 0;
516
if ( ctx->powers ) {
517
while ( ctx->h && ctx->r[ctx->h] < ctx->pi ) ctx->h--;
518
for ( i = 1, p=q ; i < ctx->h ; i++ ) q *= p;
519
}
520
return q;
521
}
522
for (;;) {
523
if ( ctx->j == ctx->wheel->phi-1 ) {
524
register unsigned char *mp, *np;
525
register unsigned i, p;
526
memset (ctx->map, 0, ctx->wheel->n);
527
np = ctx->map + ctx->wheel->n;
528
for ( i = MPZ_SMALL_PRIMORIAL_W+1 ; i <= ctx->w ; i++ ) {
529
p = mpz_util_primes[i];
530
mp = ctx->map+ctx->wv[i];
531
while ( mp < np ) {
532
*mp = 1;
533
gap = p*ctx->wheel->gaps[ctx->wi[i]++];
534
if ( ctx->wi[i] == ctx->wheel->phi ) ctx->wi[i] = 0;
535
ctx->wv[i] += gap;
536
mp += gap;
537
}
538
ctx->wv[i] -= ctx->wheel->n;
539
}
540
ctx->mp = ctx->map+1;
541
if ( ctx->p ) {
542
ctx->p += 2; // last gap is always 2
543
ctx->j = 0;
544
} else {
545
ctx->p = 1+ctx->wheel->gaps[0]; // special case - skip 1
546
ctx->mp += ctx->wheel->gaps[0];
547
ctx->j = 1;
548
}
549
} else {
550
gap = ctx->wheel->gaps[ctx->j++];
551
ctx->mp += gap;
552
ctx->p += gap;
553
}
554
if ( ctx->p > ctx->L ) return 0;
555
if ( ! *ctx->mp ) return ctx->p;
556
}
557
}
558
559
560
void fast_prime_enum_end (prime_enum_ctx_t *ctx)
561
{
562
mem_free (ctx->map);
563
mem_free (ctx->wv);
564
mem_free (ctx->wi);
565
primorial_wheel_free (ctx->wheel);
566
mem_free (ctx);
567
}
568
569
570
// returns the least p for which the p-adic valuation of a and b differ
571
unsigned long ui_pdiff (unsigned long a, unsigned long b)
572
{
573
unsigned long d, p;
574
unsigned long q[MPZ_MAX_UI_PP_FACTORS];
575
unsigned long h[MPZ_MAX_UI_PP_FACTORS];
576
int w;
577
int i;
578
579
mpz_util_init();
580
if ( a == b ) return 0;
581
d = ui_gcd(a,b);
582
a /= d;
583
b /= d;
584
// check small primes before factoring
585
for ( i = 1 ; i < 25 ; i++ ) {
586
if ( a%mpz_util_primes[i] ) {
587
if ( ! (b%mpz_util_primes[i]) ) break;
588
} else {
589
if ( b%mpz_util_primes[i] ) break;
590
}
591
}
592
if ( i < 25 ) return mpz_util_primes[i];
593
printf ("Factoring %lu and %lu\nb", a, b);
594
w = ui_factor (q, h, a);
595
if ( w ) p = q[0]; else p = 0;
596
w = ui_factor (q, h, b);
597
if ( w && p > q[0] ) p = q[0];
598
printf ("pdiff = %d\n", p);
599
return p;
600
}
601
602
603
// note that o and a can overlap
604
void mpz_parallel_invert (mpz_t o[], mpz_t a[], unsigned n, mpz_t p)
605
{
606
static int init;
607
static mpz_t c[MPZ_MAX_INVERTS];
608
static mpz_t u, v;
609
unsigned i;
610
611
if ( ! init ) {
612
for ( i = 0 ; i < MPZ_MAX_INVERTS ; i++ ) mpz_init (c[i]);
613
mpz_init (u); mpz_init (v);
614
init = 1;
615
}
616
if ( ! n ) return;
617
if ( n > MPZ_MAX_INVERTS ) { err_printf ("Exceeded MPZ_MAX_INVERTS, %d > %d\n", n, MPZ_MAX_INVERTS); exit (0); }
618
mpz_set (c[0], a[0]);
619
for ( i = 1 ; i < n ; i++ ) mpz_mulm (c[i], c[i-1], a[i], p);
620
if ( ! mpz_invert (u, c[n-1], p) ) { err_printf ("Invert failed in mpz_parallel_invert!\n"); }
621
for ( i = n-1 ; i > 0 ; i-- ) {
622
mpz_mulm (v, c[i-1], u, p);
623
mpz_mulm (u, u, a[i], p);
624
mpz_set (o[i], v);
625
}
626
mpz_set (o[0], u);
627
}
628
629
630
void mpz_mul_set (mpz_t o, mpz_t *a, unsigned long n)
631
{
632
unsigned long i, j;
633
634
if ( ! n ) { mpz_set_ui(o, 1); return; }
635
while ( n >= 2 ) {
636
for ( i = 0 ; i < (n+1)/2 ; i++ ) {
637
if ( 2*i+1 < n ) {
638
mpz_mul (a[i], a[2*i], a[2*i+1]);
639
} else {
640
mpz_set (a[i], a[2*i]);
641
}
642
}
643
n = i;
644
}
645
if ( n == 2 ) {
646
mpz_mul (o, a[0], a[1]);
647
} else {
648
mpz_set (o, a[0]);
649
}
650
}
651
652
#define MPZ_PM_CACHE_SIZE 100
653
654
static struct {
655
mpz_t p;
656
mpz_t maxp;
657
mpz_t endp;
658
mpz_t o;
659
unsigned long maxbits;
660
int n;
661
} _mpz_pm_cache[MPZ_PM_CACHE_SIZE];
662
unsigned long _mpz_pm_cache_count;
663
664
665
#define MPZ_TIER_SIZE 256
666
667
// multiplies o by the product of all primes in (p,maxp] up to maxbits and updates p to last prime used or > maxp if all used. return number of primes multiplied.
668
int mpz_prime_mult (mpz_t o, mpz_t p, mpz_t maxp, unsigned long maxbits)
669
{
670
static int init, warn;
671
static mpz_t t1[MPZ_TIER_SIZE];
672
static mpz_t t2[MPZ_TIER_SIZE];
673
static mpz_t t3[MPZ_TIER_SIZE];
674
unsigned long bits;
675
register int i, i1, i2, i3, n;
676
677
if ( ! init ) {
678
for ( i = 0 ; i < MPZ_TIER_SIZE ; i++ ) { mpz_init (t1[i]); mpz_init (t2[i]); mpz_init (t3[i]); }
679
for ( i = 0 ; i < MPZ_PM_CACHE_SIZE ; i++ ) {
680
mpz_init (_mpz_pm_cache[i].p);
681
mpz_init (_mpz_pm_cache[i].endp);
682
mpz_init (_mpz_pm_cache[i].maxp);
683
mpz_init (_mpz_pm_cache[i].o);
684
}
685
init = 1;
686
}
687
for ( i = 0 ; i < _mpz_pm_cache_count ; i++ ) {
688
if ( mpz_cmp (p,_mpz_pm_cache[i].p) == 0 && mpz_cmp (maxp, _mpz_pm_cache[i].maxp) == 0 &&
689
maxbits == _mpz_pm_cache[i].maxbits ) {
690
mpz_set (p, _mpz_pm_cache[i].endp);
691
mpz_set (o, _mpz_pm_cache[i].o);
692
return _mpz_pm_cache[i].n;
693
}
694
}
695
if ( _mpz_pm_cache_count < MPZ_PM_CACHE_SIZE ) {
696
i = _mpz_pm_cache_count;
697
mpz_set (_mpz_pm_cache[i].p, p);
698
mpz_set (_mpz_pm_cache[i].maxp, maxp);
699
_mpz_pm_cache[i].maxbits = maxbits;
700
} else {
701
if ( ! warn ) { err_printf ("Prime product cache full in mpz_prime_mult...\n"); warn = 1; }
702
}
703
i1 = i2 = i3 = 0;
704
bits = mpz_sizeinbase (o, 2);
705
for ( n = 0 ; bits < maxbits ; n++ ) {
706
mpz_nextprime (p, p);
707
if ( mpz_cmp (p, maxp) > 0 ) break;
708
if ( i3 == MPZ_TIER_SIZE ) {
709
if ( i2 == MPZ_TIER_SIZE ) {
710
if ( i1 >= MPZ_TIER_SIZE-2 ) break;
711
mpz_mul_set (t1[i1++], t2, i2);
712
i2 = 0;
713
}
714
mpz_mul_set (t2[i2++], t3, i3);
715
i3 = 0;
716
}
717
mpz_set (t3[i3++], p);
718
bits += mpz_sizeinbase (p, 2);
719
}
720
if ( i2 == MPZ_TIER_SIZE ) {
721
mpz_mul_set (t1[i1++], t2, i2);
722
i2 = 0;
723
}
724
mpz_mul_set (t2[i2++], t3, i3);
725
mpz_mul_set (t1[i1++], t2, i2);
726
mpz_mul_set (t3[0], t1, i1);
727
mpz_mul (o, o, t3[0]);
728
if ( _mpz_pm_cache_count < MPZ_PM_CACHE_SIZE ) {
729
i = _mpz_pm_cache_count++;
730
mpz_set (_mpz_pm_cache[i].endp, p);
731
mpz_set (_mpz_pm_cache[i].o, o);
732
_mpz_pm_cache[i].n = n;
733
}
734
return n;
735
}
736
737
// computes the product of all prime powers <= L
738
// this function is designed to be called once - it dynamically allocates and frees all memory
739
void mpz_power_primorial (mpz_t o, unsigned long L)
740
{
741
mpz_t t1[MPZ_TIER_SIZE];
742
mpz_t t2[MPZ_TIER_SIZE];
743
mpz_t t3[MPZ_TIER_SIZE];
744
mpz_t p, q, t;
745
unsigned long roots[33];
746
register int i, i1, i2, i3, j1, j2, n;
747
748
n = ui_len(L);
749
if ( n > 32 ) { err_printf ("primorial %u too large to compute - be reasonable.\n"); exit (0); }
750
for ( i = n ; i >= 2 ; i-- ) roots[i] = (unsigned long) floor(pow((double)L,1.0/(double)i));
751
roots[1] = L;
752
roots[0] = -1;
753
754
// just init tier 3 initially, init tier 1 and 2 variables as needed
755
for ( i = 0 ; i < MPZ_TIER_SIZE ; i++ ) mpz_init2 (t3[i], MPZ_TIER_SIZE*n);
756
j1 = j2 = 0;
757
758
mpz_init (p); mpz_init (q); mpz_init (t); mpz_set_ui (p, 1);
759
i1 = i2 = i3 = 0;
760
i = n;
761
for ( ;; ) {
762
mpz_nextprime (p, p);
763
while ( i && mpz_cmp_ui (p,roots[i]) > 0 ) i--;
764
if ( ! i ) break;
765
mpz_pow_ui (q, p, i);
766
if ( i3 == MPZ_TIER_SIZE ) {
767
if ( i2 == MPZ_TIER_SIZE ) {
768
if ( i1 >= MPZ_TIER_SIZE-2 ) { err_printf ("Insufficient memory in mpz_power_primorial on input %u - increase MPZ_TIER_SIZE or add a tier\n", L); exit (0); }
769
if ( i1 == j1 ) mpz_init (t1[j1++]);
770
mpz_mul_set (t1[i1++], t2, i2);
771
i2 = 0;
772
}
773
if ( i2 == j2 ) mpz_init (t2[j2++]);
774
mpz_mul_set (t2[i2++], t3, i3);
775
i3 = 0;
776
}
777
mpz_set (t3[i3++], q);
778
}
779
if ( i2 == MPZ_TIER_SIZE ) {
780
if ( i1 == j1 ) mpz_init (t1[j1++]);
781
mpz_mul_set (t1[i1++], t2, i2);
782
i2 = 0;
783
}
784
// free memory as we go to keep peak usage down
785
if ( i2 == j2 ) mpz_init (t2[j2++]);
786
mpz_mul_set (t2[i2++], t3, i3);
787
for ( i = 0 ; i < MPZ_TIER_SIZE ; i++ ) mpz_clear (t3[i]);
788
if ( i1 == j1 ) mpz_init (t1[j1++]);
789
mpz_mul_set (t1[i1++], t2, i2);
790
for ( i = 0 ; i < j2 ; i++ ) mpz_clear (t2[i]);
791
mpz_mul_set (o, t1, i1);
792
for ( i = 0 ; i < j1 ; i++ ) mpz_clear (t1[i]);
793
mpz_clear (p); mpz_clear (q); mpz_clear (t);
794
return;
795
}
796
797
798
int mpz_remove_small_primes (mpz_t o, mpz_t n, unsigned long exps[], unsigned long maxprimes)
799
{
800
static int init;
801
static mpz_t d, x, t;
802
int i, j, w;
803
804
if ( ! init ) { mpz_util_init(); mpz_init (d); mpz_init (x); mpz_init (t); init = 1; }
805
if ( maxprimes > MPZ_SMALL_PRIMES ) { err_printf ("maxprimes value %d exceeded MAX_SMALL_PRIMES = %d in mpz_remove_small_primes\n", maxprimes, MPZ_SMALL_PRIMES); exit (0); }
806
mpz_gcd (d, n, mpz_util_primorial);
807
mpz_set (o, n);
808
exps[0] = 0;
809
w = 0;
810
for ( i = 1 ; i <= maxprimes ; i++ ) {
811
if ( mpz_divisible_ui_p (d, mpz_util_primes[i]) ) {
812
mpz_set_ui (x, mpz_util_primes[i]);
813
exps[i] = mpz_remove (o, o, x);
814
w++;
815
} else {
816
exps[i] = 0;
817
}
818
}
819
return w;
820
}
821
822
// Let p be the largest prime factor of n. If n/p <= L, return n/p, otherwise return 0
823
unsigned long mpz_nearprime (mpz_t n, unsigned long L)
824
{
825
static int init;
826
static mpz_t d, x, t;
827
int i;
828
829
if ( ! init ) { mpz_util_init(); mpz_init (d); mpz_init (x); mpz_init (t); init = 1; }
830
if ( L > MPZ_MAX_SMALL_INTEGER ) { err_printf ("cofactor bound too large in mpz_nearprime\n"); exit (0); }
831
mpz_gcd (d, n, mpz_util_primorial);
832
if ( mpz_cmp_ui (d, L) > 0 ) return 0;
833
mpz_set (t, n);
834
for ( i = 1 ; i <= MPZ_SMALL_PRIMES ; i++ ) {
835
if ( mpz_divisible_ui_p (d, mpz_util_primes[i]) ) {
836
mpz_set_ui (x, mpz_util_primes[i]);
837
mpz_remove (t, t, x);
838
mpz_remove (d, d, x);
839
if ( mpz_cmp_ui(d,1) == 0 ) break;
840
}
841
}
842
mpz_divexact (x, n, t);
843
if ( mpz_cmp_ui (x, L) > 0 ) return 0;
844
if ( ! mpz_probab_prime_p (t, 10) ) return 0;
845
return mpz_get_ui (x);
846
}
847
848
849
int mpz_remove_small_squares (mpz_t o, mpz_t n)
850
{
851
static int init;
852
static mpz_t d, x, m;
853
int i, j, w;
854
855
if ( ! init ) { mpz_util_init(); mpz_init (d); mpz_init (x); mpz_init (m); init = 1; }
856
mpz_set (o, n);
857
if ( mpz_cmp_ui (n, 1) <= 0 ) return 0;
858
mpz_gcd (d, n, mpz_util_primorial);
859
mpz_set (m, n);
860
for ( i = 1 ; i <= MPZ_SMALL_PRIMES ; i++ ) {
861
if ( mpz_divisible_ui_p (d, mpz_util_primes[i]) ) {
862
mpz_set_ui (x, mpz_util_primes[i]);
863
j = mpz_remove (m, m, x);
864
if ( j%2 ) mpz_mul (m, m, x);
865
}
866
}
867
mpz_set (o, m);
868
return 1;
869
}
870
871
872
int mpz_print_factors (mpz_t N)
873
{
874
static int init;
875
static mpz_t P;
876
unsigned long p[MPZ_MAX_SMALL_FACTORS];
877
unsigned long h[MPZ_MAX_SMALL_FACTORS];
878
int i, w;
879
880
if ( ! init ) { mpz_init (P); init = 1; }
881
w = mpz_factor_small (p, h, P, N, MPZ_MAX_SMALL_FACTORS, 128);
882
if ( mpz_cmp_ui (P,1) > 0 ) out_printf ("%Zd", P);
883
if ( w ) out_printf (" ");
884
for ( i = 0 ; i < w ; i++ ) {
885
if ( h[i] > 1 ) {
886
out_printf ("%lu^%lu ", p[i], h[i]);
887
} else if ( h[i] == 1 ) {
888
out_printf ("%lu", p[i]);
889
}
890
}
891
puts ("");
892
}
893
894
895
#define _remove(n,d,c) while ( !((n)%(d)) ) { (n)/=(d); (c)++; }
896
#define _tdiv(n,d,h,p,w) { _remove(n,d,h[w]); if ( (h)[(w)] ) { (p)[(w)++] = (d); (h)[(w)] = 0; } }
897
898
int _mod64res[64] = { 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, };
899
int _mod63res[63] = { 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0 };
900
int _mod65res[65] = { 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, };
901
int _mod11res[11] = { 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0 };
902
903
static inline int _ui_sqrt(unsigned long n)
904
{
905
register unsigned long x;
906
907
if ( ! _mod64res[n&0x3F] ) return 0;
908
if ( ! _mod63res[n%63] ) return 0;
909
if ( ! _mod65res[n%65] ) return 0;
910
if ( ! _mod11res[n%11] ) return 0;
911
x = (unsigned long)(sqrt(n)+0.01); // avoid potential rounding problems
912
return (x*x == n ? x : 0);
913
}
914
915
int ui_sqrt(long n)
916
{ register int k; if (n<0) return -1; if ( !n) return 0; k = _ui_sqrt(n); if ( k ) return k; else return -1; }
917
918
919
int ui_factor (unsigned long p[MPZ_MAX_UI_PP_FACTORS], unsigned long h[MPZ_MAX_UI_PP_FACTORS], unsigned long n)
920
{
921
static int init;
922
static mpz_t N, D, D1;
923
register unsigned long d, d0, d1;
924
register int i, k, w;
925
926
if ( ! init ) { mpz_init (N); mpz_init (D); mpz_init (D1); mpz_util_init(); init = 1; }
927
if ( n == 0 ) { err_printf ("attempt to factor 0\n"); exit (0); }
928
w = 0;
929
h[w] = 0;
930
while ( ! (n&0x1) ) { n >>= 1; h[w]++; }
931
if ( h[w] ) { p[w++] = 2; h[w] = 0; }
932
if ( n == 1 ) return w;
933
934
// factor small integers using factor table - but need to reverse the order of the factors
935
if ( n <= MPZ_MAX_SMALL_INTEGER ) {
936
register unsigned char tiny;
937
unsigned long p2[16];
938
939
k = 0;
940
while ( (tiny = mpz_small_factors[n]) ) {
941
if ( w && p[w-1] == tiny ) { h[w-1]++; } else { p[w] = tiny; h[w++] = 1; }
942
n /= tiny;
943
}
944
if ( w && p[w-1] == n ) { h[w-1]++; } else { p[w] = n; h[w++] = 1; }
945
return w;
946
}
947
// Clear out all tiny primes via trial division. Yes, it is worth hardwiring all this - it's much faster.
948
_tdiv(n,3,h,p,w); _tdiv(n,5,h,p,w); _tdiv(n,7,h,p,w); _tdiv(n,11,h,p,w); _tdiv(n,13,h,p,w); _tdiv(n,17,h,p,w); _tdiv(n,19,h,p,w); _tdiv(n,23,h,p,w); _tdiv(n,29,h,p,w);
949
_tdiv(n,31,h,p,w); _tdiv(n,37,h,p,w); _tdiv(n,41,h,p,w); _tdiv(n,43,h,p,w); _tdiv(n,47,h,p,w); _tdiv(n,53,h,p,w); _tdiv(n,59,h,p,w); _tdiv(n,61,h,p,w); _tdiv(n,67,h,p,w); _tdiv(n,71,h,p,w);
950
_tdiv(n,73,h,p,w); _tdiv(n,79,h,p,w); _tdiv(n,83,h,p,w); _tdiv(n,89,h,p,w); _tdiv(n,97,h,p,w); _tdiv(n,101,h,p,w); _tdiv(n,103,h,p,w); _tdiv(n,107,h,p,w); _tdiv(n,109,h,p,w); _tdiv(n,113,h,p,w);
951
_tdiv(n,127,h,p,w); _tdiv(n,131,h,p,w); _tdiv(n,137,h,p,w); _tdiv(n,139,h,p,w); _tdiv(n,149,h,p,w); _tdiv(n,151,h,p,w); _tdiv(n,157,h,p,w); _tdiv(n,163,h,p,w); _tdiv(n,167,h,p,w); _tdiv(n,173,h,p,w);
952
_tdiv(n,179,h,p,w); _tdiv(n,181,h,p,w); _tdiv(n,191,h,p,w); _tdiv(n,193,h,p,w); _tdiv(n,197,h,p,w); _tdiv(n,199,h,p,w); _tdiv(n,211,h,p,w); _tdiv(n,223,h,p,w); _tdiv(n,227,h,p,w); _tdiv(n,229,h,p,w);
953
_tdiv(n,233,h,p,w); _tdiv(n,239,h,p,w); _tdiv(n,241,h,p,w); _tdiv(n,251,h,p,w);
954
955
if ( n == 1 ) return w;
956
if ( n < MPZ_MAX_SMALL_INTEGER ) {
957
p[w] = n;
958
h[w++] = 1;
959
return w;
960
}
961
962
// at this point n > MPZ_MAX_SMALL_INTEGER and contains no primes <= MPZ_MAX_TINY_PRIME
963
// time to start whacking it with some gcd's
964
mpz_set_ui (N, n);
965
for ( i = 0 ; i < MPZ_PP_TABSIZE ; i++ ) {
966
mpz_gcd (D, N,_pptab[i].m);
967
if ( mpz_cmp_ui(D,1) != 0 ) {
968
d = mpz_get_ui(D);
969
if ( d <= mpz_util_primes[_pptab[i].i2] ) { // sliced of just one prime - this is what we want
970
p[w] = d;
971
h[w] = 0;
972
do { n /= d; h[w]++; } while ( ! (n%d) ); // need to remove all occurrences of d
973
w++;
974
mpz_set_ui (N, n);
975
} else {
976
//printf ("multiple primes in gcd span\n");
977
mpz_gcd (D1, D, _pptab[i].m0);
978
if ( mpz_cmp_ui(D1,1) ) {
979
d1 = mpz_get_ui (D1);
980
if ( d1 <= mpz_util_primes[_pptab[i].i1] ) {
981
p[w] = d1;
982
h[w] = 0;
983
do { n /= d1; h[w]++; } while ( ! (n%d1) ); // need to remove all occurrences of d1
984
w++;
985
} else {
986
//printf ("trial dividing low i=%d, d1=%lu, (%u,%u)\n", i, d1, mpz_util_primes[_pptab[i].i0],mpz_util_primes[_pptab[i].i1]);
987
h[w] = 0;
988
for ( k = _pptab[i].i0+1 ; k <= _pptab[i].i1 ; k++ ) _tdiv (n, mpz_util_primes[k], h, p, w);
989
}
990
d1 = d/d1;
991
} else {
992
d1 = d;
993
}
994
if ( d1 > 1 ) {
995
if ( d1 < mpz_util_primes[_pptab[i].i2]) {
996
p[w] = d1;
997
h[w] = 0;
998
do { n /= d1; h[w]++; } while ( ! (n%d1) ); // need to remove all occurrences of d1
999
w++;
1000
} else {
1001
//printf ("trial dividing high i=%d, d1=%lu, (%u,%u)\n", i, d1, mpz_util_primes[_pptab[i].i1],mpz_util_primes[_pptab[i].i2]);
1002
h[w] = 0;
1003
for ( k = _pptab[i].i1+1 ; k <= _pptab[i].i2 ; k++ ) _tdiv (n, mpz_util_primes[k], h, p, w);
1004
}
1005
}
1006
}
1007
if ( n == 1 ) return w;
1008
}
1009
if ( n < _pptab[i].b ) {
1010
//printf ("added remainder n=%d\n", n);
1011
p[w] = n; h[w++] = 1;
1012
return w;
1013
}
1014
mpz_set_ui (N, n);
1015
}
1016
1017
// If the original n's second largest prime was below MPZ_SMALL_PRIME, what remains is prime - this is likely for n in the 32-48 bit range, so check here.
1018
if ( mpz_probab_prime_p (N, 10) ) {
1019
p[w] = n; h[w++] = 1;
1020
return w;
1021
}
1022
1023
// resort to bigger guns - this can't happen unless N is a composite with more than 32 bits and no prime factors below MPZ_MAX_SMALL_PRIME
1024
// we could go direct to a single-precision version of pollard rho here, but we don't expect this to happen much anyway
1025
w += mpz_factor_small(p+w,h+w,D,N,MPZ_MAX_UI_PP_FACTORS-w, 64);
1026
return w;
1027
}
1028
1029
// this code hasn't been fully tested and isn't currently used
1030
int ui_lehman_factor (unsigned long p[MPZ_MAX_UI_PP_FACTORS], unsigned long h[MPZ_MAX_UI_PP_FACTORS], unsigned long n)
1031
{
1032
unsigned long b;
1033
register unsigned long a, m, c, d, e, r, k, s, t, s1;
1034
register int w;
1035
1036
// Lehman's O(n^{1/3}) deterministic algorithm - [CANT] p. 425
1037
b = (unsigned)pow(n,1.0/3.0)+1; // add 1 to be safe
1038
t = b*b;
1039
s1 = n<<2;
1040
s = 0;
1041
for ( k = 1 ; k < b ; k++ ) {
1042
if ( k&0x1 ) {
1043
r = (k+n)&0x3;
1044
m = 4;
1045
} else {
1046
r = 1;
1047
m = 2;
1048
}
1049
s += s1;
1050
a = _ui_sqrt(s);
1051
while ( (a&(m-1)) != r ) a++;
1052
e = s+t;
1053
while ( (c=a*a) <= e ) {
1054
c -= s;
1055
if ( (c=_ui_sqrt(c)) ) goto lehman_done;
1056
a += m;
1057
}
1058
}
1059
p[w] = n;
1060
h[w++] = 1;
1061
return w;
1062
lehman_done:
1063
d = ui_gcd(a+c,n);
1064
if ( d == 1 || d == n ) { err_printf ("Lehman's algorithm failed for n = %lu with a = %lu, b = %lu, c = %lu, s = %lu, s+t = %lu, k = %lu, r = %lu, m = %lu\n", n, a, b, c, s, s+t, k, r, m); exit (0); }
1065
p[w] = d;
1066
p[w+1] = n/d;
1067
h[w] = h[w+1] = 1;
1068
if ( p[w] > p[w+1] ) { p[w] = p[w+1]; p[w+1] = d; } // keep primes in increasing order
1069
if ( p[w] == p[w+1] ) h[w++] = 2; else w += 2; // check for square
1070
return w;
1071
}
1072
1073
1074
// returns primes in order
1075
int mpz_factor_small (unsigned long p[], unsigned long h[], mpz_t bigp, mpz_t n, int max_factors, int max_hard_bits)
1076
{
1077
static int init;
1078
static mpz_t d, x, m;
1079
unsigned long pt, ht;
1080
int i, j, w;
1081
1082
if ( ! init ) { mpz_util_init(); mpz_init (d); mpz_init (x); mpz_init (m); init = 1; }
1083
if ( ! mpz_sgn (n) ) { err_printf ("Attempt to factor 0"); exit (0); }
1084
mpz_set_ui (bigp, 1);
1085
if ( mpz_sgn(n) < 0 ) mpz_neg (m, n); else mpz_set (m,n);
1086
if ( mpz_cmp_ui(m,1) == 0 ) return 0;
1087
mpz_gcd (d, m, mpz_util_primorial);
1088
w = 0;
1089
for ( i = 1 ; i <= MPZ_SMALL_PRIMES ; i++ ) {
1090
if ( mpz_cmp_ui (d, 1) == 0 ) break;
1091
if ( mpz_divisible_ui_p (d, mpz_util_primes[i]) ) {
1092
p[w] = mpz_util_primes[i];
1093
mpz_set_ui (x, p[w]);
1094
h[w] = mpz_remove (m, m, x);
1095
w++;
1096
if ( w == max_factors ) { err_printf ("Exceeded max_factors %d in mpz_factor_small\n", max_factors); exit (0); }
1097
mpz_remove (d, d, x);
1098
}
1099
}
1100
if ( mpz_cmp_ui (m, 1) == 0 ) return w;
1101
if ( mpz_sizeinbase (m, 2) > max_hard_bits ) return -1;
1102
while ( ! mpz_probab_prime_p (m, 5) ) {
1103
mpz_pollard_rho (d, m);
1104
if ( ! mpz_fits_ulong_p (d) ) { err_printf ("factor too big to fit in unsigned long!"); return -1; }
1105
pt = mpz_get_ui (d);
1106
ht = mpz_remove (m, m, d);
1107
for ( i = 0 ; i < w ; i++ ) if ( p[i] > pt ) break;
1108
for ( j = w ; j-1 >= i ; j-- ) { p[j] = p[j-1]; h[j] = h[j-1]; }
1109
p[j] = pt;
1110
h[j] = ht;
1111
w++;
1112
if ( mpz_cmp_ui (m,1) == 0 ) return w;
1113
if ( w == max_factors ) { err_printf ("Exceeded max_factors %d in mpz_factor_small\n", max_factors); exit (0); }
1114
}
1115
if ( ! mpz_fits_ulong_p (m) ) {
1116
mpz_set (bigp, m);
1117
} else {
1118
mpz_set_ui (bigp, 1);
1119
pt = mpz_get_ui (m);
1120
ht = 1;
1121
for ( i = 0 ; i < w ; i++ ) if ( p[i] > pt ) break;
1122
for ( j = w ; j-1 >= i ; j-- ) { p[j] = p[j-1]; h[j] = h[j-1]; }
1123
p[j] = pt;
1124
h[j] = ht;
1125
w++;
1126
}
1127
return w;
1128
}
1129
1130
1131
int mpz_pollard_rho (mpz_t d, mpz_t n)
1132
{
1133
static int init;
1134
static mpz_t x, y, z, t, P;
1135
register unsigned c, i, j, k, m;
1136
1137
if ( ! init ) { mpz_util_init(); mpz_init (x); mpz_init (y); mpz_init(t); mpz_init (P); mpz_init (z); init = 1; }
1138
m = 0;
1139
for ( c = 1 ;; c++ ) {
1140
mpz_set_ui (x, 2);
1141
mpz_set_ui (y, 2);
1142
i = 1;
1143
k = 2;
1144
for (;;) {
1145
mpz_set_ui (P, 1);
1146
mpz_set (t, x);
1147
for ( j = 0 ; i < k && j < 20 ; j++ ) {
1148
m++;
1149
i++;
1150
mpz_mul (x, x, x);
1151
mpz_add_ui (x, x, c);
1152
mpz_mod (x, x, n);
1153
mpz_sub (z, y, x);
1154
mpz_mulm (P, P, z, n);
1155
}
1156
mpz_gcd (d, P, n);
1157
if ( mpz_cmp_ui (d,1) != 0 ) {
1158
mpz_set (x,t);
1159
do {
1160
mpz_mul (x, x, x);
1161
mpz_add_ui (x, x, c);
1162
mpz_mod (x, x, n);
1163
mpz_sub (z, y, x);
1164
mpz_gcd (d, z, n);
1165
} while ( mpz_cmp_ui (d,1) == 0 );
1166
if ( mpz_cmp (d,n) != 0 ) return m;
1167
break;
1168
}
1169
if ( i == k ) {
1170
mpz_set (y,x);
1171
k *= 2;
1172
}
1173
}
1174
}
1175
return 1;
1176
}
1177
1178
1179
// computes the y-coarse part of x
1180
int mpz_coarse_part (mpz_t o, mpz_t x, mpz_t y)
1181
{
1182
static int init;
1183
static mpz_t d, z;
1184
int i, j, w;
1185
1186
if ( ! init ) { mpz_util_init(); mpz_init (d); mpz_init (z); init = 1; }
1187
if ( mpz_cmp (x,y) <= 0 ) { mpz_set_ui (o,1); return 1; }
1188
mpz_gcd (d, x, mpz_util_primorial);
1189
mpz_set (o, x);
1190
for ( i = 1 ; i <= MPZ_SMALL_PRIMES ; i++ ) {
1191
if ( mpz_cmp_ui (y, mpz_util_primes[i]) < 0 ) break;
1192
if ( mpz_divisible_ui_p (d, mpz_util_primes[i]) ) {
1193
mpz_set_ui (z, mpz_util_primes[i]);
1194
mpz_remove (o, o, z);
1195
}
1196
}
1197
if ( i <= MPZ_SMALL_PRIMES ) return 1;
1198
if ( mpz_cmp (o,y) <= 0 ) { mpz_set_ui (o, 1); return 1; }
1199
mpz_set_ui (d, MPZ_MAX_SMALL_PRIME);
1200
while ( ! mpz_probab_prime_p (o, 5) ) {
1201
while ( ! mpz_divisible_p (o, d) ) {
1202
mpz_nextprime (d, d);
1203
if ( mpz_cmp (d, y) > 0 ) return 1;
1204
}
1205
mpz_remove (o, o, d);
1206
}
1207
return 1;
1208
}
1209
1210
1211
int mpz_eval_expr (mpz_t o, char *expr)
1212
{
1213
static int init;
1214
static mpz_t p, x, y, z;
1215
char *s, *t, op, nextop;
1216
int i, digits, n;
1217
1218
if ( ! init ) { mpz_init (p); mpz_init (x); mpz_init (y); mpz_init (z); init = 1; }
1219
mpz_util_init();
1220
s = expr;
1221
if ( *s == 'D' || *s == 'd' ) {
1222
digits = atoi (s+1);
1223
mpz_ui_pow_ui (x, 10, digits);
1224
do {
1225
mpz_urandomm (o, mpz_util_rands, x);
1226
} while ( ! mpz_tstbit (o, 0) );
1227
if ( mpz_congruent_ui_p (o, 1, 4) ) mpz_mul_2exp (o, o, 2);
1228
info_printf ("Random Discriminant: %Zd\n", o);
1229
return 1;
1230
}
1231
if ( *s == 'R' || *s == 'r' ) {
1232
digits = atoi (s+1);
1233
mpz_ui_pow_ui (x, 10, digits);
1234
mpz_urandomm (o, mpz_util_rands, x);
1235
info_printf ("Random Number: %Zd\n", o);
1236
return 1;
1237
}
1238
if ( *s == 'P' || *s == 'p' ) {
1239
digits = atoi (s+1);
1240
mpz_ui_pow_ui (x, 10, digits);
1241
mpz_urandomm (o, mpz_util_rands, x);
1242
do {
1243
mpz_nextprime (o, o);
1244
} while ( ! mpz_probab_prime_p (o, 20) ); // We really want to be sure here so we don't screw up test cases
1245
info_printf ("Random Prime: %Zd\n", o);
1246
return 1;
1247
}
1248
if ( *s == 'B' || *s == 'b' ) {
1249
digits = atoi (s+1);
1250
mpz_ui_pow_ui (x, 10, digits);
1251
mpz_urandomm (o, mpz_util_rands, x);
1252
do {
1253
mpz_nextprime (o, o);
1254
} while ( ! mpz_congruent_ui_p (o, 3, 4) || ! mpz_probab_prime_p (o, 20) ); // We really want to be sure here so we don't screw up test cases
1255
info_printf ("Random Prime 3mod4: %Zd\n", o);
1256
return 1;
1257
}
1258
if ( *s == 'C' || *s == 'c' ) {
1259
digits = atoi (s+1);
1260
mpz_ui_pow_ui (x, 10, digits/2);
1261
mpz_urandomm (y, mpz_util_rands, x);
1262
mpz_nextprime (y, y);
1263
mpz_urandomm (z, mpz_util_rands, x);
1264
mpz_nextprime (z, z);
1265
mpz_mul (o, y, z);
1266
info_printf ("Random Composite of 2 Primes: %Zd\n", o);
1267
return 1;
1268
}
1269
mpz_set_ui (o, 1);
1270
mpz_set_ui (x, 1);
1271
op = '*';
1272
while ( expr_valid_op(op) ) {
1273
t = s;
1274
while ( isdigit (*s) ) s++;
1275
if ( s == t ) return 0;
1276
nextop = *s;
1277
*s++ = '\0';
1278
mpz_set (y, x);
1279
if ( mpz_set_str (x, t, 0) != 0 ) return 0;
1280
if ( nextop == '!' || nextop == '#' || nextop == '$' ) {
1281
if ( nextop == '!' ) {
1282
n = atoi (t);
1283
mpz_fac_ui (x, n);
1284
} else if ( nextop == '#' ) {
1285
mpz_set_ui (p,1);
1286
mpz_set_ui (z,1);
1287
for(;;) {
1288
mpz_nextprime (p, p);
1289
if ( mpz_cmp (p, x) > 0 ) break;
1290
mpz_mul (z, z, p);
1291
}
1292
mpz_set (x, z);
1293
} else if ( nextop == '$' ) {
1294
mpz_set_ui (p,1);
1295
mpz_set_ui (z,1);
1296
for ( i = 0 ; mpz_cmp_ui (x, i) > 0 ; i++ ) {
1297
mpz_nextprime (p, p);
1298
mpz_mul (z, z, p);
1299
}
1300
mpz_set (x, z);
1301
}
1302
nextop = *s;
1303
*s++ = '\0';
1304
}
1305
if ( op == 'E' || op == 'e' ) {
1306
n = atoi (t);
1307
if ( n > 0 ) {
1308
mpz_pow_ui (x, y, n-1);
1309
mpz_mul (o, o, x);
1310
}
1311
} else if ( op == '*' ) {
1312
mpz_mul (o, o, x);
1313
} else if ( op == '+' ) {
1314
mpz_add (o, o, x);
1315
return 1;
1316
} else if ( op == '-' ) {
1317
mpz_sub (o, o, x);
1318
return 1;
1319
}
1320
op = nextop;
1321
}
1322
return 1;
1323
}
1324
1325
1326
static unsigned long mpz_mulm_counter, mpz_powm_counter, mpz_powm_tiny_counter;
1327
static clock_t mpz_counter_reset_time;
1328
1329
void mpz_mulm (mpz_t o, mpz_t a, mpz_t b, mpz_t m)
1330
{ mpz_mul (o, a, b); mpz_mod (o, o, m); mpz_mulm_counter++; }
1331
1332
void mpz_addm (mpz_t o, mpz_t a, mpz_t b, mpz_t m)
1333
{ mpz_add (o, a, b); mpz_mod (o, o, m); }
1334
1335
void mpz_subm (mpz_t o, mpz_t a, mpz_t b, mpz_t m)
1336
{ mpz_sub (o, a, b); mpz_mod (o, o, m); }
1337
1338
// assumes input already mod m
1339
void mpz_negm (mpz_t a, mpz_t m)
1340
{ if ( mpz_sgn(a) ) mpz_sub (a, m, a); }
1341
1342
void mpz_subm_ui (mpz_t o, mpz_t a, unsigned long b, mpz_t m)
1343
{ mpz_sub_ui (o, a, b); mpz_mod (o, o, m); }
1344
1345
void mpz_set_i (mpz_t o, long n)
1346
{
1347
if ( n < 0 ) { mpz_set_ui (o, (unsigned long)(-n)); mpz_neg (o, o); } else { mpz_set_ui (o, (unsigned long)n); }
1348
}
1349
1350
void mpq_set_i (mpq_t o, long n)
1351
{
1352
if ( n < 0 ) { mpq_set_ui (o, (unsigned long)(-n), 1UL); mpq_neg (o, o); } else { mpq_set_ui (o, (unsigned long)n, 1UL); }
1353
}
1354
1355
// Optimize small powers - 0, 1, and 2 - assume b < m
1356
void mpz_powm_tiny (mpz_t o, mpz_t b, unsigned e, mpz_t m)
1357
{
1358
switch (e) {
1359
case 0: mpz_set_ui (o, 1); return;
1360
case 1: if ( o != b ) mpz_set (o, b); return;
1361
case 2: mpz_mulm (o, b, b, m); return;
1362
default: mpz_powm_ui (o, b, e, m); mpz_powm_tiny_counter;
1363
}
1364
return;
1365
}
1366
1367
void mpz_powm_big (mpz_t o, mpz_t b, mpz_t e, mpz_t m)
1368
{ mpz_powm (o, b, e, m); mpz_powm_counter++; }
1369
1370
void mpz_reset_counters ()
1371
{
1372
mpz_mulm_counter = 0;
1373
mpz_powm_counter = 0;
1374
mpz_powm_tiny_counter = 0;
1375
mpz_counter_reset_time = clock();
1376
}
1377
1378
void mpz_report_counters ()
1379
{
1380
info_printf ("Counters: %d mult, %d tiny exp, %d exp, %d msec\n", mpz_mulm_counter, mpz_powm_tiny_counter, mpz_powm_counter,
1381
delta_msecs(mpz_counter_reset_time, clock()));
1382
}
1383
1384
// Algorithm 1.5.1 in [CANT] - standard Tonelli-Shanks n^2 algorithm
1385
int mpz_sqrt_modprime (mpz_t o, mpz_t a, mpz_t p)
1386
{
1387
static mpz_t q, x, y, b;
1388
static int init;
1389
int i, r, m, e;
1390
1391
if ( ! init ) { mpz_util_init(); mpz_init (q); mpz_init (x); mpz_init (y); mpz_init (b); init = 1; }
1392
if ( ! mpz_sgn (a) ) { mpz_set_ui (o, 0); return 1; }
1393
if ( mpz_cmp_ui (a, 1) == 0 ) { mpz_set_ui (o, 1); return 1; }
1394
mpz_sub_ui (q, p, 1);
1395
mpz_set_ui (x, 2);
1396
e = mpz_remove (q, q, x);
1397
do {
1398
mpz_urandomm (x, mpz_util_rands, p);
1399
} while ( mpz_jacobi (x, p) != -1 );
1400
mpz_powm_big (y, x, q, p);
1401
r = e;
1402
mpz_sub_ui (q, q, 1);
1403
mpz_divexact_ui (q, q, 2);
1404
mpz_powm_big (x, a, q, p);
1405
mpz_mulm (b, a, x, p);
1406
mpz_mulm (b, b, x, p);
1407
mpz_mulm (x, a, x, p);
1408
for (;;) {
1409
if ( mpz_cmp_ui (b, 1) == 0 ) { mpz_set (o, x); break; }
1410
mpz_set (q, b);
1411
for ( m = 1 ; m <= r; m++ ) {
1412
mpz_mulm (q, q, q, p);
1413
if ( mpz_cmp_ui (q, 1) == 0 ) break;
1414
}
1415
if ( m > r ) { err_printf ("Unexpected result: m=%d > r=%d in mpz_sqrt_modprime?! a = %Zd, p = %Zd\n", m, r, a, p); exit (1); }
1416
if ( m == r ) return 0;
1417
mpz_set (q, y);
1418
for ( i = 0 ; i < r-m-1 ; i++ ) mpz_mulm (q, q, q, p);
1419
mpz_mulm (y, q, q, p);
1420
r = m;
1421
mpz_mulm (x, x, q, p);
1422
mpz_mulm (b, b, y, p);
1423
}
1424
/// dbg_printf ("%Zd is a square root of %Zd mod %Zd\n", o, a, p);
1425
return 1;
1426
}
1427
1428
// these are horribly inefficient
1429
unsigned long mpz_get_bits_ui (mpz_t a, unsigned long i, unsigned long n) // gets bits i thru i+n-1 and returns as ui
1430
{
1431
register unsigned long j, k, x, y;
1432
1433
/* y = 0;
1434
for ( j = i ; j < i+n ; j++ ) {
1435
if ( mpz_tstbit (a, j) ) y |= (1<<(j-i));
1436
}
1437
return y;
1438
*/
1439
if ( mp_bits_per_limb != ULONG_BITS ) { err_printf ("mpz_get_bits_ui needs mp_bits_per_limb == ULONG_BITS!\n"); exit (0); }
1440
j = i >> ULONG_BITS_LOG2;
1441
if ( j >= a->_mp_size ) return 0;
1442
x = a->_mp_d[j];
1443
k = i-(j<<ULONG_BITS_LOG2); // k = i mod ULONG_BITS < ULONG_BITS
1444
x >>= k;
1445
k = ULONG_BITS-k; // k = # bits in x > 0
1446
if ( k < n ) {
1447
if ( ++j >= a->_mp_size ) return x;
1448
x |= (a->_mp_d[j]&((1UL<<(n-k))-1))<<k; // get n-k more bits
1449
} else if ( k > n ) {
1450
x &= (1UL<<n)-1;
1451
}
1452
1453
// if ( x != y ) { err_printf ("bug in mpz_get_bits_ui(%Zx(hex),i,n) = %d != %d\n", a, i, n, x, y); exit (0); }
1454
1455
return x;
1456
}
1457
1458
// Note bits is assumed to contain only the n bits to be set, the higher order bits must be zero
1459
unsigned long mpz_set_bits_ui (mpz_t a, unsigned long i, unsigned long n, unsigned long bits) // sets bits i thru i+n-1 and returns as ui
1460
{
1461
register unsigned long j, k, k2, x;
1462
1463
/*
1464
for ( j = i ; j < i+n ; j++ ) {
1465
if ( bits&(1<<(j-i)) ) {
1466
mpz_setbit (a, j);
1467
} else {
1468
mpz_clrbit (a, j);
1469
}
1470
}
1471
return bits;
1472
*/
1473
if ( ! n ) return 0;
1474
if ( mp_bits_per_limb != ULONG_BITS ) { err_printf ("mpz_get_bits_ui needs mp_bits_per_limb == ULONG_BITS!\n"); exit (0); }
1475
j = i >> ULONG_BITS_LOG2;
1476
if ( j >= a->_mp_size ) { mpz_setbit (a, i+n-1); } // force size adjustment and realloc if required
1477
k = i-(j<<ULONG_BITS_LOG2); // k = i mod ULONG_BITS < ULONG_BITS
1478
x = bits<<k;
1479
x |= a->_mp_d[j] & ((1UL<<k)-1); // get k low bits that should remain the same
1480
k2 = ULONG_BITS-k; // k2 = # bits in set so far > 0
1481
if ( k2 < n ) {
1482
a->_mp_d[j] = x;
1483
if ( ++j >= a->_mp_size ) { mpz_setbit (a, i+n-1); } // force size adjustment and realloc if required
1484
x = bits >>k2;
1485
x |= (a->_mp_d[j]&~((1UL<<(n-k2))-1)); // get high bits that should remain the same
1486
a->_mp_d[j] = x;
1487
} else if ( k2 > n ) {
1488
x |= a->_mp_d[j] & ~((1UL<<(k+n))-1); // get high bits past k+n bits that should remain the same
1489
a->_mp_d[j] = x;
1490
} else {
1491
a->_mp_d[j] = x;
1492
}
1493
while ( a->_mp_size && ! a->_mp_d[a->_mp_size-1] ) a->_mp_size--;
1494
return bits;
1495
}
1496
1497
unsigned long ui_randomm (unsigned long m)
1498
{
1499
mpz_util_init();
1500
return gmp_urandomm_ui (mpz_util_rands, m);
1501
}
1502
1503
unsigned long ui_randomb (unsigned long b)
1504
{
1505
mpz_util_init();
1506
return gmp_urandomb_ui (mpz_util_rands, b);
1507
}
1508
1509
unsigned long ui_pp_div (unsigned long n, unsigned long p)
1510
{
1511
unsigned long q;
1512
1513
if ( ! n ) return 1;
1514
q = 1;
1515
while ( (n%p) == 0 ) {
1516
n /= p;
1517
q *= p;
1518
}
1519
return q;
1520
}
1521
1522
1523
unsigned long ui_inverse (unsigned long a, unsigned long m)
1524
{
1525
register unsigned long q, r, r0, r1; // amazingly in this day and age, the register declaration gives a 10% improvement
1526
register long t, t0, t1;
1527
1528
if ( a >= m ) a = a%m;
1529
if ( a == 0 ) return 0;
1530
1531
t1 = 1;
1532
t0 = 0;
1533
r0 = m;
1534
r1 = a;
1535
while ( r1 > 0 ) {
1536
q = r0/r1;
1537
r = r0 - q*r1;
1538
r0 = r1;
1539
r1 = r;
1540
t = t0 - q*t1;
1541
t0 = t1;
1542
t1 = t;
1543
}
1544
if ( r0 > 1 ) return 0;
1545
if ( t0 < 0 ) return m - ((unsigned long)(-t0));
1546
return (unsigned long)t0;
1547
}
1548
1549
// return 1 if the integer represented by the prime factorization (p,h,w) <ULONG_MAX contains a divisor in [min,max]
1550
// slow implementation
1551
int ui_divisor_in_interval (unsigned long p[], unsigned long h[], int w, unsigned long min, unsigned long max)
1552
{
1553
register unsigned long n;
1554
unsigned long e[MPZ_MAX_FACTORS+1];
1555
register int i, j;
1556
1557
if ( min > max ) return 0;
1558
if ( min <= 1 ) return 1;
1559
for ( i = 0 ; i < w ; i++ ) e[i] = 0;
1560
for (;;) {
1561
n = 1;
1562
for ( j = 0 ; j < w ; j++ ) {
1563
if ( e[j] ) {
1564
n *= p[j];
1565
for ( i = 1 ; i < e[j] ; i++ ) n *= p[j];
1566
}
1567
}
1568
// printf ("n=%d\n", n);
1569
if ( n >= min && n <= max ) return 1;
1570
e[0]++;
1571
for ( i = 0 ; e[i] > h[i] ; i++ ) { if ( i == w-1 ) return 0; e[i] = 0; e[i+1]++; }
1572
}
1573
}
1574
1575
// a is compatible with b if it is composed entirely of primes dividing b
1576
int ui_compatible (unsigned long a, unsigned long b)
1577
{
1578
unsigned long d;
1579
1580
while ( a != 1 ) {
1581
d = ui_gcd(a,b);
1582
if ( d == 1 ) return 0;
1583
a /= d;
1584
}
1585
return 1;
1586
}
1587
1588
// a is compatible with b if it is composed entirely of primes dividing b
1589
int mpz_compatible (mpz_t a, mpz_t b)
1590
{
1591
static int init;
1592
static mpz_t t, d;
1593
1594
if ( ! init ) { mpz_init(d); mpz_init(t); init = 1; }
1595
mpz_set (t, a);
1596
while ( mpz_cmp_ui (t,1) != 0 ) {
1597
mpz_gcd (d, t, b);
1598
if ( mpz_cmp_ui(d,1) == 0 ) return 0;
1599
mpz_divexact(t,t,d);
1600
}
1601
return 1;
1602
}
1603
1604
unsigned long ui_crt (unsigned long a, unsigned long M, unsigned long b, unsigned long N)
1605
{
1606
unsigned long x;
1607
1608
if ( a > b ) {
1609
x = ui_inverse (N, M);
1610
return (x*N*(a-b)+b)%(M*N);
1611
} else {
1612
x = ui_inverse (M, N);
1613
return (x*M*(b-a)+a)%(M*N);
1614
}
1615
}
1616
1617
unsigned long ui_gcd (unsigned long a, unsigned long b)
1618
{ return (ui_gcd_ext (a, b, NULL, NULL)); }
1619
1620
unsigned long ui_gcd_ext (unsigned long a, unsigned long b, long *x, long *y)
1621
{
1622
register unsigned long q, r, r0, r1;
1623
register long s, t, s0, s1, t0, t1;
1624
1625
if ( a < b ) return (ui_gcd_ext (b, a, y, x));
1626
if ( b == 0 ) {
1627
if ( x ) *x = 1;
1628
if ( y ) *y = 0;
1629
return a;
1630
}
1631
if ( x ) { s0 = 1; s1 = 0; }
1632
if ( y ) { t1 = 1; t0 = 0; }
1633
r0 = a;
1634
r1 = b;
1635
while ( r1 > 0 ) {
1636
q = r0/r1;
1637
r = r0 - q*r1;
1638
r0 = r1;
1639
r1 = r;
1640
if ( y ) {
1641
t = t0 - q*t1;
1642
t0 = t1;
1643
t1 = t;
1644
}
1645
if ( x ) {
1646
s = s0 - q*s1;
1647
s0 = s1;
1648
s1 = s;
1649
}
1650
}
1651
if ( x ) *x = s0;
1652
if ( y ) *y = t0;
1653
return r0;
1654
}
1655
1656
// Assumes gcd(a,b,N) = 1 but does not verify this
1657
unsigned long bach_gcd (long a, long b, unsigned long N)
1658
{
1659
unsigned long c, g, h;
1660
unsigned long M, K;
1661
1662
g = ui_gcd(abs(a),N);
1663
if ( g == 1 ) return 0;
1664
if ( ui_gcd(abs(a+b),N) == 1 ) return 1;
1665
M = N;
1666
for ( h = g ; h > 1 ; ) {
1667
do { M /= h; } while ( (M%h) == 0 );
1668
h = ui_gcd (M, g); // could use h instead of g?
1669
}
1670
// M>1 should now be a factor of N that is relatively prime to both g and N
1671
if ( M <= 1 || (N%M)!=0 ) { out_printf ("Error M=%d in bach_gcd\n", M); exit (1); }
1672
c = (M*ui_inverse(M,N/M)) % N;
1673
if ( c == 0 ) { out_printf ("Error c == 0 in bach_gcd\n", c); exit (1); }
1674
return c;
1675
}
1676
1677
1678
1679
1680
int mpz_eval_term_ui (mpz_t o, unsigned long numvars, unsigned long vars[], unsigned long exps[])
1681
{
1682
static int init;
1683
static mpz_t x;
1684
int i;
1685
1686
if ( ! init ) { mpz_init (x); init = 1; }
1687
1688
mpz_set_ui (o, 1);
1689
for ( i = 0 ; i < numvars ; i++ ) {
1690
if ( exps[i] > 0 ) {
1691
mpz_ui_pow_ui (x, vars[i], exps[i]);
1692
mpz_mul (o, o, x);
1693
}
1694
}
1695
return 1;
1696
}
1697
1698
1699
char *ui_term_to_string (char *buf, unsigned long numvars, unsigned long vars[], unsigned long exps[])
1700
{
1701
char *s;
1702
int i;
1703
1704
if ( ! numvars ) { strcpy (buf, "1"); return buf; }
1705
s = buf;
1706
*s = '\0';
1707
for ( i = 0 ; i < numvars ; i++ ) {
1708
if ( exps[i] > 0 ) {
1709
if ( s > buf ) *s++ = '*';
1710
sprintf (s, "%d^%d", vars[i], exps[i]);
1711
while ( *s ) s++;
1712
}
1713
}
1714
return buf;
1715
}
1716
1717
unsigned long ui_wt (unsigned long x)
1718
{
1719
unsigned long i, n;
1720
1721
n = 0;
1722
for ( i = 1 ; i <= x ; i <<= 1 ) {
1723
if ( i&x ) n++;
1724
}
1725
return n;
1726
}
1727
1728
unsigned long ui_lg_ceil (unsigned long x)
1729
{
1730
unsigned long i;
1731
1732
i = _asm_highbit(x);
1733
if ( x==(1UL<<i) ) return i; else return i+1;
1734
}
1735
1736
unsigned long ui_binexp_cost (unsigned long x)
1737
{ return ui_len(x) + ui_wt(x) - 2; }
1738
1739
unsigned long ui_get_bits (unsigned long x, unsigned long pos, unsigned long bits)
1740
{
1741
unsigned long i, m;
1742
1743
m = 0;
1744
for ( i = pos ; i < pos+bits ; i++ ) m |= (1<<i);
1745
m &= x;
1746
return (m >> pos);
1747
}
1748
1749
char *ui_bit_string (char *buf, unsigned long x)
1750
{
1751
int i;
1752
1753
for ( i = ui_len(x)-1 ; i >= 0 ; i-- ) *buf++ = ( (x & (1<<i)) ? 1 : 0 );
1754
*buf = '\0';
1755
return buf;
1756
}
1757
1758
void ui_invert_permutation (unsigned long p2[], unsigned long p1[], unsigned long n)
1759
{
1760
unsigned long i;
1761
1762
for ( i = 0 ; i < n ; i++ ) p2[p1[i]] = i;
1763
}
1764
1765
1766
double mpz_log2 (mpz_t a)
1767
{
1768
unsigned long b, n;
1769
1770
b = mpz_sizeinbase(a,2);
1771
if ( ! b ) return 0.0; // define lg(0) = 0 for convenience
1772
if ( b < ULONG_BITS ) {
1773
n = mpz_get_ui (a);
1774
return log2((double)n);
1775
} else {
1776
n = mpz_get_bits_ui (a, b-(ULONG_BITS-1), ULONG_BITS-2);
1777
return (double)(b-1) + log2(1.0+(double)n/(double)(1UL<<(ULONG_BITS-2)));
1778
}
1779
}
1780
1781
1782
int ui_qsort_cmp (const void *a, const void *b)
1783
{
1784
if ( ((unsigned long*)a) > ((unsigned long *)b) ) return 1;
1785
if ( ((unsigned long*)b) > ((unsigned long *)a) ) return -1;
1786
return 0;
1787
}
1788
1789
int _qsort_mpz_cmp (const void *a, const void *b)
1790
{
1791
return mpz_cmp (*((mpz_t *)a), *((mpz_t *)b));
1792
}
1793
1794
1795
void mpz_sort (mpz_t a[], unsigned long n)
1796
{
1797
qsort (a, n, sizeof(a[0]), _qsort_mpz_cmp);
1798
}
1799
1800
1801
unsigned long mpz_randomf (mpz_t o, mpz_t N, mpz_t factors[], unsigned long w)
1802
{
1803
return mpz_randomft (o, N, factors, NULL, w);
1804
}
1805
1806
1807
/*
1808
The algorithm below is an implementation of Bach's algorithm for computing random factored integers.
1809
See "Analytic Methods in the Analysis and Design of Number-Theoretic Algorithms", Eric Bach, MIT Press 1984
1810
Returns the factorization of a random integer in the range (N/2,N]
1811
*/
1812
1813
unsigned long mpz_randomft (mpz_t o, mpz_t N, mpz_t factors[], mpz_ftree_t factor_trees[], unsigned long w)
1814
{
1815
mpz_t d, Q, M;
1816
mpf_t x;
1817
mpz_ftree_t t;
1818
double b, u;
1819
unsigned long n;
1820
int i, j, k, m, q;
1821
1822
mpz_init (d);
1823
mpz_init (M);
1824
mpz_util_init ();
1825
1826
if ( w == 0 ) { err_printf ("Factor array too small - increase size!\n"); exit (1); }
1827
1828
// Base case
1829
if ( mpz_cmp_ui (N, MPZ_MAX_SMALL_INTEGER) <= 0 ) {
1830
// pick random r in (N/2,N]
1831
mpz_fdiv_q_2exp (M, N, 1);
1832
mpz_sub (d, N, M);
1833
mpz_urandomm (o, mpz_util_rands, d);
1834
mpz_add (o, o, M);
1835
mpz_add_ui (o, o, 1);
1836
// factor r using small factors array
1837
n = mpz_get_ui (o);
1838
k = 0;
1839
while ( n > 1 ) {
1840
if ( k >= w ) { err_printf ("Factor array too small - increase size!\n"); exit (1); }
1841
q = mpz_small_factors[n];
1842
if ( ! q ) q = n;
1843
if ( n%q ) { err_printf ("Small factor array assert failed - %d not divisible by %d\n", n, q); exit (1); }
1844
n /= q;
1845
for ( i = 0 ; i < k ; i++ ) {
1846
if ( mpz_divisible_ui_p (factors[i], q) ) {
1847
mpz_mul_ui (factors[i], factors[i], q);
1848
break;
1849
}
1850
}
1851
if ( i == k ) mpz_set_ui (factors[k++], q);
1852
}
1853
mpz_clear (d);
1854
mpz_clear (M);
1855
return k;
1856
}
1857
1858
mpz_init (Q);
1859
mpf_init (x);
1860
for (;;) {
1861
if ( factor_trees ) {
1862
t = mpz_randomfpp (Q, N);
1863
} else {
1864
mpz_randompp (Q, N);
1865
}
1866
mpz_fdiv_q (M, N, Q);
1867
k = mpz_randomf (o, M, factors, w-1);
1868
for ( i = 0 ; i < k ; i++ ) {
1869
if ( mpz_divisible_p (factors[i], Q) ) {
1870
mpz_mul (factors[i], factors[i], Q);
1871
break;
1872
}
1873
}
1874
if ( i == k ) {
1875
if ( factor_trees ) factor_trees[k] = t;
1876
mpz_set (factors[k++], Q);
1877
} else {
1878
if ( factor_trees ) mpz_clear_ftree (t);
1879
}
1880
mpz_set_ui (o, 1);
1881
for ( i = 0 ; i < k ; i++ ) mpz_mul (o, o, factors[i]);
1882
b = (mpz_log2 (N) - 1.0) / mpz_log2 (o);
1883
mpf_urandomb (x, mpz_util_rands, 64);
1884
u = mpf_get_d (x);
1885
if ( u <= b ) break;
1886
dbg_printf ("random reject %f > %f\n", u, b);
1887
if ( factor_trees ) for ( i = 0 ; i < k ; i++ ) mpz_clear_ftree(t);
1888
}
1889
// Need to clean-up factorizations of p-1 to make sure we deal with cases where we generated a prime power with
1890
// the factorization of p^k-1. Fortunately (p-1)|p^k-1, so all the prime factors of p-1 are present in the factorization
1891
// of p^k-1, we just need to pick them out.
1892
if ( factor_trees ) {
1893
dbg_printf ("cleaning up\n");
1894
for ( i = 0 ; i < k ; i++ ) {
1895
if ( ! mpz_perfect_power_p (factors[i]) ) continue;
1896
if ( ! mpz_pp_base (Q, factors[i]) ) { err_printf ("Unable to extract prime power base from a known prime power!"); exit (0); }
1897
mpz_sub_ui (Q, Q, 1);
1898
m = 0;
1899
t = factor_trees[i];
1900
for ( j = 0 ; j < t->w ; j++ ) {
1901
mpz_gcd (d, Q, t->factors[j]);
1902
if ( mpz_cmp_ui (d,1) > 0 ) mpz_set (t->factors[m++], d);
1903
}
1904
for ( j = m ; j < t->w ; j++ ) mpz_clear (t->factors[j]);
1905
t->w = m;
1906
// sanity check the results
1907
mpz_set_ui (d, 1);
1908
for ( j = 0 ; j < t->w ; j++ ) mpz_mul (d, d, t->factors[j]);
1909
if ( mpz_cmp (Q, d) != 0 ) { err_printf ("Invalid factorization of p-1 after prime power cleanup! %Zd != %Zd\n", d, Q); exit (0); }
1910
}
1911
}
1912
mpz_clear (d);
1913
mpz_clear (M);
1914
mpz_clear (Q);
1915
mpf_clear (x);
1916
return k;
1917
}
1918
1919
// Returns a random prime power in the range [2,N]
1920
void mpz_randompp (mpz_t Q, mpz_t N)
1921
{
1922
static int init;
1923
static mpz_t M, M2, J, p, d, r;
1924
static mpf_t x, y;
1925
double b, u;
1926
unsigned long i, j, n;
1927
1928
if ( ! init ) {
1929
mpz_init (M); mpz_init (M2); mpz_init (J); mpz_init (p); mpz_init (d); mpz_init (r); mpf_init (x); mpf_init (y);
1930
mpz_util_init ();
1931
init = 1;
1932
}
1933
for (;;) {
1934
// select random j in [1,log2(N)]
1935
n = (unsigned long)ceil (mpz_log2 (N));
1936
j = gmp_urandomm_ui (mpz_util_rands, n) + 1;
1937
mpz_ui_pow_ui (J, 2, j);
1938
mpz_urandomm (r, mpz_util_rands, J);
1939
mpz_add (Q, J, r);
1940
if ( mpz_cmp (Q, N) > 0 ) continue;
1941
if ( mpz_perfect_power_p (Q) ) {
1942
if ( ! mpz_pp_base (p, Q) ) continue;
1943
} else {
1944
mpz_set (p, Q);
1945
}
1946
mpz_gcd (d, p, mpz_util_primorial);
1947
if ( mpz_cmp_ui (d,1) != 0 && mpz_cmp (d,p) != 0 ) continue;
1948
if ( ! mpz_probab_prime_p (p, 5) ) continue;
1949
mpf_urandomb (x, mpz_util_rands, 64);
1950
u = mpf_get_d (x);
1951
mpz_fdiv_q (M, N, Q);
1952
mpz_mul_ui (d, Q, 2);
1953
mpz_fdiv_q (M2, N, d);
1954
mpz_sub (M, M, M2);
1955
//err_printf ("#(N/2q,N/q] = %Zd for N = %Zd, q = %Zd\n", M, N, Q);
1956
mpz_mul (M, M, J);
1957
mpf_set_z (x, M);
1958
mpf_set_z (y, N);
1959
mpf_div (x, x, y);
1960
b = mpf_get_d (x);
1961
//err_printf ("b = %f, Q = %Zd, p = %Zd, log2(p) = %f, log2(N) = %f\n", b, Q, p, mpz_log2(p), mpz_log2(N));
1962
b *= mpz_log2(p) / mpz_log2(N);
1963
if ( u < b ) break;
1964
//err_printf ("random reject %f >= %f\n", u, b);
1965
}
1966
}
1967
1968
// optimize later
1969
unsigned long ui_pp_base (unsigned long pp)
1970
{
1971
static int init;
1972
static mpz_t x, b;
1973
1974
if ( ! init ) { mpz_init (x); mpz_init (b); }
1975
mpz_set_ui (x, pp);
1976
if ( mpz_probab_prime_p (x, 5) ) return mpz_get_ui (x);
1977
if ( ! mpz_pp_base (b, x) ) return 0;
1978
return mpz_get_ui (b);
1979
}
1980
1981
1982
/*
1983
Extracts base from a prime power and returns the exponent
1984
*/
1985
unsigned long mpz_pp_base (mpz_t b, mpz_t q)
1986
{
1987
static int init;
1988
static mpz_t p, x, y, z;
1989
double d;
1990
int c, m, n;
1991
1992
if ( ! init ) { mpz_util_init (); mpz_init (p); mpz_init (x); mpz_init (y); mpz_init (z); init = 1; }
1993
mpz_gcd (p, q, mpz_util_primorial);
1994
if ( mpz_cmp_ui (p, 1) != 0 ) {
1995
if ( mpz_cmp_ui(p,MPZ_MAX_SMALL_PRIME) > 0 || ! ui_is_small_prime (mpz_get_ui(p)) ) return 0; // q divisible by more than 1 small prime
1996
mpz_fdiv_q (x, q, p);
1997
n = 1;
1998
while ( mpz_cmp_ui (x,1) > 0 ) {
1999
mpz_fdiv_qr (x, z, x, p);
2000
if ( mpz_cmp_ui (z, 0) != 0 ) return 0; // q is not a prime power
2001
n++;
2002
}
2003
mpz_set (b, p);
2004
return n;
2005
} else {
2006
// This is not particular efficient, but it rarely gets used.
2007
if ( mpz_probab_prime_p (q, 5) ) { mpz_set (b, q); return 1; }
2008
n = mpz_sizeinbase (q,2)/ui_lg_floor(mpz_util_primes[MPZ_SMALL_PRIMES]);
2009
while ( n >= 0 ) {
2010
mpz_ui_pow_ui (z, 2, (mpz_sizeinbase (q,2) / n) + 1); // upper bound
2011
mpz_ui_pow_ui (y, 2, (mpz_sizeinbase (q,2)-1) / n); // lower bound
2012
do {
2013
mpz_add (x, y, z);
2014
mpz_tdiv_q_ui (x, x, 2); // middle
2015
mpz_pow_ui (p, x, n);
2016
c = mpz_cmp (p, q);
2017
if ( ! c ) { if ( ! mpz_probab_prime_p (x, 5) ) return 0; mpz_set (b, x); return n; }
2018
if ( c < 0 ) {
2019
mpz_add_ui (y, x, 1);
2020
} else {
2021
mpz_sub_ui (z, x, 1);
2022
}
2023
} while ( mpz_cmp (y,z) <= 0 );
2024
n--;
2025
}
2026
}
2027
return 0;
2028
}
2029
2030
mpz_ftree_t mpz_randomfp (mpz_t o, mpz_t N)
2031
{
2032
static int init;
2033
static mpz_t N2;
2034
mpz_ftree_t t;
2035
int i;
2036
2037
if ( ! init ) { mpz_init(N2); init = 1; }
2038
mpz_sub_ui (N2, N, 1);
2039
mpz_fdiv_q_ui (N2, N2, 2);
2040
t = (struct factor_tree_item_struct *)mem_alloc (sizeof (*t));
2041
for ( i = 0 ; i < MPZ_MAX_TREE_FACTORS ; i++ ) mpz_init (t->factors[i]);
2042
for (;;) {
2043
t->w = mpz_randomf (o, N2, t->factors, MPZ_MAX_TREE_FACTORS);
2044
mpz_mul_ui (o, o, 2);
2045
mpz_add_ui (o, o, 1);
2046
if ( mpz_probab_prime_p (o, 5) ) break;
2047
out_printf (".");
2048
}
2049
mpz_sort (t->factors, t->w);
2050
for ( i = 0 ; i < t->w ; i++ ) {
2051
if ( ! mpz_tstbit (t->factors[i], 0) ) break;
2052
}
2053
if ( i < t->w ) {
2054
mpz_mul_ui (t->factors[i], t->factors[i], 2);
2055
} else {
2056
if ( t->w >= MPZ_MAX_TREE_FACTORS ) { err_printf ("Exceeded MPZ_MAX_TREE_FACTORS!"); exit (0); }
2057
for ( i = t->w ; i > 0 ; i-- ) mpz_set (t->factors[i], t->factors[i-1]);
2058
mpz_set_ui (t->factors[0], 2);
2059
t->w++;
2060
}
2061
return t;
2062
}
2063
2064
2065
mpz_ftree_t mpz_randomfpp (mpz_t o, mpz_t N)
2066
{
2067
static int init;
2068
static mpz_t d, p, N2;
2069
mpz_ftree_t t;
2070
int i;
2071
2072
if ( ! init ) { mpz_init (d); mpz_init (p); mpz_init(N2); init = 1; }
2073
mpz_sub_ui (N2, N, 1);
2074
mpz_fdiv_q_ui (N2, N2, 2);
2075
t = (struct factor_tree_item_struct*)mem_alloc (sizeof (*t));
2076
for ( i = 0 ; i < MPZ_MAX_TREE_FACTORS ; i++ ) mpz_init (t->factors[i]);
2077
for (;;) {
2078
t->w = mpz_randomf (o, N2, t->factors, MPZ_MAX_TREE_FACTORS);
2079
out_printf (".");
2080
mpz_mul_ui (o, o, 2);
2081
mpz_add_ui (o, o, 1);
2082
if ( mpz_perfect_power_p (o) ) {
2083
if ( ! mpz_pp_base (p, o) ) continue;
2084
} else {
2085
mpz_set (p, o);
2086
}
2087
mpz_gcd (d, p, mpz_util_primorial);
2088
if ( mpz_cmp_ui (d,1) != 0 && mpz_cmp (d,p) != 0 ) continue;
2089
if ( ! mpz_probab_prime_p (p, 5) ) continue;
2090
}
2091
mpz_sort (t->factors, t->w);
2092
for ( i = 0 ; i < t->w ; i++ ) {
2093
if ( ! mpz_tstbit (t->factors[i], 0) ) break;
2094
}
2095
if ( i < t->w ) {
2096
mpz_mul_ui (t->factors[i], t->factors[i], 2);
2097
} else {
2098
if ( t->w >= MPZ_MAX_TREE_FACTORS ) { err_printf ("Exceeded MPZ_MAX_TREE_FACTORS!"); exit (0); }
2099
for ( i = t->w ; i > 0 ; i-- ) mpz_set (t->factors[i], t->factors[i-1]);
2100
mpz_set_ui (t->factors[0], 2);
2101
t->w++;
2102
}
2103
return t;
2104
}
2105
2106
2107
void mpz_clear_ftree (mpz_ftree_t t)
2108
{
2109
int i;
2110
2111
for ( i = 0 ; i < t->w ; i++ ) {
2112
if ( t->subtrees[i] ) mpz_clear_ftree (t->subtrees[i]);
2113
}
2114
for ( i = 0 ; i < MPZ_MAX_TREE_FACTORS ; i++ ) mpz_clear (t->factors[i]);
2115
}
2116
2117
2118
unsigned long mpz_store_bytes (mpz_t a)
2119
{
2120
unsigned long size;
2121
2122
size = _ui_ceil_ratio(mpz_sizeinbase(a,2),8);
2123
if ( size+2 >= (1<<15) ) { err_printf ("Integer %Zd too large to store!\n", a); exit (0); }
2124
return size+2;
2125
}
2126
2127
2128
void mpz_store (char *s, mpz_t a)
2129
{
2130
struct _group_storage_block *pStore;
2131
size_t size, count;
2132
short cnt;
2133
2134
size = _ui_ceil_ratio(mpz_sizeinbase(a,2),8);
2135
if ( size+1 >= (1<<15) ) { err_printf ("Integer %Zd too large to store!\n", a); exit (0); }
2136
mpz_export (s+sizeof(short), &count, 1, 1, 0, 0, a);
2137
if ( count >= (1<<15) ) { err_printf ("mpz_export wrote too many bytes for integer %Zd\n", a); exit (0); }
2138
cnt = (short)count;
2139
if ( mpz_sgn(a) < 0 ) cnt = -cnt;
2140
*((short*)s) = cnt;
2141
return;
2142
}
2143
2144
2145
void mpz_retrieve (mpz_t o, char *s)
2146
{
2147
short cnt;
2148
int sign;
2149
2150
cnt = *((short*)s);
2151
sign = 1;
2152
if ( cnt < 0 ) { sign = -1; cnt = -cnt; }
2153
mpz_import (o, (unsigned long)cnt, 1, 1, 0, 0, s+2);
2154
if ( sign < 0 ) mpz_neg (o, o);
2155
return;
2156
}
2157
2158
2159
unsigned long ui_eval_expr (char *expr)
2160
{
2161
char *s;
2162
unsigned long n;
2163
int i, j, k;
2164
2165
for ( s = expr ; *s && *s != 'e' ; s++ );
2166
if ( *s ) {
2167
*s++ = '\0';
2168
k = atoi(expr);
2169
j = atoi(s);
2170
for ( i = 0, n = 1 ; i < j ; i++ ) n *= k;
2171
} else {
2172
n = atoll (expr);
2173
}
2174
return n;
2175
}
2176
2177
NAF_entry_t ui_NAF_table[2][4] = { {{0,0}, {1,0}, {0,0}, {-1,1}}, {{1,0},{0,1},{-1,1},{0,1}} };
2178
unsigned char NAF_pbits_tab[1024] = {0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 32, 32, 32, 33, 34, 32, 32, 33, 32, 32, 32, 33, 34, 36, 36, 37, 40, 40, 40, 41, 42, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 64, 64, 64, 65, 66, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 72, 72, 72, 73, 74, 80, 80, 81, 80, 80, 80, 81, 82, 84, 84, 85, 128, 128, 128, 129, 130, 128, 128, 129, 128, 128, 128, 129, 130, 132, 132, 133, 136, 136, 136, 137, 138, 128, 128, 129, 128, 128, 128, 129, 130, 132, 132, 133, 128, 128, 128, 129, 130, 128, 128, 129, 128, 128, 128, 129, 130, 132, 132, 133, 136, 136, 136, 137, 138, 144, 144, 145, 144, 144, 144, 145, 146, 148, 148, 149, 160, 160, 160, 161, 162, 160, 160, 161, 160, 160, 160, 161, 162, 164, 164, 165, 168, 168, 168, 169, 170, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 32, 32, 32, 33, 34, 32, 32, 33, 32, 32, 32, 33, 34, 36, 36, 37, 40, 40, 40, 41, 42, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 64, 64, 64, 65, 66, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 72, 72, 72, 73, 74, 80, 80, 81, 80, 80, 80, 81, 82, 84, 84, 85, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 32, 32, 32, 33, 34, 32, 32, 33, 32, 32, 32, 33, 34, 36, 36, 37, 40, 40, 40, 41, 42, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 32, 32, 32, 33, 34, 32, 32, 33, 32, 32, 32, 33, 34, 36, 36, 37, 40, 40, 40, 41, 42, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 64, 64, 64, 65, 66, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 72, 72, 72, 73, 74, 80, 80, 81, 80, 80, 80, 81, 82, 84, 84, 85, 128, 128, 128, 129, 130, 128, 128, 129, 128, 128, 128, 129, 130, 132, 132, 133, 136, 136, 136, 137, 138, 128, 128, 129, 128, 128, 128, 129, 130, 132, 132, 133, 128, 128, 128, 129, 130, 128, 128, 129, 128, 128, 128, 129, 130, 132, 132, 133, 136, 136, 136, 137, 138, 144, 144, 145, 144, 144, 144, 145, 146, 148, 148, 149, 160, 160, 160, 161, 162, 160, 160, 161, 160, 160, 160, 161, 162, 164, 164, 165, 168, 168, 168, 169, 170, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 32, 32, 32, 33, 34, 32, 32, 33, 32, 32, 32, 33, 34, 36, 36, 37, 40, 40, 40, 41, 42, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 64, 64, 64, 65, 66, 64, 64, 65, 64, 64, 64, 65, 66, 68, 68, 69, 72, 72, 72, 73, 74, 80, 80, 81, 80, 80, 80, 81, 82, 84, 84, 85, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 32, 32, 32, 33, 34, 32, 32, 33, 32, 32, 32, 33, 34, 36, 36, 37, 40, 40, 40, 41, 42, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 16, 16, 17, 16, 16, 16, 17, 18, 20, 20, 21, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 8, 8, 8, 9, 10, 0, 0, 1, 0, 0, 0, 1, 2, 4, 4, 5, 0, 0, 0, 1, 2, 0, 0, 1, 0, 0, 0, };
2179
unsigned char NAF_nbits_tab[1024] = {0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 42, 41, 40, 40, 40, 37, 36, 36, 34, 33, 32, 32, 32, 33, 32, 32, 34, 33, 32, 32, 32, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 85, 84, 84, 82, 81, 80, 80, 80, 81, 80, 80, 74, 73, 72, 72, 72, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 66, 65, 64, 64, 64, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 42, 41, 40, 40, 40, 37, 36, 36, 34, 33, 32, 32, 32, 33, 32, 32, 34, 33, 32, 32, 32, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 170, 169, 168, 168, 168, 165, 164, 164, 162, 161, 160, 160, 160, 161, 160, 160, 162, 161, 160, 160, 160, 149, 148, 148, 146, 145, 144, 144, 144, 145, 144, 144, 138, 137, 136, 136, 136, 133, 132, 132, 130, 129, 128, 128, 128, 129, 128, 128, 130, 129, 128, 128, 128, 133, 132, 132, 130, 129, 128, 128, 128, 129, 128, 128, 138, 137, 136, 136, 136, 133, 132, 132, 130, 129, 128, 128, 128, 129, 128, 128, 130, 129, 128, 128, 128, 85, 84, 84, 82, 81, 80, 80, 80, 81, 80, 80, 74, 73, 72, 72, 72, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 66, 65, 64, 64, 64, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 42, 41, 40, 40, 40, 37, 36, 36, 34, 33, 32, 32, 32, 33, 32, 32, 34, 33, 32, 32, 32, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 42, 41, 40, 40, 40, 37, 36, 36, 34, 33, 32, 32, 32, 33, 32, 32, 34, 33, 32, 32, 32, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 85, 84, 84, 82, 81, 80, 80, 80, 81, 80, 80, 74, 73, 72, 72, 72, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 66, 65, 64, 64, 64, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 42, 41, 40, 40, 40, 37, 36, 36, 34, 33, 32, 32, 32, 33, 32, 32, 34, 33, 32, 32, 32, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 2, 1, 0, 0, 0, 5, 4, 4, 2, 1, 0, 0, 0, 1, 0, 0, 170, 169, 168, 168, 168, 165, 164, 164, 162, 161, 160, 160, 160, 161, 160, 160, 162, 161, 160, 160, 160, 149, 148, 148, 146, 145, 144, 144, 144, 145, 144, 144, 138, 137, 136, 136, 136, 133, 132, 132, 130, 129, 128, 128, 128, 129, 128, 128, 130, 129, 128, 128, 128, 133, 132, 132, 130, 129, 128, 128, 128, 129, 128, 128, 138, 137, 136, 136, 136, 133, 132, 132, 130, 129, 128, 128, 128, 129, 128, 128, 130, 129, 128, 128, 128, 85, 84, 84, 82, 81, 80, 80, 80, 81, 80, 80, 74, 73, 72, 72, 72, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 66, 65, 64, 64, 64, 69, 68, 68, 66, 65, 64, 64, 64, 65, 64, 64, 42, 41, 40, 40, 40, 37, 36, 36, 34, 33, 32, 32, 32, 33, 32, 32, 34, 33, 32, 32, 32, 21, 20, 20, 18, 17, 16, 16, 16, 17, 16, 16, 10, 9, 8, 8, 8, 5, 4, 4, 2, 1, 0, };
2180
unsigned char NAF_c_tab[1024] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, };
2181
2182
// n must be less than 2^63, takes about 14 nsecs for n~2^30 and about 32 nsecs for n~2^60 (AMD 2.5GHz Athlon64)
2183
void ui_NAF (unsigned long *pbits, unsigned long *nbits, unsigned long n)
2184
{
2185
register int c, m;
2186
2187
m=n&0x1FF;
2188
*pbits = NAF_pbits_tab[m];
2189
*nbits = NAF_nbits_tab[m];
2190
if ( n < 128 ) return;
2191
c = NAF_c_tab[m];
2192
n>>=8;
2193
m=n&0x1FF;
2194
*pbits |= (unsigned long)NAF_pbits_tab[m+(c<<9)] << 8;
2195
*nbits |= (unsigned long)NAF_nbits_tab[m+(c<<9)] << 8;
2196
if ( n < 128 ) return;
2197
c = NAF_c_tab[m+(c<<9)];
2198
n>>=8;
2199
m=n&0x1FF;
2200
*pbits |= (unsigned long)NAF_pbits_tab[m+(c<<9)] << 16;
2201
*nbits |= (unsigned long)NAF_nbits_tab[m+(c<<9)] << 16;
2202
if ( n < 128 ) return;
2203
c = NAF_c_tab[m+(c<<9)];
2204
n>>=8;
2205
m=n&0x1FF;
2206
*pbits |= (unsigned long)NAF_pbits_tab[m+(c<<9)] << 24;
2207
*nbits |= (unsigned long)NAF_nbits_tab[m+(c<<9)] << 24;
2208
if ( n < 128 ) return;
2209
c = NAF_c_tab[m+(c<<9)];
2210
n>>=8;
2211
m=n&0x1FF;
2212
*pbits |= (unsigned long)NAF_pbits_tab[m+(c<<9)] << 32;
2213
*nbits |= (unsigned long)NAF_nbits_tab[m+(c<<9)] << 32;
2214
if ( n < 128 ) return;
2215
c = NAF_c_tab[m+(c<<9)];
2216
n>>=8;
2217
m=n&0x1FF;
2218
*pbits |= (unsigned long)NAF_pbits_tab[m+(c<<9)] << 40;
2219
*nbits |= (unsigned long)NAF_nbits_tab[m+(c<<9)] << 40;
2220
if ( n < 128 ) return;
2221
c = NAF_c_tab[m+(c<<9)];
2222
n>>=8;
2223
m=n&0x1FF;
2224
*pbits |= (unsigned long)NAF_pbits_tab[m+(c<<9)] << 48;
2225
*nbits |= (unsigned long)NAF_nbits_tab[m+(c<<9)] << 48;
2226
if ( n < 128 ) return;
2227
c = NAF_c_tab[m+(c<<9)];
2228
n>>=8;
2229
m=n&0x1FF;
2230
*pbits |= (unsigned long)NAF_pbits_tab[m+(c<<9)] << 56;
2231
*nbits |= (unsigned long)NAF_nbits_tab[m+(c<<9)] << 56;
2232
return;
2233
}
2234
2235
2236
2237