Code coverage tests

This page documents the degree to which the PARI/GP source code is tested by our public test suite, distributed with the source distribution in directory src/test/. This is measured by the gcov utility; we then process gcov output using the lcov frond-end.

We test a few variants depending on Configure flags on the pari.math.u-bordeaux.fr machine (x86_64 architecture), and agregate them in the final report:

The target is to exceed 90% coverage for all mathematical modules (given that branches depending on DEBUGLEVEL or DEBUGMEM are not covered). This script is run to produce the results below.

LCOV - code coverage report
Current view: top level - modules - ratpoints.c (source / functions) Coverage Total Hit
Test: PARI/GP v2.18.1 lcov report (development 31042-0fbe168e69) Lines: 96.7 % 911 881
Test Date: 2026-07-23 17:04:59 Functions: 100.0 % 33 33
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.0-1