Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Testing latest pari + WASM + node.js... and it works?! Wow.

28485 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2017 The PARI group.
2
3
This file is part of the PARI/GP package.
4
5
PARI/GP is free software; you can redistribute it and/or modify it under the
6
terms of the GNU General Public License as published by the Free Software
7
Foundation; either version 2 of the License, or (at your option) any later
8
version. It is distributed in the hope that it will be useful, but WITHOUT
9
ANY WARRANTY WHATSOEVER.
10
11
Check the License for details. You should have received a copy of it, along
12
with the package; see the file 'COPYING'. If not, write to the Free Software
13
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14
15
/* This file is based on ratpoints-2.1.3 by Michael Stoll, see
16
* http://www.mathe2.uni-bayreuth.de/stoll/programs/
17
* Original copyright / license: */
18
/***********************************************************************
19
* ratpoints-2.1.3 *
20
* Copyright (C) 2008, 2009 Michael Stoll *
21
* - A program to find rational points on hyperelliptic curves *
22
* *
23
* This program is free software: you can redistribute it and/or *
24
* modify it under the terms of the GNU General Public License *
25
* as published by the Free Software Foundation, either version 2 of *
26
* the License, or (at your option) any later version. *
27
***********************************************************************/
28
29
#include "pari.h"
30
#include "paripriv.h"
31
32
#define pel(a,b) gel((a),(b)+2)
33
34
#define RATPOINTS_ARRAY_SIZE 256 /* Array size in longs */
35
#define RATPOINTS_DEFAULT_SP1 9 /* Default value for sp1 */
36
#define RATPOINTS_DEFAULT_SP2 16 /* Default value for sp2 */
37
#define RATPOINTS_DEFAULT_NUM_PRIMES 28 /* Default value for num_primes */
38
#define RATPOINTS_DEFAULT_BIT_PRIMES 7 /* Default value for bit_primes */
39
#define RATPOINTS_DEFAULT_MAX_FORBIDDEN 30 /* Default value for max_forbidden */
40
41
typedef struct {double low; double up;} ratpoints_interval;
42
43
/* Define the flag bits for the flags component: */
44
#define RATPOINTS_NO_REVERSE 0x0004UL
45
46
#define RATPOINTS_FLAGS_INPUT_MASK (RATPOINTS_NO_REVERSE)
47
48
/* Flags bits for internal purposes */
49
#define RATPOINTS_REVERSED 0x0100UL
50
#define RATPOINTS_CHECK_DENOM 0x0200UL
51
#define RATPOINTS_USE_SQUARES 0x0400UL
52
#define RATPOINTS_USE_SQUARES1 0x0800UL
53
54
#define LONG_MASK (~(-(1UL<<TWOPOTBITS_IN_LONG)))
55
56
#define CEIL(a,b) (((a) <= 0) ? -(-(a) / (b)) : 1 + ((a)-1) / (b))
57
58
/* Some Macros for working with SSE registers */
59
#ifdef HAS_SSE2
60
#include <emmintrin.h>
61
62
#define AND(a,b) ((ratpoints_bit_array)__builtin_ia32_andps((__v4sf)(a), (__v4sf)(b)))
63
#define EXT0(a) ((ulong)__builtin_ia32_vec_ext_v2di((__v2di)(a), 0))
64
#define EXT1(a) ((ulong)__builtin_ia32_vec_ext_v2di((__v2di)(a), 1))
65
#define TEST(a) (EXT0(a) || EXT1(a))
66
#define RBA(a) ((__v2di){((long) a), ((long) a)})
67
68
/* Use SSE 128 bit registers for the bit arrays */
69
typedef __v2di ratpoints_bit_array;
70
71
#define RBA_LENGTH (128)
72
#define RBA_SHIFT (7)
73
#define RBA_ALIGN (sizeof(ratpoints_bit_array))
74
#define RBA_MASK (~(-(1UL<<RBA_SHIFT)))
75
76
#else
77
/* Use ulong for the bit arrays */
78
typedef ulong ratpoints_bit_array;
79
#define AND(a,b) ((a)&(b))
80
#define EXT0(a) (a)
81
#define TEST(a) (a)
82
#define RBA(a) (a)
83
84
#define RBA_LENGTH BITS_IN_LONG
85
#define RBA_SHIFT TWOPOTBITS_IN_LONG
86
#define RBA_ALIGN (sizeof(long))
87
#define RBA_MASK LONG_MASK
88
89
#endif
90
91
typedef struct { long p; long offset; ratpoints_bit_array *ptr; } sieve_spec;
92
93
typedef enum { num_all, num_even, num_odd, num_none } bit_selection;
94
95
typedef struct {
96
long p; int *is_f_square;
97
const long *inverses;
98
long offset; ratpoints_bit_array** sieve;
99
} ratpoints_sieve_entry;
100
101
typedef struct { long p;
102
ulong *start;
103
ulong *end;
104
ulong *curr; }
105
forbidden_entry;
106
107
typedef struct {
108
GEN cof, listprime;
109
ratpoints_interval *domain;
110
long height, b_low, b_high, sp1, sp2, array_size;
111
long num_inter, num_primes, bit_primes, max_forbidden;
112
ulong flags;
113
/* from here: private data */
114
GEN bc;
115
ratpoints_sieve_entry *se_buffer;
116
ratpoints_sieve_entry *se_next;
117
ratpoints_bit_array *ba_buffer;
118
ratpoints_bit_array *ba_next;
119
int *int_buffer, *int_next;
120
forbidden_entry *forb_ba;
121
long *forbidden;
122
GEN inverses, offsets, den_info, divisors;
123
ulong **sieves0;
124
} ratpoints_args;
125
126
#ifdef HAS_SSE2
127
#define CODE_INIT_SIEVE_COPY for (a = 0; a < p; a++) si[a+p] = si[a];
128
#else
129
#define CODE_INIT_SIEVE_COPY
130
#endif
131
132
static ratpoints_bit_array *
133
#if defined(__GNUC__)
134
__attribute__((noinline))
135
#endif
136
sieve_init1(long p, ratpoints_sieve_entry *se1, long b1, ratpoints_args *args1)
137
{
138
ratpoints_sieve_entry *se = se1;
139
ratpoints_args *args = args1;
140
register int *isfs = se->is_f_square;
141
register long b = b1;
142
long lmp = BITS_IN_LONG % p;
143
long ldp = BITS_IN_LONG / p;
144
long p1 = (ldp + 1) * p;
145
long diff_shift = p1 & LONG_MASK;
146
long diff = BITS_IN_LONG - diff_shift;
147
register ulong help0;
148
register long a;
149
register long d = se->inverses[b];
150
register long ab = 0; /* a/b mod p */
151
register ulong test = 1UL;
152
register ulong he0 = 0UL;
153
for (a = 0; a < p; a++)
154
{
155
if (isfs[ab]) he0 |= test;
156
ab += d;
157
if (ab >= p) ab -= p;
158
test <<= 1;
159
}
160
help0 = he0;
161
{
162
register ulong help1;
163
/* repeat bit pattern floor(BITS_IN_LONG/p) times */
164
register ulong pattern = help0;
165
register long i;
166
/* the p * (floor(BITS_IN_LONG/p) + 1) - BITS_IN_LONG
167
= p - (BITS_IN_LONG mod p)
168
upper bits into help[b][1] :
169
shift away the BITS_IN_LONG mod p lower bits */
170
help1 = pattern >> lmp;
171
for (i = p; i < BITS_IN_LONG; i <<= 1)
172
help0 |= help0 << i;
173
{ /* fill the bit pattern from help0/help1 into sieve[b][].
174
sieve[b][a0] has the same semantics as help0/help1,
175
but here, a0 runs from 0 to p-1 and all bits are filled. */
176
register long a;
177
ulong *si = (ulong *)args->ba_next;
178
179
args->ba_next += p;
180
/* copy the first chunk into sieve[b][] */
181
si[0] = help0;
182
/* now keep repeating the bit pattern,
183
rotating it in help0/help1 */
184
for (a = 1 ; a < p; a++)
185
{
186
register ulong temp = help0 >> diff;
187
help0 = help1 | (help0 << diff_shift);
188
si[a] = help0;
189
help1 = temp;
190
}
191
CODE_INIT_SIEVE_COPY
192
/* set sieve array */
193
se->sieve[b] = (ratpoints_bit_array *)si;
194
return (ratpoints_bit_array *)si;
195
}
196
}
197
}
198
199
/* This is for p > BITS_IN_LONG */
200
static ratpoints_bit_array *
201
#if defined(__GNUC__)
202
__attribute__((noinline))
203
#endif
204
sieve_init2(long p, ratpoints_sieve_entry *se1, long b1, ratpoints_args *args1)
205
{
206
ratpoints_sieve_entry *se = se1;
207
ratpoints_args *args = args1;
208
register int *isfs = se->is_f_square;
209
register long b = b1;
210
/* long ldp = 0; = BITS_IN_LONG / p */
211
/* long p1 = p; = (ldp + 1) * p; */
212
long wp = p >> TWOPOTBITS_IN_LONG;
213
long diff_shift = p & LONG_MASK;
214
long diff = BITS_IN_LONG - diff_shift;
215
ulong help[(p>>TWOPOTBITS_IN_LONG) + 2];
216
217
/* initialize help */
218
{
219
register ulong *he = &help[0];
220
register ulong *he1 = &he[(p>>TWOPOTBITS_IN_LONG) + 2];
221
while (he1 != he) { he1--; *he1 = 0UL; }
222
}
223
{ register ulong work = 0UL;
224
register long a;
225
register long ab = 0; /* a/b mod p */
226
register long d = se->inverses[b];
227
register long n = 0;
228
register ulong test = 1UL;
229
for (a = 0; a < p; )
230
{
231
if (isfs[ab]) work |= test;
232
ab += d;
233
if (ab >= p) ab -= p;
234
test <<= 1;
235
a++;
236
if ((a & LONG_MASK) == 0)
237
{ help[n] = work; n++; work = 0UL; test = 1UL; }
238
}
239
help[n] = work;
240
}
241
242
{ /* fill the bit pattern from help[] into sieve[b][].
243
sieve[b][a0] has the same semantics as help[b][a0],
244
but here, a0 runs from 0 to p-1 and all bits are filled. */
245
register ulong *si = (ulong *)args->ba_next;
246
register long a1;
247
register long a;
248
249
args->ba_next += p;
250
/* copy the first chunk from help[] into sieve[num][b][] */
251
for (a = 0; a < wp; a++) si[a] = help[a];
252
/* now keep repeating the bit pattern, rotating it in help */
253
for (a1 = a ; a < p; a++)
254
{
255
register long t = (a1 == wp) ? 0 : a1+1;
256
help[a1] |= help[t]<<diff_shift;
257
si[a] = help[a1];
258
a1 = t;
259
help[a1] >>= diff;
260
}
261
CODE_INIT_SIEVE_COPY
262
/* set sieve array */
263
se->sieve[b] = (ratpoints_bit_array *)si;
264
return (ratpoints_bit_array *)si;
265
}
266
}
267
268
static GEN
269
gen_squares(GEN listprime)
270
{
271
long nbprime = lg(listprime)-1;
272
GEN sq = cgetg(nbprime+1, t_VEC);
273
long n;
274
for (n = 1; n <= nbprime; n++)
275
{
276
ulong i, p = uel(listprime,n);
277
GEN w = zero_zv(p), work = w+1;
278
work[0] = 1;
279
/* record nonzero squares mod p, p odd */
280
for (i = 1; i < p; i += 2) work[(i*i) % p] = 1;
281
gel(sq, n) = w;
282
}
283
return sq;
284
}
285
286
static GEN
287
gen_offsets(GEN P)
288
{
289
long n, l = lg(P);
290
GEN of = cgetg(l, t_VEC);
291
for (n = 1; n < l; n++)
292
{
293
ulong p = uel(P,n);
294
uel(of, n) = Fl_inv((2*RBA_LENGTH)%p, p);
295
}
296
return of;
297
}
298
299
static GEN
300
gen_inverses(GEN P)
301
{
302
long n, l = lg(P);
303
GEN iv = cgetg(l, t_VEC);
304
for (n = 1; n < l; n++)
305
{
306
ulong i, p = uel(P,n);
307
GEN w = cgetg(p, t_VECSMALL);
308
for (i = 1; i < p; i++) uel(w, i) = Fl_inv(i, p);
309
gel(iv, n) = w;
310
}
311
return iv;
312
}
313
314
static ulong **
315
gen_sieves0(GEN listprime)
316
{
317
long n;
318
long nbprime = lg(listprime)-1;
319
ulong ** si = (ulong**) new_chunk(nbprime+1);
320
for (n = 1; n <= nbprime; n++)
321
{
322
ulong i, p = uel(listprime,n);
323
ulong *w = (ulong *) stack_malloc_align(2*p*sizeof(ulong), RBA_ALIGN);
324
for (i = 0; i < p; i++) uel(w,i) = ~0UL;
325
for (i = 0; i < BITS_IN_LONG; i++)
326
uel(w,(p*i)>>TWOPOTBITS_IN_LONG) &= ~(1UL<<((p*i) & LONG_MASK));
327
for (i = 0; i < p; i++) uel(w,i+p) = uel(w,i);
328
si[n] = w;
329
}
330
return si;
331
}
332
333
static void
334
gen_sieve(ratpoints_args *args)
335
{
336
GEN listprimes = args->listprime;
337
args->offsets = gen_offsets(listprimes);
338
args->inverses = gen_inverses(listprimes);
339
args->sieves0 = gen_sieves0(listprimes);
340
}
341
342
static GEN
343
ZX_positive_region(GEN P, long h, long bitprec)
344
{
345
long prec = nbits2prec(bitprec);
346
GEN it = mkvec2(stoi(-h),stoi(h));
347
GEN R = ZX_Uspensky(P, it, 1, bitprec);
348
long nR = lg(R)-1;
349
long s = signe(ZX_Z_eval(P,gel(it,1)));
350
long i=1, j;
351
GEN iv, st, en;
352
if (s<0 && nR==0) return NULL;
353
iv = cgetg(((nR+1+(s>=0))>>1)+1, t_VEC);
354
if (s>=0) st = itor(gel(it,1),prec);
355
else { st = gel(R,i); i++; }
356
for (j=1; i<nR; j++)
357
{
358
gel(iv, j) = mkvec2(st, gel(R,i));
359
st = gel(R,i+1);
360
i+=2;
361
}
362
if (i==nR) en = gel(R,i); else en = itor(gel(it,2),prec);
363
gel(iv,j) = mkvec2(st, en);
364
return iv;
365
}
366
367
static long
368
posint(ratpoints_interval *ivlist, GEN P, long h)
369
{
370
GEN R = ZX_positive_region(P, h, 53);
371
const double eps = 1e-5;
372
long nR, i;
373
374
if (!R) return 0;
375
nR = lg(R)-1;
376
i = 1;
377
for (i=1; i<=nR; i++)
378
{
379
ivlist[i-1].low = rtodbl(gmael(R,i,1))-eps;
380
ivlist[i-1].up = rtodbl(gmael(R,i,2))+eps;
381
}
382
return nR;
383
}
384
385
static long
386
ratpoints_compute_sturm(ratpoints_args *args)
387
{
388
ratpoints_interval *ivlist = args->domain;
389
args->num_inter = posint(ivlist, args->cof, (long) ivlist[0].up);
390
return args->num_inter;
391
}
392
393
/**************************************************************************
394
* Try to avoid divisions *
395
**************************************************************************/
396
INLINE long
397
mod(long a, long b)
398
{
399
long b1 = b << 4; /* b1 = 16*b */
400
401
if (a < -b1) { a %= b; if (a < 0) { a += b; } return a ; }
402
if (a < 0) { a += b1; }
403
else { if (a >= b1) { return a % b; } }
404
b1 >>= 1; /* b1 = 8*b */
405
if (a >= b1) { a -= b1; }
406
b1 >>= 1; /* b1 = 4*b */
407
if (a >= b1) { a -= b1; }
408
b1 >>= 1; /* b1 = 2*b */
409
if (a >= b1) { a -= b1; }
410
if (a >= b) { a -= b; }
411
return a;
412
}
413
414
static void
415
set_bc(long b, ratpoints_args *args)
416
{
417
GEN w0 = gen_1;
418
GEN c = args->cof, bc;
419
long k, degree = degpol(c);
420
bc = cgetg(degree+2, t_POL);
421
for (k = degree-1; k >= 0; k--)
422
{
423
w0 = muliu(w0, b);
424
gel(bc,k+2) = mulii(gel(c,k+2), w0);
425
}
426
args->bc = bc;
427
}
428
429
/**************************************************************************
430
* Check a `survivor' of the sieve if it really gives a point. *
431
**************************************************************************/
432
433
static long
434
_ratpoints_check_point(long a, long b, ratpoints_args *args, int *quit,
435
int process(long, long, GEN, void*, int*), void *info)
436
{
437
pari_sp av = avma;
438
GEN w0, w2, c = args->cof, bc = args->bc;
439
long k, degree = degpol(c);
440
int reverse = args->flags & RATPOINTS_REVERSED;
441
442
/* Compute F(a, b), where F is the homogenized version of f
443
of smallest possible even degree */
444
w2 = gel(c, degree+2);
445
for (k = degree-1; k >= 0; k--)
446
{
447
w2 = mulis(w2, a);
448
w2 = addii(w2, gel(bc,k+2));
449
}
450
if (odd(degree)) w2 = muliu(w2, b);
451
/* check if f(x,z) is a square; if so, process the point(s) */
452
if (signe(w2) >= 0 && Z_issquareall(w2, &w0))
453
{
454
if (reverse)
455
{
456
if (a >= 0) (void)process(b, a, w0, info, quit);
457
else (void)process(-b, -a, w0, info, quit);
458
}
459
else (void)process(a, b, w0, info, quit);
460
if (!*quit && signe(w0) != 0)
461
{
462
GEN nw0 = negi(w0);
463
if (reverse)
464
{
465
if (a >= 0) (void)process(b, a, nw0, info, quit);
466
else (void)process(-b, -a, nw0, info, quit);
467
}
468
else (void)process(a, b, nw0, info, quit);
469
}
470
return 1;
471
}
472
set_avma(av);
473
return 0;
474
}
475
476
/**************************************************************************
477
* The inner loop of the sieving procedure *
478
**************************************************************************/
479
static long
480
_ratpoints_sift0(long b, long w_low, long w_high,
481
ratpoints_args *args, bit_selection which_bits,
482
ratpoints_bit_array *survivors, sieve_spec *sieves, int *quit,
483
int process(long, long, GEN, void*, int*), void *info)
484
{
485
long range = w_high - w_low;
486
long sp1 = args->sp1;
487
long sp2 = args->sp2;
488
long i, n, nb = 0, absb = labs(b);
489
ratpoints_bit_array *surv0;
490
491
/* now do the sieving (fast!) */
492
for (n = 0; n < sp1; n++)
493
{
494
ratpoints_bit_array *sieve_n = sieves[n].ptr;
495
register long p = sieves[n].p;
496
long r = mod(-w_low-sieves[n].offset, p);
497
register ratpoints_bit_array *surv = survivors;
498
499
if (w_high < w_low + r)
500
{ /* if we get here, r > 0, since w_high >= w_low always */
501
register ratpoints_bit_array *siv1 = &sieve_n[p-r];
502
register ratpoints_bit_array *siv0 = siv1 + range;
503
504
while (siv1 != siv0) { *surv = AND(*surv, *siv1++); surv++; }
505
}
506
else
507
{
508
register ratpoints_bit_array *siv1 = &sieve_n[p-r];
509
register ratpoints_bit_array *surv_end = &survivors[range - p];
510
register long i;
511
for (i = r; i; i--) { *surv = AND(*surv, *siv1++); surv++; }
512
siv1 -= p;
513
while (surv <= surv_end)
514
{
515
for (i = p; i; i--) { *surv = AND(*surv, *siv1++); surv++; }
516
siv1 -= p;
517
}
518
surv_end += p;
519
while (surv < surv_end) { *surv = AND(*surv, *siv1++); surv++; }
520
}
521
} /* for n */
522
/* 2nd phase of the sieve: test each surviving bit array with more primes */
523
surv0 = &survivors[0];
524
for (i = w_low; i < w_high; i++)
525
{
526
register ratpoints_bit_array nums = *surv0++;
527
sieve_spec *ssp = &sieves[sp1];
528
register long n;
529
530
for (n = sp2-sp1; n && TEST(nums); n--)
531
{
532
register long p = ssp->p;
533
nums = AND(nums, ssp->ptr[mod(i + ssp->offset, p)]);
534
ssp++;
535
}
536
537
/* Check the survivors of the sieve if they really give points */
538
if (TEST(nums))
539
{
540
long a0, a, d;
541
#ifdef HAS_SSE2
542
long da = (which_bits == num_all) ? RBA_LENGTH/2 : RBA_LENGTH;
543
#endif
544
/* a will be the numerator corresponding to the selected bit */
545
if (which_bits == num_all)
546
{
547
d = 1; a0 = i * RBA_LENGTH;
548
}
549
else
550
{
551
d = 2; a0 = i * 2 * RBA_LENGTH;
552
if (which_bits == num_odd) a0++;
553
}
554
{
555
#ifdef HAS_SSE2
556
ulong nums0 = EXT0(nums);
557
ulong nums1 = EXT1(nums);
558
#else
559
ulong nums0 = nums;
560
#endif
561
562
for (a = a0; nums0; a += d, nums0 >>= 1)
563
{ /* test one bit */
564
if (odd(nums0) && ugcd(labs(a), absb)==1)
565
{
566
if (!args->bc) set_bc(b, args);
567
nb += _ratpoints_check_point(a, b, args, quit, process, info);
568
if (*quit) return nb;
569
}
570
}
571
#ifdef HAS_SSE2
572
for (a = a0 + da; nums1; a += d, nums1 >>= 1)
573
{ /* test one bit */
574
if (odd(nums1) && ugcd(labs(a), absb)==1)
575
{
576
if (!args->bc) set_bc(b, args);
577
nb += _ratpoints_check_point(a, b, args, quit, process, info);
578
if (*quit) return nb;
579
}
580
}
581
#endif
582
}
583
}
584
}
585
return nb;
586
}
587
588
#define MAX_DIVISORS 512
589
/* Maximal length of array for squarefree divisors of leading coefficient */
590
591
typedef struct { double r; ratpoints_sieve_entry *ssp; } entry;
592
593
static const int squares16[16] = {1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0};
594
/* Says if a is a square mod 16, for a = 0..15 */
595
596
/**************************************************************************
597
* Initialization and cleanup of ratpoints_args structure *
598
**************************************************************************/
599
600
static ratpoints_sieve_entry*
601
alloc_sieve(long nbprime, long maxprime)
602
{
603
long i;
604
ratpoints_sieve_entry * s = (ratpoints_sieve_entry*)
605
stack_malloc(nbprime*sizeof(ratpoints_sieve_entry));
606
for (i=0; i<nbprime; i++)
607
s[i].sieve = (ratpoints_bit_array**) new_chunk(maxprime);
608
return s;
609
}
610
611
/* NOTE: args->degree must be set */
612
static void
613
find_points_init(ratpoints_args *args, long bit_primes)
614
{
615
long need = 0;
616
long n, nbprime,maxprime;
617
args->listprime = primes_interval_zv(3, 1<<bit_primes);
618
nbprime = lg(args->listprime)-1;
619
maxprime = args->listprime[nbprime];
620
621
/* allocate space for se_buffer */
622
args->se_buffer = alloc_sieve(nbprime, maxprime);
623
args->se_next = args->se_buffer;
624
for (n = 1; n <= nbprime; n++)
625
{
626
ulong p = args->listprime[n];
627
need += p*p;
628
}
629
args->ba_buffer = (ratpoints_bit_array*)
630
stack_malloc_align(need*sizeof(ratpoints_bit_array),RBA_ALIGN);
631
args->ba_next = args->ba_buffer;
632
633
/* allocate space for int_buffer */
634
args->int_buffer = (int *) stack_malloc(nbprime*(maxprime+1)*sizeof(int));
635
args->int_next = args->int_buffer;
636
637
args->forb_ba = (forbidden_entry*)
638
stack_malloc((nbprime + 1)*sizeof(forbidden_entry));
639
args->forbidden = new_chunk(nbprime + 1);
640
gen_sieve(args);
641
return;
642
}
643
644
/* f = leading coeff; b = b1*b2, b1 maximal with (b1, 2*f) = 1;
645
* return Jacobi symbol (f, b1) */
646
INLINE int
647
rpjacobi(long b, GEN lcf)
648
{
649
ulong f;
650
b >>= vals(b);
651
f = umodiu(lcf, b);
652
return krouu(f, u_ppo(b,f));
653
}
654
655
/************************************************************************
656
* Set up information on possible denominators *
657
* when polynomial is of odd degree with leading coefficient != +-1 *
658
************************************************************************/
659
660
static void
661
setup_us1(ratpoints_args *args, GEN w0)
662
{
663
GEN F = Z_issmooth_fact(w0, 1000), P, E, S, D;
664
long i, l;
665
666
if (!F) return;
667
P = gel(F,1); l = lg(P);
668
E = gel(F,2);
669
D = cgetg(1+(1<<(l-1)), t_VECSMALL);
670
/* factorization is complete, set up array of squarefree divisors */
671
D[1] = 1;
672
for (i = 1; i < l; i++)
673
{ /* multiply all divisors known so far by next prime */
674
long k, n = 1<<(i-1);
675
for (k=0; k<n; k++) uel(D,1+n+k) = uel(D,1+k) * P[i];
676
}
677
S = cgetg(l, t_VECSMALL);
678
/* set slopes in den_info */
679
for (i = 1; i < l; i++)
680
{ /* compute min{n : (d-k)*n > v_p(f_d) - v_p(f_k), k = 0,...,d-1} */
681
GEN c = args->cof;
682
long p = P[i], v = E[i];
683
long k, n = 1, d = degpol(c);
684
685
for (k = d - 1; k >= 0; k--)
686
{
687
long t = 1 + v - Z_lval(gel(c,k+2), p);
688
long m = CEIL(t, d - k);
689
690
if (m > n) n = m;
691
}
692
S[i] = n;
693
}
694
args->divisors = D;
695
args->flags |= RATPOINTS_USE_SQUARES1;
696
args->den_info = mkvec3(P, E, S);
697
}
698
699
/************************************************************************
700
* Consider 2-adic information *
701
************************************************************************/
702
703
static bit_selection
704
get_2adic_info(ratpoints_args *args, ulong *den_bits,
705
ratpoints_bit_array *num_bits)
706
{
707
GEN c = args->cof;
708
long degree = degpol(c);
709
int is_f_square16[24];
710
long *cmp = new_chunk(degree+1);
711
long npe = 0, npo = 0;
712
bit_selection result;
713
long n, a, b;
714
715
/* compute coefficients mod 16 */
716
for (n = 0; n <= degree; n++) cmp[n] = Mod16(gel(c,n+2));
717
for (a = 0 ; a < 16; a++)
718
{
719
ulong s = cmp[degree];
720
long n;
721
for (n = degree - 1 ; n >= 0 ; n--) s = s*a + cmp[n];
722
s &= 0xf;
723
if ((is_f_square16[a] = squares16[s])) { if (odd(a)) npo++; else npe++; }
724
}
725
726
/* even denominators:
727
is_f_square16[16+k] says if f((2k+1)/2) is a square, k = 0..3
728
is_f_square16[20+k] says if f((2k+1)/4) is a square, k = 0,1
729
is_f_square16[22] says if f(odd/8) is a square
730
is_f_square16[23] says if f(odd/2^n), n >= 4, can be a square */
731
{
732
long np1 = 0, np2 = 0, np3 = 0, np4 = 0;
733
734
if (odd(degree))
735
{
736
long a, cf = 4*cmp[degree-1];
737
738
if (degree >= 2) cf += 8*cmp[degree-2];
739
for (a = 0; a < 4; a++)
740
{ /* Compute 2 c[d] k^d + 4 c[d-1] k^(d-1) + 8 c[d-2] k^(d-2), k = 2a+1.
741
Note that k^d = k mod 8, k^(d-1) = 1 mod 8. */
742
long k = 2*a+1;
743
long s = (2*k*cmp[degree] + cf) & 0xf;
744
if ((is_f_square16[16+a] = squares16[s])) np1++;
745
}
746
if ((is_f_square16[20] = squares16[(4*cmp[degree]) & 0xf])) np2++;
747
if ((is_f_square16[21] = squares16[(12*cmp[degree]) & 0xf])) np2++;
748
if ((is_f_square16[22] = squares16[(8*cmp[degree]) & 0xf])) np3++;
749
is_f_square16[23] = 1; np4++;
750
}
751
else
752
{
753
long a, cf = (degree >= 2) ? 4*cmp[degree-2] : 0;
754
755
if (degree >= 3) cf += 8*cmp[degree-3];
756
for (a = 0; a < 4; a++)
757
{ /* compute c[d] k^d + 2 c[d-1] k^(d-1) + ... + 8 c[d-3] k^(d-3),
758
k = 2a+1. Note that k^d = k^2 mod 16, k^(d-1) = k mod 8. */
759
long k = 2*a+1;
760
long s = ((cmp[degree]*k + 2*cmp[degree-1])*k + cf) & 0xf;
761
if ((is_f_square16[16+a] = squares16[s])) np1++;
762
}
763
if ((is_f_square16[20] = squares16[(cmp[degree]+4*cmp[degree-1]) & 0xf]))
764
np2++;
765
if ((is_f_square16[21] = squares16[(cmp[degree]+12*cmp[degree-1]) & 0xf]))
766
np2++;
767
if ((is_f_square16[22] = squares16[(cmp[degree]+8*cmp[degree-1]) & 0xf]))
768
np3++;
769
if ((is_f_square16[23] = squares16[cmp[degree]])) np4++;
770
}
771
772
/* set den_bits */
773
{ ulong db = 0;
774
long i;
775
776
if (npe + npo > 0) db |= 0xaaaaUL; /* odd denominators */
777
if (np1 > 0) db |= 0x4444UL; /* v_2(den) = 1 */
778
if (np2 > 0) db |= 0x1010UL; /* v_2(den) = 2 */
779
if (np3 > 0) db |= 0x0100UL; /* v_2(den) = 3 */
780
if (np4 > 0) db |= 0x0001UL; /* v_2(den) >= 4 */
781
if (db == 0) { *den_bits = 0UL; return num_none; }
782
783
for (i = 16; i < BITS_IN_LONG; i <<= 1) db |= db << i;
784
*den_bits = db;
785
}
786
result = (npe == 0) ? (npo == 0) ? num_none : num_odd
787
: (npo == 0) ? num_even : num_all;
788
}
789
790
/* set up num_bits[16] */
791
792
/* odd denominators */
793
switch(result)
794
{
795
case num_all:
796
for (b = 1; b < 16; b += 2)
797
{
798
ulong work = 0, bit = 1;
799
long i, invb = b; /* inverse of b mod 16 */
800
if (b & 2) invb ^= 8;
801
if (b & 4) invb ^= 8;
802
for (i = 0; i < 16; i++)
803
{
804
if (is_f_square16[(invb*i) & 0xf]) work |= bit;
805
bit <<= 1;
806
}
807
/* now repeat the 16 bits */
808
for (i = 16; i < BITS_IN_LONG; i <<= 1) work |= work << i;
809
num_bits[b] = RBA(work);
810
}
811
break;
812
813
case num_odd:
814
for (b = 1; b < 16; b += 2)
815
{
816
ulong work = 0, bit = 1;
817
long i, invb = b; /* inverse of b mod 16 */
818
if (b & 2) invb ^= 8;
819
if (b & 4) invb ^= 8;
820
for (i = 1; i < 16; i += 2)
821
{
822
if (is_f_square16[(invb*i) & 0xf]) work |= bit;
823
bit <<= 1;
824
}
825
/* now repeat the 8 bits */
826
for (i = 8; i < BITS_IN_LONG; i <<= 1) { work |= work << i; }
827
num_bits[b] = RBA(work);
828
}
829
break;
830
831
case num_even:
832
for (b = 1; b < 16; b += 2)
833
{
834
ulong work = 0, bit = 1;
835
long i, invb = b; /* inverse of b mod 16 */
836
if (b & 2) invb ^= 8;
837
if (b & 4) invb ^= 8;
838
for (i = 0; i < 16; i += 2)
839
{
840
if (is_f_square16[(invb*i) & 0xf]) work |= bit;
841
bit <<= 1;
842
}
843
/* now repeat the 8 bits */
844
for (i = 8; i < BITS_IN_LONG; i <<= 1) work |= work << i;
845
num_bits[b] = RBA(work);
846
}
847
break;
848
849
case num_none:
850
for (b = 1; b < 16; b += 2) num_bits[b] = RBA(0UL);
851
break;
852
}
853
854
/* v_2(den) = 1 : only odd numerators */
855
for (b = 1; b < 8; b += 2)
856
{
857
ulong work = 0, bit = 1;
858
long i;
859
for (i = 1; i < 16; i += 2)
860
{
861
if (is_f_square16[16 + (((b*i)>>1) & 0x3)]) work |= bit;
862
bit <<= 1;
863
}
864
/* now repeat the 8 bits */
865
for (i = 8; i < BITS_IN_LONG; i <<= 1) work |= work << i;
866
num_bits[2*b] = RBA(work);
867
}
868
869
/* v_2(den) = 2 : only odd numerators */
870
for (b = 1; b < 4; b += 2)
871
{
872
ulong work = 0, bit = 1;
873
long i;
874
for (i = 1; i < 8; i += 2)
875
{
876
if (is_f_square16[20 + (((b*i)>>1) & 0x1)]) work |= bit;
877
bit <<= 1;
878
}
879
/* now repeat the 4 bits */
880
for (i = 4; i < BITS_IN_LONG; i <<= 1) work |= work << i;
881
num_bits[4*b] = RBA(work);
882
}
883
884
/* v_2(den) = 3, >= 4 : only odd numerators */
885
num_bits[8] = (is_f_square16[22]) ? RBA(~(0UL)) : RBA(0UL);
886
num_bits[0] = (is_f_square16[23]) ? RBA(~(0UL)) : RBA(0UL);
887
888
return result;
889
}
890
891
/**************************************************************************
892
* This is a comparison function needed for sorting in order to determine *
893
* the `best' primes for sieving. *
894
**************************************************************************/
895
896
static int
897
compare_entries(const void *a, const void *b)
898
{
899
double diff = ((entry *)a)->r - ((entry *)b)->r;
900
return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
901
}
902
903
/************************************************************************
904
* Collect the sieving information *
905
************************************************************************/
906
907
static long
908
sieving_info(ratpoints_args *args,
909
ratpoints_sieve_entry **sieve_list)
910
{
911
GEN c = args->cof;
912
GEN inverses = args->inverses, squares;
913
GEN offsets = args->offsets;
914
ulong ** sieves0 = args->sieves0;
915
long degree = degpol(c);
916
long fba = 0, fdc = 0;
917
long pn, pnp = 0;
918
long n;
919
long nbprime = lg(args->listprime)-1;
920
entry *prec = (entry*) stack_malloc(nbprime*sizeof(entry));
921
/* This array is used for sorting in order to
922
determine the `best' sieving primes. */
923
924
forbidden_entry *forb_ba = args->forb_ba;
925
long *forbidden = args->forbidden;
926
ulong bound = (1UL)<<(BITS_IN_LONG - args->bit_primes);
927
pari_sp av = avma;
928
squares = gen_squares(args->listprime);
929
930
/* initialize sieve in se_buffer */
931
for (pn = 1; pn <= args->num_primes; pn++)
932
{
933
long coeffs_mod_p[degree+1]; /* The coefficients of f reduced modulo p */
934
ulong a, p = args->listprime[pn], np;
935
long n;
936
int *is_f_square = args->int_next;
937
938
args->int_next += p + 1; /* need space for (p+1) int's */
939
940
/* compute coefficients mod p */
941
for (n = 0; n <= degree; n++) coeffs_mod_p[n] = umodiu(pel(c,n), p);
942
943
np = umael(squares,pn,coeffs_mod_p[0]+1);
944
is_f_square[0] = np;
945
for (a = 1 ; a < p; a++)
946
{
947
ulong s = coeffs_mod_p[degree];
948
if ((degree+1)*args->bit_primes <= BITS_IN_LONG)
949
{
950
for (n = degree - 1 ; n >= 0 ; n--) s = s*a + coeffs_mod_p[n];
951
/* here, s < p^(degree+1) <= max. long */
952
s %= p;
953
}
954
else
955
{
956
for (n = degree - 1 ; n >= 0 ; n--)
957
{
958
s = s*a + coeffs_mod_p[n];
959
if (s+1 >= bound) s %= p;
960
}
961
s %= p;
962
}
963
if ((is_f_square[a] = mael(squares,pn,s+1))) np++;
964
}
965
is_f_square[p] = odd(degree) || mael(squares,pn,coeffs_mod_p[degree]+1);
966
967
/* check if there are no solutions mod p */
968
if (np == 0 && !is_f_square[p]) return gc_long(av,p);
969
970
/* Fill arrays with info for p */
971
if (np < p)
972
{ /* only when there is some information */
973
ulong i;
974
ratpoints_sieve_entry *se = args->se_next;
975
double r = is_f_square[p] ? ((double)(np*(p-1) + p))/((double)(p*p))
976
: (double)np/(double)p;
977
prec[pnp].r = r;
978
args->se_next ++;
979
se->p = p;
980
se->is_f_square = is_f_square;
981
se->inverses = gel(inverses,pn);
982
se->offset = offsets[pn];
983
se->sieve[0] = (ratpoints_bit_array *)sieves0[pn];
984
for (i = 1; i < p; i++) se->sieve[i] = NULL;
985
prec[pnp].ssp = se;
986
pnp++;
987
}
988
989
if ((args->flags & RATPOINTS_CHECK_DENOM)
990
&& fba + fdc < args->max_forbidden
991
&& !is_f_square[p])
992
{ /* record forbidden divisors of the denominator */
993
if (coeffs_mod_p[degree] == 0)
994
{ /* leading coeff. divisible by p */
995
GEN r;
996
long v = Z_lvalrem(pel(c,degree), p, &r);
997
998
if (odd(v) || !mael(squares,pn, umodiu(r,p)+1))
999
{ /* Can only get something when valuation is odd
1000
or when valuation is even and lcf is not a p-adic square.
1001
Compute smallest n such that if v(den) >= n, the leading
1002
term determines the valuation. Then we must have v(den) < n. */
1003
long k, n = 1;
1004
for (k = degree-1; k >= 0; k--)
1005
{
1006
if (coeffs_mod_p[k] == 0)
1007
{
1008
long t = 1 + v - Z_lval(pel(c,k), p);
1009
long m = CEIL(t, (degree-k));
1010
if (m > n) n = m;
1011
}
1012
}
1013
if (n == 1)
1014
{
1015
forb_ba[fba].p = p;
1016
forb_ba[fba].start = sieves0[pn];
1017
forb_ba[fba].end = sieves0[pn]+p;
1018
forb_ba[fba].curr = forb_ba[fba].start;
1019
fba++;
1020
}
1021
else
1022
{
1023
forbidden[fdc] = upowuu(p, n);
1024
fdc++;
1025
}
1026
}
1027
}
1028
else /* leading coefficient is a nonsquare mod p */
1029
{ /* denominator divisible by p is excluded */
1030
forb_ba[fba].p = p;
1031
forb_ba[fba].start = sieves0[pn];
1032
forb_ba[fba].end = sieves0[pn]+p;
1033
forb_ba[fba].curr = forb_ba[fba].start;
1034
fba++;
1035
}
1036
}
1037
} /* end for pn */
1038
1039
/* update sp2 and sp1 if necessary */
1040
if (args->sp2 > pnp) args->sp2 = pnp;
1041
if (args->sp1 > args->sp2) args->sp1 = args->sp2;
1042
1043
/* sort the array to get at the best primes */
1044
qsort(prec, pnp, sizeof(entry), compare_entries);
1045
1046
/* put the sorted entries into sieve_list */
1047
for (n = 0; n < args->sp2; n++) sieve_list[n] = prec[n].ssp;
1048
1049
/* terminate array of forbidden divisors */
1050
if (args->flags & RATPOINTS_CHECK_DENOM)
1051
{
1052
long n;
1053
1054
for (n = args->num_primes+1;
1055
fba + fdc < args->max_forbidden && n <= nbprime; n++)
1056
{
1057
ulong p = args->listprime[n];
1058
1059
if (p*p > (ulong) args->b_high) break;
1060
if (kroiu(pel(c,degree), p) == -1)
1061
{
1062
forb_ba[fba].p = p;
1063
forb_ba[fba].start = sieves0[n];
1064
forb_ba[fba].end = sieves0[n]+p;
1065
forb_ba[fba].curr = forb_ba[fba].start;
1066
fba++;
1067
}
1068
}
1069
forb_ba[fba].p = 0; /* terminating zero */
1070
forbidden[fdc] = 0; /* terminating zero */
1071
args->max_forbidden = fba + fdc; /* note actual number */
1072
}
1073
1074
if (fba + fdc == 0) args->flags &= ~RATPOINTS_CHECK_DENOM;
1075
return gc_long(av,0);
1076
}
1077
1078
/**************************************************************************
1079
* The sieving procedure itself *
1080
**************************************************************************/
1081
static void
1082
sift(long b, ratpoints_bit_array *survivors, ratpoints_args *args,
1083
bit_selection which_bits, ratpoints_bit_array bits16,
1084
ratpoints_sieve_entry **sieve_list, long *bp_list, int *quit,
1085
int process(long, long, GEN, void*, int*), void *info)
1086
{
1087
pari_sp av = avma;
1088
sieve_spec ssp[args->sp2];
1089
int do_setup = 1;
1090
long k, height = args->height, nb;
1091
1092
if (odd(b) == 0) which_bits = num_odd; /* even denominator */
1093
1094
/* Note that b is new */
1095
args->bc = NULL;
1096
nb = 0;
1097
1098
for (k = 0; k < args->num_inter; k++)
1099
{
1100
ratpoints_interval inter = args->domain[k];
1101
long low, high;
1102
1103
/* Determine relevant interval [low, high] of numerators. */
1104
if (b*inter.low <= -height)
1105
low = -height;
1106
else
1107
{
1108
if (b*inter.low > height) break;
1109
low = ceil(b*inter.low);
1110
}
1111
if (b*inter.up >= height)
1112
high = height;
1113
else
1114
{
1115
if (b*inter.up < -height) continue;
1116
high = floor(b*inter.up);
1117
}
1118
1119
if (do_setup)
1120
{ /* set up the sieve information */
1121
long n;
1122
1123
do_setup = 0; /* only do it once for every b */
1124
for (n = 0; n < args->sp2; n++)
1125
{
1126
ratpoints_sieve_entry *se = sieve_list[n];
1127
long p = se->p;
1128
long bp = bp_list[n];
1129
ratpoints_bit_array *sptr;
1130
1131
if (which_bits != num_all) /* divide by 2 mod p */
1132
bp = odd(bp) ? (bp+p) >> 1 : bp >> 1;
1133
sptr = se->sieve[bp];
1134
1135
ssp[n].p = p;
1136
ssp[n].offset = (which_bits == num_odd) ? se->offset : 0;
1137
1138
/* copy if already initialized, else initialize */
1139
ssp[n].ptr = sptr ? sptr : (p<BITS_IN_LONG?sieve_init1(p, se, bp, args)
1140
:sieve_init2(p, se, bp, args));
1141
}
1142
}
1143
1144
switch(which_bits)
1145
{
1146
case num_all: break;
1147
case num_none: break;
1148
case num_odd: low >>= 1; high--; high >>= 1; break;
1149
case num_even: low++; low >>= 1; high >>= 1; break;
1150
}
1151
1152
/* now turn the bit interval into [low, high[ */
1153
high++;
1154
1155
if (low < high)
1156
{
1157
long w_low, w_high, w_low0, w_high0, range = args->array_size;
1158
1159
/* Now the range of longwords (= bit_arrays) */
1160
w_low = low >> RBA_SHIFT;
1161
w_high = (high + (long)(RBA_LENGTH-1)) >> RBA_SHIFT;
1162
w_low0 = w_low;
1163
w_high0 = w_low0 + range;
1164
for ( ; w_low0 < w_high; w_low0 = w_high0, w_high0 += range)
1165
{
1166
long i;
1167
if (w_high0 > w_high) { w_high0 = w_high; range = w_high0 - w_low0; }
1168
/* initialise the bits */
1169
for (i = range; i; i--) survivors[i-1] = bits16;
1170
/* boundary words */
1171
if (w_low0 == w_low)
1172
{
1173
long sh = low - RBA_LENGTH * w_low;
1174
ulong *survl = (ulong *)survivors;
1175
1176
#ifdef HAS_SSE2
1177
if (sh >= BITS_IN_LONG)
1178
{
1179
survl[0] = 0UL;
1180
survl[1] &= (~0UL)<<(sh - BITS_IN_LONG);
1181
}
1182
else
1183
survl[0] &= ~(0UL)<<sh;
1184
#else
1185
survl[0] &= ~(0UL)<<sh;
1186
#endif
1187
}
1188
if (w_high0 == w_high)
1189
{
1190
long sh = RBA_LENGTH * w_high - high;
1191
ulong *survl = (ulong *)&survivors[range-1];
1192
1193
#ifdef HAS_SSE2
1194
if (sh >= BITS_IN_LONG)
1195
{
1196
survl[0] &= ~(0UL)>>(sh - BITS_IN_LONG);
1197
survl[1] = 0UL;
1198
}
1199
else
1200
survl[1] &= ~(0UL)>>sh;
1201
#else
1202
survl[0] &= ~(0UL)>>sh;
1203
#endif
1204
}
1205
nb += _ratpoints_sift0(b, w_low0, w_high0, args, which_bits,
1206
survivors, &ssp[0], quit, process, info);
1207
if (*quit) return;
1208
}
1209
}
1210
}
1211
if (nb==0) set_avma(av);
1212
}
1213
1214
/**************************************************************************
1215
* Find points by looping over the denominators and sieving numerators *
1216
**************************************************************************/
1217
static void
1218
find_points_work(ratpoints_args *args,
1219
int process(long, long, GEN, void*, int*), void *info)
1220
{
1221
int quit = 0;
1222
GEN c = args->cof;
1223
long degree = degpol(c);
1224
long nbprime = lg(args->listprime)-1;
1225
long height = args->height;
1226
1227
int point_at_infty = 0; /* indicates if there are points at infinity */
1228
int lcfsq = Z_issquare(pel(c,degree));
1229
1230
forbidden_entry *forb_ba = args->forb_ba;
1231
long *forbidden = args->forbidden;
1232
/* The forbidden divisors, a zero-terminated array.
1233
Used when degree is even and leading coefficient is not a square */
1234
1235
/* These are used when degree is odd and leading coeff. is not +-1 */
1236
1237
ratpoints_sieve_entry **sieve_list = (ratpoints_sieve_entry**)
1238
stack_malloc(nbprime*sizeof(ratpoints_sieve_entry*));
1239
bit_selection which_bits = num_all;
1240
ulong den_bits;
1241
ratpoints_bit_array num_bits[16];
1242
1243
args->flags &= RATPOINTS_FLAGS_INPUT_MASK;
1244
args->flags |= RATPOINTS_CHECK_DENOM;
1245
1246
/* initialize memory management */
1247
args->se_next = args->se_buffer;
1248
args->ba_next = args->ba_buffer;
1249
args->int_next = args->int_buffer;
1250
1251
/* Some sanity checks */
1252
args->num_inter = 0;
1253
1254
if (args->num_primes > nbprime) args->num_primes = nbprime;
1255
if (args->sp2 > args->num_primes) args->sp2 = args->num_primes;
1256
if (args->sp1 > args->sp2) args->sp1 = args->sp2;
1257
1258
if (args->b_low < 1) args->b_low = 1;
1259
if (args->b_high < 1) args->b_high = height;
1260
if (args->b_high > height) args->b_high = height;
1261
if (args->max_forbidden < 0)
1262
args->max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN;
1263
if (args->max_forbidden > nbprime)
1264
args->max_forbidden = nbprime;
1265
if (args->array_size <= 0) args->array_size = RATPOINTS_ARRAY_SIZE;
1266
{
1267
long s = 2*CEIL(height, BITS_IN_LONG);
1268
if (args->array_size > s) args->array_size = s;
1269
}
1270
/* Don't reverse if intervals are specified or limits for the denominator
1271
are given */
1272
if (args->num_inter > 0 || args->b_low > 1 || args->b_high < height)
1273
args->flags |= RATPOINTS_NO_REVERSE;
1274
1275
/* Check if reversal of polynomial might be better:
1276
* case 1: degree is even, but trailing coefficient is zero
1277
* case 2: degree is even, leading coefficient is a square, but
1278
* trailing coefficient is not
1279
* case 3: degree is odd, |leading coefficient| > 1,
1280
* trailing coefficient is zero, |coeff. of x| = 1 */
1281
if (!(args->flags & RATPOINTS_NO_REVERSE))
1282
{
1283
if (!odd(degree))
1284
{
1285
if (signe(pel(c,0)) == 0)
1286
{ /* case 1 */
1287
long n;
1288
args->flags |= RATPOINTS_REVERSED;
1289
for (n = 0; n < degree>>1; n++) swap(pel(c,n), pel(c,degree-n));
1290
degree--;
1291
setlg(c,degree+3);
1292
}
1293
else if (lcfsq && !Z_issquare(pel(c,0)))
1294
{ /* case 2 */
1295
long n;
1296
args->flags |= RATPOINTS_REVERSED;
1297
for (n = 0; n < degree>>1; n++) swap(pel(c,n), pel(c,degree-n));
1298
lcfsq = 0;
1299
}
1300
}
1301
else
1302
{ /* odd degree, case 3*/
1303
if (!is_pm1(pel(c,degree)) && !signe(pel(c,0)) && is_pm1(pel(c,1)))
1304
{
1305
long n;
1306
args->flags |= RATPOINTS_REVERSED;
1307
for (n = 1; n < degree>>1; n++) swap(pel(c,n),pel(c,degree+1-n));
1308
}
1309
}
1310
}
1311
1312
/* Deal with the intervals */
1313
if (args->num_inter == 0)
1314
{ /* default interval (effectively ]-oo,oo[) if none is given */
1315
args->domain = (ratpoints_interval*) stack_malloc(2*degree*sizeof(ratpoints_interval));
1316
args->domain[0].low = -height; args->domain[0].up = height;
1317
args->num_inter = 1;
1318
}
1319
1320
ratpoints_compute_sturm(args);
1321
1322
/* Point(s) at infinity? */
1323
if (odd(degree) || lcfsq)
1324
{
1325
args->flags &= ~RATPOINTS_CHECK_DENOM;
1326
point_at_infty = 1;
1327
}
1328
1329
/* Can use only squares as denoms if degree is odd and poly is +-monic */
1330
if (odd(degree))
1331
{
1332
GEN w1 = pel(c,degree);
1333
if (is_pm1(w1))
1334
args->flags |= RATPOINTS_USE_SQUARES;
1335
else /* set up information on divisors of leading coefficient */
1336
setup_us1(args, absi_shallow(w1));
1337
}
1338
1339
/* deal with f mod powers of 2 */
1340
which_bits = get_2adic_info(args, &den_bits, &num_bits[0]);
1341
/* which_bits says whether to consider even and/or odd numerators
1342
* when the denominator is odd.
1343
*
1344
* Bit k in den_bits is 0 if b congruent to k mod BITS_IN_LONG need
1345
* not be considered as a denominator.
1346
*
1347
* Bit k in num_bits[b] is 0 is numerators congruent to
1348
* k (which_bits = den_all)
1349
* 2k (which_bits = den_even)
1350
* 2k+1 (which_bits = den_odd)
1351
* need not be considered for denominators congruent to b mod 16. */
1352
1353
/* set up the sieve data structure */
1354
if (sieving_info(args, sieve_list)) return;
1355
1356
/* deal with point(s) at infinity */
1357
if (point_at_infty)
1358
{
1359
long a = 1, b = 0;
1360
1361
if (args->flags & RATPOINTS_REVERSED) { a = 0; b = 1; }
1362
if (odd(degree))
1363
(void)process(a, b, gen_0, info, &quit);
1364
else
1365
{
1366
GEN w0 = sqrti(pel(c,degree));
1367
(void)process(a, b, w0, info, &quit);
1368
(void)process(a, b, negi(w0), info, &quit);
1369
}
1370
if (quit) return;
1371
}
1372
/* now do the sieving */
1373
{
1374
ratpoints_bit_array *survivors = (ratpoints_bit_array *)
1375
stack_malloc_align((args->array_size)*sizeof(ratpoints_bit_array), RBA_ALIGN);
1376
if (args->flags & (RATPOINTS_USE_SQUARES | RATPOINTS_USE_SQUARES1))
1377
{
1378
if (args->flags & RATPOINTS_USE_SQUARES)
1379
/* need only take squares as denoms */
1380
{
1381
long b, bb;
1382
long bp_list[args->sp2];
1383
long last_b = args->b_low;
1384
long n;
1385
for (n = 0; n < args->sp2; n++)
1386
bp_list[n] = mod(args->b_low, sieve_list[n]->p);
1387
1388
for (b = 1; bb = b*b, bb <= args->b_high; b++)
1389
if (bb >= args->b_low)
1390
{
1391
ratpoints_bit_array bits = num_bits[bb & 0xf];
1392
if (TEST(bits))
1393
{
1394
long n;
1395
long d = bb - last_b;
1396
1397
/* fill bp_list */
1398
for (n = 0; n < args->sp2; n++)
1399
bp_list[n] = mod(bp_list[n] + d, sieve_list[n]->p);
1400
last_b = bb;
1401
1402
sift(bb, survivors, args, which_bits, bits,
1403
sieve_list, &bp_list[0], &quit, process, info);
1404
if (quit) break;
1405
}
1406
}
1407
}
1408
else /* args->flags & RATPOINTS_USE_SQUARES1 */
1409
{
1410
GEN den_info = args->den_info;
1411
GEN divisors = args->divisors;
1412
long ld = lg(divisors);
1413
long k;
1414
long b, bb;
1415
long bp_list[args->sp2];
1416
1417
for (k = 1; k < ld; k++)
1418
{
1419
long d = divisors[k];
1420
long last_b = d;
1421
long n;
1422
if (d > args->b_high) continue;
1423
for (n = 0; n < args->sp2; n++)
1424
bp_list[n] = mod(d, sieve_list[n]->p);
1425
1426
for (b = 1; bb = d*b*b, bb <= args->b_high; b++)
1427
{
1428
if (bb >= args->b_low)
1429
{
1430
int flag = 1;
1431
ratpoints_bit_array bits = num_bits[bb & 0xf];
1432
1433
if (EXT0(bits))
1434
{
1435
long i, n, l = lg(gel(den_info,1));
1436
long d = bb - last_b;
1437
1438
/* fill bp_list */
1439
for (n = 0; n < args->sp2; n++)
1440
bp_list[n] = mod(bp_list[n] + d, sieve_list[n]->p);
1441
last_b = bb;
1442
1443
for(i = 1; i < l; i++)
1444
{
1445
long v = z_lval(bb, mael(den_info,1,i));
1446
if((v >= mael(den_info,3,i))
1447
&& odd(v + (mael(den_info,2,i)))) { flag = 0; break; }
1448
}
1449
if (flag)
1450
{
1451
sift(bb, survivors, args, which_bits, bits,
1452
sieve_list, &bp_list[0], &quit, process, info);
1453
if (quit) break;
1454
}
1455
}
1456
}
1457
}
1458
if (quit) break;
1459
}
1460
}
1461
}
1462
else
1463
{
1464
if (args->flags & RATPOINTS_CHECK_DENOM)
1465
{
1466
long *forb;
1467
long b;
1468
long bp_list[args->sp2];
1469
long last_b = args->b_low;
1470
ulong b_bits;
1471
long n;
1472
for (n = 0; n < args->sp2; n++)
1473
bp_list[n] = mod(args->b_low, sieve_list[n]->p);
1474
{
1475
forbidden_entry *fba = &forb_ba[0];
1476
long b_low = args->b_low;
1477
long w_low = (b_low-1) >> TWOPOTBITS_IN_LONG;
1478
1479
b_bits = den_bits;
1480
while (fba->p)
1481
{
1482
fba->curr = fba->start + mod(w_low, fba->p);
1483
b_bits &= *(fba->curr);
1484
fba++;
1485
}
1486
b_bits >>= (b_low-1) & LONG_MASK;
1487
}
1488
1489
for (b = args->b_low; b <= args->b_high; b++)
1490
{
1491
ratpoints_bit_array bits = num_bits[b & 0xf];
1492
1493
if ((b & LONG_MASK) == 0)
1494
{ /* next b_bits */
1495
forbidden_entry *fba = &forb_ba[0];
1496
1497
b_bits = den_bits;
1498
while (fba->p)
1499
{
1500
fba->curr++;
1501
if (fba->curr == fba->end) fba->curr = fba->start;
1502
b_bits &= *(fba->curr);
1503
fba++;
1504
}
1505
}
1506
else
1507
b_bits >>= 1;
1508
1509
if (odd(b_bits) && EXT0(bits))
1510
{ /* check if denominator is excluded */
1511
for (forb = &forbidden[0] ; *forb && (b % (*forb)); forb++)
1512
continue;
1513
if (*forb == 0 && rpjacobi(b, pel(c,degree)) == 1)
1514
{
1515
long n, d = b - last_b;
1516
1517
/* fill bp_list */
1518
for (n = 0; n < args->sp2; n++)
1519
{
1520
long bp = bp_list[n] + d;
1521
long p = sieve_list[n]->p;
1522
1523
while (bp >= p) bp -= p;
1524
bp_list[n] = bp;
1525
}
1526
last_b = b;
1527
1528
sift(b, survivors, args, which_bits, bits,
1529
sieve_list, &bp_list[0], &quit, process, info);
1530
if (quit) break;
1531
}
1532
}
1533
}
1534
} /* if (args->flags & RATPOINTS_CHECK_DENOM) */
1535
else
1536
{
1537
long b, n;
1538
long bp_list[args->sp2];
1539
long last_b = args->b_low;
1540
for (n = 0; n < args->sp2; n++)
1541
bp_list[n] = mod(args->b_low, sieve_list[n]->p);
1542
for (b = args->b_low; b <= args->b_high; b++)
1543
{
1544
ratpoints_bit_array bits = num_bits[b & 0xf];
1545
if (EXT0(bits))
1546
{
1547
long n;
1548
long d = b - last_b;
1549
1550
/* fill bp_list */
1551
for (n = 0; n < args->sp2; n++)
1552
{
1553
long bp = bp_list[n] + d;
1554
long p = sieve_list[n]->p;
1555
1556
while (bp >= p) bp -= p;
1557
bp_list[n] = bp;
1558
}
1559
last_b = b;
1560
1561
sift(b, survivors, args, which_bits, bits,
1562
sieve_list, &bp_list[0], &quit, process, info);
1563
if (quit) break;
1564
}
1565
}
1566
}
1567
}
1568
}
1569
}
1570
1571
static GEN
1572
vec_append_grow(GEN z, long i, GEN x)
1573
{
1574
long n = lg(z)-1;
1575
if (i > n)
1576
{
1577
n <<= 1;
1578
z = vec_lengthen(z,n);
1579
}
1580
gel(z,i) = x;
1581
return z;
1582
}
1583
1584
struct points
1585
{
1586
GEN z;
1587
long i, f;
1588
};
1589
1590
static int
1591
process(long a, long b, GEN y, void *info0, int *quit)
1592
{
1593
struct points *p = (struct points *) info0;
1594
if (b==0 && (p->f&2L)) return 0;
1595
*quit = (p->f&1);
1596
p->z = vec_append_grow(p->z, ++p->i, mkvec3(stoi(a),y,stoi(b)));
1597
return 1;
1598
}
1599
1600
static int
1601
args_h(ratpoints_args *args, GEN D)
1602
{
1603
long H, h, l = 1;
1604
GEN L;
1605
switch(typ(D))
1606
{
1607
case t_INT: if (signe(D) <= 0) return 0;
1608
H = h = itos(D); break;
1609
case t_VEC: if (lg(D) != 3) return 0;
1610
H = gtos(gel(D,1));
1611
L = gel(D,2);
1612
if (typ(L)==t_INT) { h = itos(L); break; }
1613
if (typ(L)==t_VEC && lg(L)==3)
1614
{
1615
l = gtos(gel(L,1));
1616
h = gtos(gel(L,2)); break;
1617
}
1618
default: return 0;
1619
}
1620
args->height = H;
1621
args->b_low = l;
1622
args->b_high = h; return 1;
1623
}
1624
1625
static GEN
1626
ZX_hyperellratpoints(GEN P, GEN h, long flag)
1627
{
1628
pari_sp av = avma;
1629
ratpoints_args args;
1630
struct points data;
1631
ulong flags = 0;
1632
1633
if (!ZX_is_squarefree(P))
1634
pari_err_DOMAIN("hyperellratpoints","issquarefree(pol)","=",gen_0, P);
1635
if (!args_h(&args, h))
1636
{
1637
pari_err_TYPE("hyperellratpoints", h);
1638
return NULL;/*LCOV_EXCL_LINE*/
1639
}
1640
find_points_init(&args, RATPOINTS_DEFAULT_BIT_PRIMES);
1641
1642
args.cof = shallowcopy(P);
1643
args.num_inter = 0;
1644
args.sp1 = RATPOINTS_DEFAULT_SP1;
1645
args.sp2 = RATPOINTS_DEFAULT_SP2;
1646
args.array_size = RATPOINTS_ARRAY_SIZE;
1647
args.num_primes = RATPOINTS_DEFAULT_NUM_PRIMES;
1648
args.bit_primes = RATPOINTS_DEFAULT_BIT_PRIMES;
1649
args.max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN;
1650
args.flags = flags;
1651
data.z = cgetg(17,t_VEC);
1652
data.i = 0;
1653
data.f = flag;
1654
find_points_work(&args, process, (void *)&data);
1655
1656
setlg(data.z, data.i+1);
1657
return gerepilecopy(av, data.z);
1658
}
1659
1660
/* The ordinates of the points returned need to be divided by den
1661
* by the caller to get the actual solutions */
1662
static GEN
1663
QX_hyperellratpoints(GEN P, GEN h, long flag, GEN *den)
1664
{
1665
GEN Q = Q_remove_denom(P, den);
1666
if (*den) Q = ZX_Z_mul(Q, *den);
1667
return ZX_hyperellratpoints(Q, h, flag);
1668
}
1669
1670
static GEN
1671
ZX_homogenous_evalpow(GEN Q, GEN A, GEN B)
1672
{
1673
pari_sp av = avma;
1674
long i, d = degpol(Q);
1675
GEN s = gel(Q, d+2);
1676
for (i = d-1; i >= 0; i--)
1677
s = addii(mulii(s, A), mulii(gel(B,d+1-i), gel(Q,i+2)));
1678
return gerepileuptoint(av, s);
1679
}
1680
1681
static GEN
1682
to_RgX(GEN a, long v) { return typ(a)==t_POL? a: scalarpol(a,v); }
1683
1684
static int
1685
hyperell_check(GEN PQ, GEN *P, GEN *Q)
1686
{
1687
*P = *Q = NULL;
1688
if (typ(PQ) == t_POL)
1689
{
1690
if (!RgX_is_QX(PQ)) return 0;
1691
*P = PQ;
1692
}
1693
else
1694
{
1695
long v = gvar(PQ);
1696
if (v == NO_VARIABLE || typ(PQ) != t_VEC || lg(PQ) != 3) return 0;
1697
*P = to_RgX(gel(PQ,1), v); if (!RgX_is_QX(*P)) return 0;
1698
*Q = to_RgX(gel(PQ,2), v); if (!RgX_is_QX(*Q)) return 0;
1699
if (!signe(*Q)) *Q = NULL;
1700
}
1701
return 1;
1702
}
1703
1704
GEN
1705
hyperellratpoints(GEN PQ, GEN h, long flag)
1706
{
1707
pari_sp av = avma;
1708
GEN P, Q, H, L, den;
1709
long i, l, dy, dQ;
1710
1711
if (flag<0 || flag>1) pari_err_FLAG("ellratpoints");
1712
if (!hyperell_check(PQ, &P, &Q)) pari_err_TYPE("hyperellratpoints",PQ);
1713
if (!Q)
1714
{
1715
L = QX_hyperellratpoints(P, h, flag|2L, &den);
1716
dy = (degpol(P)+1)>>1;
1717
l = lg(L);
1718
for (i = 1; i < l; i++)
1719
{
1720
GEN Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3);
1721
GEN zdy = powiu(z, dy);
1722
if (den) zdy = mulii(zdy, den);
1723
gel(L,i) = mkvec2(gdiv(x,z), gdiv(y, zdy));
1724
}
1725
return gerepilecopy(av, L);
1726
}
1727
H = RgX_add(RgX_muls(P,4), RgX_sqr(Q));
1728
dy = (degpol(H)+1)>>1; dQ = degpol(Q);
1729
L = QX_hyperellratpoints(H, h, flag|2L, &den);
1730
l = lg(L);
1731
for (i = 1; i < l; i++)
1732
{
1733
GEN Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3);
1734
GEN B = gpowers(z, dQ);
1735
GEN Qx = gdiv(ZX_homogenous_evalpow(Q, x, B), gel(B, dQ+1));
1736
GEN zdy = powiu(z, dy);
1737
if (den) zdy = mulii(zdy, den);
1738
gel(L,i) = mkvec2(gdiv(x,z), gmul2n(gsub(gdiv(y,zdy),Qx),-1));
1739
}
1740
return gerepilecopy(av, L);
1741
}
1742
1743
GEN
1744
ellratpoints(GEN E, GEN h, long flag)
1745
{
1746
pari_sp av = avma;
1747
GEN L, a1, a3, den;
1748
long i, l;
1749
checkell_Q(E);
1750
if (flag<0 || flag>1) pari_err_FLAG("ellratpoints");
1751
if (!RgV_is_QV(vecslice(E,1,5))) pari_err_TYPE("ellratpoints",E);
1752
a1 = ell_get_a1(E);
1753
a3 = ell_get_a3(E);
1754
L = QX_hyperellratpoints(ec_bmodel(E), h, flag|2L, &den);
1755
l = lg(L);
1756
for (i = 1; i < l; i++)
1757
{
1758
GEN P, Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3);
1759
if (!signe(z))
1760
P = ellinf();
1761
else
1762
{
1763
GEN z2 = sqri(z);
1764
if (den) y = gdiv(y, den);
1765
y = gsub(y, gadd(gmul(a1, mulii(x,z)), gmul(a3,z2)));
1766
P = mkvec2(gdiv(x,z), gdiv(y,shifti(z2,1)));
1767
}
1768
gel(L,i) = P;
1769
}
1770
return gerepilecopy(av, L);
1771
}
1772
1773