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) Hit Total Coverage
Test: PARI/GP v2.18.0 lcov report (development 29804-254f602fce) Lines: 879 908 96.8 %
Date: 2024-12-18 09:08:59 Functions: 33 33 100.0 %
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     2737965 : sieve_init1(long p, ratpoints_sieve_entry *se1, long b1, ratpoints_args *args1)
     213             : {
     214     2737965 :   ratpoints_sieve_entry *se = se1;
     215     2737965 :   ratpoints_args *args = args1;
     216     2737965 :   int *isfs = se->is_f_square;
     217     2737965 :   long b = b1;
     218     2737965 :   long lmp = BITS_IN_LONG % p;
     219     2737965 :   long ldp = BITS_IN_LONG / p;
     220     2737965 :   long p1 = (ldp + 1) * p;
     221     2737965 :   long diff_shift = p1 & LONG_MASK;
     222     2737965 :   long diff = BITS_IN_LONG - diff_shift;
     223             :   ulong help0;
     224             :   long a;
     225     2737965 :   long d = se->inverses[b];
     226     2737965 :   long ab = 0; /* a/b mod p */
     227     2737965 :   ulong test = 1UL;
     228     2737965 :   ulong he0 = 0UL;
     229   121734264 :   for (a = 0; a < p; a++)
     230             :   {
     231   118996299 :     if (isfs[ab]) he0 |= test;
     232   118996299 :     ab += d;
     233   118996299 :     if (ab >= p) ab -= p;
     234   118996299 :     test <<= 1;
     235             :   }
     236     2737965 :   help0 = he0;
     237             :   {
     238             :     ulong help1;
     239             :      /* repeat bit pattern floor(BITS_IN_LONG/p) times */
     240     2737965 :     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     2737965 :     help1 = pattern >> lmp;
     247     6249223 :     for (i = p; i < BITS_IN_LONG; i <<= 1)
     248     3511258 :       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     2737965 :       ulong *si = (ulong *)args->ba_next;
     254             : 
     255     2737965 :       args->ba_next += p + RATPOINTS_CHUNK-1;
     256             :       /* copy the first chunk into sieve[b][] */
     257     2737965 :       si[0] = help0;
     258             :       /* now keep repeating the bit pattern,
     259             :          rotating it in help0/help1 */
     260   118996299 :       for (a = 1 ; a < p; a++)
     261             :       {
     262   116258334 :         ulong temp = help0 >> diff;
     263   116258334 :         help0 = help1 | (help0 << diff_shift);
     264   116258334 :         si[a] = help0;
     265   116258334 :         help1 = temp;
     266             :       }
     267   314875500 :       CODE_INIT_SIEVE_COPY
     268             :       /* set sieve array */
     269     2737965 :       se->sieve[b] = (ratpoints_bit_array *)si;
     270     2737965 :       return (ratpoints_bit_array *)si;
     271             :     }
     272             :   }
     273             : }
     274             : 
     275             : /* This is for p > BITS_IN_LONG */
     276             : static ratpoints_bit_array *
     277     9938663 : sieve_init2(long p, ratpoints_sieve_entry *se1, long b1, ratpoints_args *args1)
     278             : {
     279     9938663 :   pari_sp av = avma;
     280     9938663 :   ratpoints_sieve_entry *se = se1;
     281     9938663 :   ratpoints_args *args = args1;
     282     9938663 :   int *isfs = se->is_f_square;
     283     9938663 :   long b = b1;
     284             :   /* long ldp = 0;  = BITS_IN_LONG / p */
     285             :   /* long p1 = p; = (ldp + 1) * p; */
     286     9938663 :   long wp = p >> TWOPOTBITS_IN_LONG;
     287     9938663 :   long diff_shift = p & LONG_MASK;
     288     9938663 :   long diff = BITS_IN_LONG - diff_shift;
     289     9938663 :   ulong *help = (ulong *) new_chunk((p>>TWOPOTBITS_IN_LONG) + 2);
     290             : 
     291             :   /* initialize help */
     292             :   {
     293     9938663 :     ulong *he = &help[0];
     294     9938663 :     ulong *he1 = &he[(p>>TWOPOTBITS_IN_LONG) + 2];
     295    41996437 :     while (he1 != he) { he1--; *he1 = 0UL; }
     296             :   }
     297     9938663 :   { ulong work = 0UL;
     298             :     long a;
     299     9938663 :     long ab = 0; /* a/b mod p */
     300     9938663 :     long d = se->inverses[b];
     301     9938663 :     long n = 0;
     302     9938663 :     ulong test = 1UL;
     303   965864274 :     for (a = 0; a < p; )
     304             :     {
     305   955925611 :       if (isfs[ab]) work |= test;
     306   955925611 :       ab += d;
     307   955925611 :       if (ab >= p) ab -= p;
     308   955925611 :       test <<= 1;
     309   955925611 :       a++;
     310   955925611 :       if ((a & LONG_MASK) == 0)
     311    12180448 :       { help[n] = work; n++; work = 0UL; test = 1UL; }
     312             :     }
     313     9938663 :     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     9938663 :     ulong *si = (ulong *)args->ba_next;
     320             :     long a1;
     321             :     long a;
     322             : 
     323     9938663 :     args->ba_next += p + RATPOINTS_CHUNK-1;
     324             :     /* copy the first chunk from help[] into sieve[num][b][] */
     325    22119111 :     for (a = 0; a < wp; a++) si[a] = help[a];
     326             :     /* now keep repeating the bit pattern, rotating it in help */
     327   953683826 :     for (a1 = a ; a < p; a++)
     328             :     {
     329   943745163 :       long t = (a1 == wp) ? 0 : a1+1;
     330   943745163 :       help[a1] |= help[t]<<diff_shift;
     331   943745163 :       si[a] = help[a1];
     332   943745163 :       a1 = t;
     333   943745163 :       help[a1] >>= diff;
     334             :     }
     335  1865556852 :      CODE_INIT_SIEVE_COPY
     336             :     /* set sieve array */
     337     9938663 :     se->sieve[b] = (ratpoints_bit_array *)si;
     338     9938663 :     set_avma(av);
     339     9938663 :     return (ratpoints_bit_array *)si;
     340             :   }
     341             : }
     342             : 
     343             : static GEN
     344       12428 : gen_squares(GEN listprime)
     345             : {
     346       12428 :   long nbprime = lg(listprime)-1;
     347       12428 :   GEN sq = cgetg(nbprime+1, t_VEC);
     348             :   long n;
     349      385268 :   for (n = 1; n <= nbprime; n++)
     350             :   {
     351      372840 :     ulong i, p = uel(listprime,n);
     352      372840 :     GEN w = zero_zv(p), work = w+1;
     353      372840 :     work[0] = 1;
     354             :     /* record nonzero squares mod p, p odd */
     355    10862072 :     for (i = 1; i < p; i += 2) work[(i*i) % p] = 1;
     356      372840 :     gel(sq, n) = w;
     357             :   }
     358       12428 :   return sq;
     359             : }
     360             : 
     361             : static GEN
     362       12428 : gen_offsets(GEN P)
     363             : {
     364       12428 :   long n, l = lg(P);
     365       12428 :   GEN of = cgetg(l, t_VEC);
     366      385268 :   for (n = 1; n < l; n++)
     367             :   {
     368      372840 :     ulong p = uel(P,n);
     369      372840 :     uel(of, n) = Fl_inv((2*RBA_LENGTH)%p, p);
     370             :   }
     371       12428 :   return of;
     372             : }
     373             : 
     374             : static GEN
     375       12428 : gen_inverses(GEN P)
     376             : {
     377       12428 :   long n, l = lg(P);
     378       12428 :   GEN iv = cgetg(l, t_VEC);
     379      385268 :   for (n = 1; n < l; n++)
     380             :   {
     381      372840 :     ulong i, p = uel(P,n);
     382      372840 :     GEN w = cgetg(p, t_VECSMALL);
     383    21351304 :     for (i = 1; i < p; i++) uel(w, i) = Fl_inv(i, p);
     384      372840 :     gel(iv, n) = w;
     385             :   }
     386       12428 :   return iv;
     387             : }
     388             : 
     389             : static ulong **
     390       12428 : gen_sieves0(GEN listprime)
     391             : {
     392             :   long n;
     393       12428 :   long nbprime = lg(listprime)-1;
     394       12428 :   ulong ** w = (ulong**) new_chunk(nbprime+1);
     395      385268 :   for (n = 1; n <= nbprime; n++)
     396             :   {
     397      372840 :     ulong a, p = uel(listprime,n);
     398      372840 :     ulong *si = (ulong *) stack_malloc_align((p+RATPOINTS_CHUNK-1)*RBA_SIZE, RBA_SIZE);
     399    21724144 :     for (a = 0; a < p; a++) si[a] = ~0UL;
     400    22533480 :     for (a = 0; a < BITS_IN_LONG; a++)
     401    22160640 :       uel(si,(p*a)>>TWOPOTBITS_IN_LONG) &= ~(1UL<<((p*a) & LONG_MASK));
     402    46524096 :     CODE_INIT_SIEVE_COPY
     403      372840 :     w[n] = si;
     404             :   }
     405       12428 :   return w;
     406             : }
     407             : 
     408             : static void
     409       12428 : gen_sieve(ratpoints_args *args)
     410             : {
     411       12428 :   GEN listprimes = args->listprime;
     412       12428 :   args->offsets = gen_offsets(listprimes);
     413       12428 :   args->inverses = gen_inverses(listprimes);
     414       12428 :   args->sieves0 = gen_sieves0(listprimes);
     415       12428 : }
     416             : 
     417             : static GEN
     418       12428 : ZX_positive_region(GEN P, long h, long bitprec)
     419             : {
     420       12428 :   long prec = nbits2prec(bitprec);
     421       12428 :   GEN it = mkvec2(stoi(-h),stoi(h));
     422       12428 :   GEN R = realroots(P, it, prec);
     423       12428 :   long nR = lg(R)-1;
     424       12428 :   long s = signe(ZX_Z_eval(P,gel(it,1)));
     425       12428 :   long i=1, j;
     426             :   GEN iv, st, en;
     427       12428 :   if (s<0 && nR==0) return NULL;
     428       11742 :   iv = cgetg(((nR+1+(s>=0))>>1)+1, t_VEC);
     429       11742 :   if (s>=0) st = itor(gel(it,1),prec);
     430        5138 :   else    { st = gel(R,i); i++; }
     431       18143 :   for (j=1; i<nR; j++)
     432             :   {
     433        6401 :     gel(iv, j) = mkvec2(st, gel(R,i));
     434        6401 :     st = gel(R,i+1);
     435        6401 :     i+=2;
     436             :   }
     437       11742 :   if (i==nR) en = gel(R,i); else en = itor(gel(it,2),prec);
     438       11742 :   gel(iv,j) = mkvec2(st, en);
     439       11742 :   return iv;
     440             : }
     441             : 
     442             : static long
     443       12428 : posint(ratpoints_interval *ivlist, GEN P, long h)
     444             : {
     445       12428 :   GEN R = ZX_positive_region(P, h, 53);
     446       12428 :   const double eps = 1e-5;
     447             :   long nR, i;
     448             : 
     449       12428 :   if (!R) return 0;
     450       11742 :   nR = lg(R)-1;
     451       11742 :   i = 1;
     452       29885 :   for (i=1; i<=nR; i++)
     453             :   {
     454       18143 :     ivlist[i-1].low = rtodbl(gmael(R,i,1))-eps;
     455       18143 :     ivlist[i-1].up  = rtodbl(gmael(R,i,2))+eps;
     456             :   }
     457       11742 :   return nR;
     458             : }
     459             : 
     460             : static long
     461       12428 : ratpoints_compute_sturm(ratpoints_args *args)
     462             : {
     463       12428 :   ratpoints_interval *ivlist = args->domain;
     464       12428 :   args->num_inter = posint(ivlist, args->cof, (long) ivlist[0].up);
     465       12428 :   return args->num_inter;
     466             : }
     467             : 
     468             : /**************************************************************************
     469             :  * Try to avoid divisions                                                 *
     470             :  **************************************************************************/
     471             : INLINE long
     472   888509854 : mod(long a, long b)
     473             : {
     474   888509854 :   long b1 = b << 4; /* b1 = 16*b */
     475             : 
     476   888509854 :   if (a < -b1) { a %= b; if (a < 0) { a += b; } return a ; }
     477   877811229 :   if (a < 0) { a += b1; }
     478   355712818 :   else { if (a >= b1) { return a % b; } }
     479   870405994 :   b1 >>= 1; /* b1 = 8*b */
     480   870405994 :   if (a >= b1) { a -= b1; }
     481   870405994 :   b1 >>= 1; /* b1 = 4*b */
     482   870405994 :   if (a >= b1) { a -= b1; }
     483   870405994 :   b1 >>= 1; /* b1 = 2*b */
     484   870405994 :   if (a >= b1) { a -= b1; }
     485   870405994 :   if (a >= b) { a -= b; }
     486   870405994 :   return a;
     487             : }
     488             : 
     489             : static void
     490     2326442 : set_bc(long b, ratpoints_args *args)
     491             : {
     492     2326442 :   GEN w0 = gen_1;
     493     2326442 :   GEN c = args->cof, bc;
     494     2326442 :   long k, degree = degpol(c);
     495     2326442 :   bc = cgetg(degree+2, t_POL);
     496    11880339 :   for (k = degree-1; k >= 0; k--)
     497             :   {
     498     9553897 :     w0 = muliu(w0, b);
     499     9553897 :     gel(bc,k+2) = mulii(gel(c,k+2), w0);
     500             :   }
     501     2326442 :   args->bc = bc;
     502     2326442 : }
     503             : 
     504             : /**************************************************************************
     505             :  * Check a `survivor' of the sieve if it really gives a point.            *
     506             :  **************************************************************************/
     507             : 
     508             : static long
     509     3282373 : _ratpoints_check_point(long a, long b, ratpoints_args *args, int *quit,
     510             :                  int process(long, long, GEN, void*, int*), void *info)
     511             : {
     512     3282373 :   pari_sp av = avma;
     513     3282373 :   GEN w0, w2, c = args->cof, bc = args->bc;
     514     3282373 :   long k, degree = degpol(c);
     515     3282373 :   int reverse = args->flags & RATPOINTS_REVERSED;
     516             : 
     517             :   /* Compute F(a, b), where F is the homogenized version of f
     518             :      of smallest possible even degree  */
     519     3282373 :   w2 = gel(c, degree+2);
     520    16933659 :   for (k = degree-1; k >= 0; k--)
     521             :   {
     522    13651286 :     w2 = mulis(w2, a);
     523    13651286 :     w2 = addii(w2, gel(bc,k+2));
     524             :   }
     525     3282373 :   if (odd(degree)) w2 = muliu(w2, b);
     526             :   /* check if f(x,z) is a square; if so, process the point(s) */
     527     3282373 :   if (signe(w2) >= 0 && Z_issquareall(w2, &w0))
     528             :   {
     529       44898 :     if (reverse)
     530             :     {
     531        1218 :       if (a >= 0) (void)process(b, a, w0, info, quit);
     532         217 :       else        (void)process(-b, -a, w0, info, quit);
     533             :     }
     534       43680 :     else (void)process(a, b, w0, info, quit);
     535       44898 :     if (!*quit && signe(w0) != 0)
     536             :     {
     537       42602 :       GEN nw0 = negi(w0);
     538       42602 :       if (reverse)
     539             :       {
     540        1155 :         if (a >= 0) (void)process(b, a, nw0, info, quit);
     541         196 :         else        (void)process(-b, -a, nw0, info, quit);
     542             :       }
     543       41447 :       else (void)process(a, b, nw0, info, quit);
     544             :     }
     545       44898 :     return 1;
     546             :   }
     547     3237475 :   set_avma(av);
     548     3237475 :   return 0;
     549             : }
     550             : 
     551             : /**************************************************************************
     552             :  * The inner loop of the sieving procedure                                *
     553             :  **************************************************************************/
     554             : static long
     555    46550975 : _ratpoints_sift0(long b, long w_low, long w_high,
     556             :            ratpoints_args *args, bit_selection which_bits,
     557             :            ratpoints_bit_array *survivors, sieve_spec *sieves, int *quit,
     558             :            int process(long, long, GEN, void*, int*), void *info)
     559             : {
     560    46550975 :   long sp1 = args->sp1, sp2 = args->sp2;
     561    46550975 :   long i, n, nb = 0, absb = labs(b), base = 0;
     562             :   ratpoints_bit_array *surv0;
     563             : 
     564             :   /* now do the sieving (fast!) */
     565             : #if (RATPOINTS_CHUNK == 16)
     566             :   long w_low_new;
     567    35655390 :   ratpoints_bit_array *surv = survivors;
     568             : 
     569             :   /* first set the start fields for the first and second phases of sieving */
     570   712472724 :   for(n = 0; n < sp2; n++)
     571   676817334 :     sieves[n].start = sieves[n].ptr + mod(w_low + sieves[n].offset, sieves[n].p);
     572             :   /* Take RATPOINTS_CHUNK bit-arrays and apply phase 1 to them,
     573             :    * then repeat with the next RATPOINTS_CHUNK bit-arrays. */
     574   243543360 :   for(w_low_new = w_low; w_low_new < w_high; surv += RATPOINTS_CHUNK, w_low_new += RATPOINTS_CHUNK)
     575             :   {
     576             :     /* read data from memory into registers */
     577   207887970 :     ratpoints_bit_array reg0 = surv[0];
     578   207887970 :     ratpoints_bit_array reg1 = surv[1];
     579   207887970 :     ratpoints_bit_array reg2 = surv[2];
     580   207887970 :     ratpoints_bit_array reg3 = surv[3];
     581   207887970 :     ratpoints_bit_array reg4 = surv[4];
     582   207887970 :     ratpoints_bit_array reg5 = surv[5];
     583   207887970 :     ratpoints_bit_array reg6 = surv[6];
     584   207887970 :     ratpoints_bit_array reg7 = surv[7];
     585   207887970 :     ratpoints_bit_array reg8 = surv[8];
     586   207887970 :     ratpoints_bit_array reg9 = surv[9];
     587   207887970 :     ratpoints_bit_array reg10 = surv[10];
     588   207887970 :     ratpoints_bit_array reg11 = surv[11];
     589   207887970 :     ratpoints_bit_array reg12 = surv[12];
     590   207887970 :     ratpoints_bit_array reg13 = surv[13];
     591   207887970 :     ratpoints_bit_array reg14 = surv[14];
     592   207887970 :     ratpoints_bit_array reg15 = surv[15];
     593             : 
     594  2494655244 :     for(n = 0; n < sp1; n++)
     595             :     { /* retrieve the pointer to the beginning of the relevant bits */
     596  2286767274 :       ratpoints_bit_array *siv1 = sieves[n].start;
     597  2286767274 :       reg0 &= *siv1++;
     598  2286767274 :       reg1 &= *siv1++;
     599  2286767274 :       reg2 &= *siv1++;
     600  2286767274 :       reg3 &= *siv1++;
     601  2286767274 :       reg4 &= *siv1++;
     602  2286767274 :       reg5 &= *siv1++;
     603  2286767274 :       reg6 &= *siv1++;
     604  2286767274 :       reg7 &= *siv1++;
     605  2286767274 :       reg8 &= *siv1++;
     606  2286767274 :       reg9 &= *siv1++;
     607  2286767274 :       reg10 &= *siv1++;
     608  2286767274 :       reg11 &= *siv1++;
     609  2286767274 :       reg12 &= *siv1++;
     610  2286767274 :       reg13 &= *siv1++;
     611  2286767274 :       reg14 &= *siv1++;
     612  2286767274 :       reg15 &= *siv1++;
     613             : 
     614             :       /* update the pointer for the next round
     615             :        * (RATPOINTS_CHUNK-1 bit-arrays after sieves[n].end) */
     616  3220498164 :       while(siv1 >= sieves[n].end) siv1 -= sieves[n].p;
     617  2286767274 :       sieves[n].start = siv1;
     618             :     }
     619             :     /* store the contents of the registers back into memory */
     620   207887970 :     surv[0] = reg0;
     621   207887970 :     surv[1] = reg1;
     622   207887970 :     surv[2] = reg2;
     623   207887970 :     surv[3] = reg3;
     624   207887970 :     surv[4] = reg4;
     625   207887970 :     surv[5] = reg5;
     626   207887970 :     surv[6] = reg6;
     627   207887970 :     surv[7] = reg7;
     628   207887970 :     surv[8] = reg8;
     629   207887970 :     surv[9] = reg9;
     630   207887970 :     surv[10] = reg10;
     631   207887970 :     surv[11] = reg11;
     632   207887970 :     surv[12] = reg12;
     633   207887970 :     surv[13] = reg13;
     634   207887970 :     surv[14] = reg14;
     635   207887970 :     surv[15] = reg15;
     636             :   }
     637             : #else /* RATPOINTS_CHUNK not between 2 and 16 */
     638    10895585 :   long range = w_high - w_low;
     639   130746954 :   for (n = 0; n < sp1; n++)
     640             :   {
     641   119851369 :     ratpoints_bit_array *sieve_n = sieves[n].ptr;
     642   119851369 :     long p = sieves[n].p;
     643   119851369 :     long r = mod(-w_low-sieves[n].offset, p);
     644   119851369 :     ratpoints_bit_array *surv = survivors;
     645             : 
     646   119851369 :     if (w_high < w_low + r)
     647             :     { /* if we get here, r > 0, since w_high >= w_low always */
     648     6972178 :       ratpoints_bit_array *siv1 = &sieve_n[p-r];
     649     6972178 :       ratpoints_bit_array *siv0 = siv1 + range;
     650             : 
     651   207983792 :       while (siv1 != siv0) { *surv &= *siv1++; surv++; }
     652             :     }
     653             :     else
     654             :     {
     655   112879191 :       ratpoints_bit_array *siv1 = &sieve_n[p-r];
     656   112879191 :       ratpoints_bit_array *surv_end = &survivors[range - p];
     657             :       long i;
     658  3567574027 :       for (i = r; i; i--) { *surv &= *siv1++; surv++; }
     659   112879191 :       siv1 -= p;
     660   572281051 :       while (surv <= surv_end)
     661             :       {
     662 15773570368 :         for (i = p; i; i--) { *surv &= *siv1++; surv++; }
     663   459401860 :         siv1 -= p;
     664             :       }
     665   112879191 :       surv_end += p;
     666  3645060227 :       while (surv < surv_end) { *surv &= *siv1++; surv++; }
     667             :     }
     668             :   }
     669             :   /* initialize pointers in sieve for the second phase */
     670    97848726 :   for(n = sp1; n < sp2; n++)
     671    86953141 :     sieves[n].start = sieves[n].ptr + mod(w_low + sieves[n].offset, sieves[n].p);
     672             : #endif /* RATPOINTS_CHUNK */
     673             : 
     674             :   /* 2nd phase of the sieve: test each surviving bit array with more primes */
     675    46550975 :   surv0 = &survivors[0];
     676  5418301297 :   for (i = w_low; i < w_high; i++, base++)
     677             :   {
     678  5371752079 :     ratpoints_bit_array nums = *surv0++;
     679  5371752079 :     sieve_spec *ssp = &sieves[sp1];
     680             :     long n;
     681             : 
     682  5870273474 :     for (n = sp2-sp1; n && TEST(nums); n--)
     683             :     {
     684   498521395 :       ratpoints_bit_array *ptr = (ssp->start) + base;
     685   498521395 :       long p = ssp->p;
     686  1325310826 :       while(ptr >= ssp->end) ptr -= p;
     687   498521395 :       nums &= *ptr;
     688   498521395 :       ssp++;
     689             :     }
     690             : 
     691             :     /* Check the survivors of the sieve if they really give points */
     692  5371752079 :     if (TEST(nums))
     693             :     {
     694             :       long a0, a, d;
     695    10790555 :       ulong nums0 = EXT0(nums);
     696             :       /* a will be the numerator corresponding to the selected bit */
     697    10790555 :       if (which_bits == num_all)
     698             :       {
     699     6949351 :         d = 1; a0 = i * RBA_LENGTH;
     700             :       }
     701             :       else
     702             :       {
     703     3841204 :         d = 2; a0 = i * 2 * RBA_LENGTH;
     704     3841204 :         if (which_bits == num_odd) a0++;
     705             :       }
     706   134513795 :       for (a = a0; nums0; a += d, nums0 >>= 1)
     707             :       { /* test one bit */
     708   123724301 :         if (odd(nums0) && ugcd(labs(a), absb)==1)
     709             :         {
     710     1876711 :           if (!args->bc) set_bc(b, args);
     711     1876711 :           nb += _ratpoints_check_point(a, b, args, quit, process, info);
     712     1876711 :           if (*quit) return nb;
     713             :         }
     714             :       }
     715             : #ifdef RBA_USE_VX
     716             :       {
     717     9247380 :         ulong k, da = d<<TWOPOTBITS_IN_LONG;
     718    18494064 :         for (k = 1; k < RBA_PACK; k++)
     719             :         {
     720     9247380 :           ulong nums1 = EXT(nums,k);
     721     9247380 :           a0 += da;
     722   112235190 :           for (a = a0; nums1; a += d, nums1 >>= 1)
     723             :           { /* test one bit */
     724   102988506 :             if (odd(nums1) && ugcd(labs(a), absb)==1)
     725             :             {
     726     1405662 :               if (!args->bc) set_bc(b, args);
     727     1405662 :               nb += _ratpoints_check_point(a, b, args, quit, process, info);
     728     1405662 :               if (*quit) return nb;
     729             :             }
     730             :           }
     731             :         }
     732             :       }
     733             : #endif
     734             :     }
     735             :   }
     736    46549218 :   return nb;
     737             : }
     738             : 
     739             : typedef struct { double r; ratpoints_sieve_entry *ssp; } entry;
     740             : 
     741             : static const int squares16[16] = {1,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0};
     742             :  /* Says if a is a square mod 16, for a = 0..15 */
     743             : 
     744             : /**************************************************************************
     745             :  * Initialization and cleanup of ratpoints_args structure                 *
     746             :  **************************************************************************/
     747             : 
     748             : static ratpoints_sieve_entry*
     749       12428 : alloc_sieve(long nbprime, long maxp)
     750             : {
     751             :   long i;
     752             :   ratpoints_sieve_entry * s = (ratpoints_sieve_entry*)
     753       12428 :                         stack_malloc(nbprime*sizeof(ratpoints_sieve_entry));
     754      385268 :   for (i=0; i<nbprime; i++)
     755      372840 :     s[i].sieve = (ratpoints_bit_array**) new_chunk(maxp);
     756       12428 :   return s;
     757             : }
     758             : 
     759             : /* NOTE: args->degree must be set */
     760             : static void
     761       12428 : find_points_init(ratpoints_args *args, long bit_primes)
     762             : {
     763       12428 :   long need = 0, n, nbprime, maxp;
     764       12428 :   args->listprime = primes_interval_zv(3, 1<<bit_primes);
     765       12428 :   nbprime = lg(args->listprime)-1;
     766       12428 :   maxp = args->listprime[nbprime];
     767             : 
     768             :   /* allocate space for se_buffer */
     769       12428 :   args->se_buffer = alloc_sieve(nbprime, maxp);
     770       12428 :   args->se_next = args->se_buffer;
     771      385268 :   for (n = 1; n <= nbprime; n++)
     772             :   {
     773      372840 :     ulong p = args->listprime[n];
     774      372840 :     need += p*(p + RATPOINTS_CHUNK-1);
     775             :   }
     776       12428 :   args->ba_buffer = (ratpoints_bit_array*)
     777       12428 :      stack_malloc_align(need*RBA_SIZE,RBA_SIZE);
     778       12428 :   args->ba_next = args->ba_buffer;
     779             : 
     780             :   /* allocate space for int_buffer */
     781       12428 :   args->int_buffer = (int *) stack_malloc(nbprime*(maxp+1)*sizeof(int));
     782       12428 :   args->int_next = args->int_buffer;
     783             : 
     784       12428 :   args->forb_ba   = (forbidden_entry*)
     785       12428 :     stack_malloc((nbprime + 1)*sizeof(forbidden_entry));
     786       12428 :   args->forbidden = new_chunk(nbprime + 1);
     787       12428 :   gen_sieve(args);
     788       12428 :   return;
     789             : }
     790             : 
     791             : /* f = leading coeff; b = b1*b2, b1 maximal with (b1, 2*f) = 1;
     792             :  * return Jacobi symbol (f, b1) */
     793             : INLINE int
     794    51429838 : rpjacobi(long b, GEN lcf)
     795             : {
     796             :   ulong f;
     797    51429838 :   b >>= vals(b);
     798    51429838 :   f = umodiu(lcf, b);
     799    51429838 :   return krouu(f, u_ppo(b,f));
     800             : }
     801             : 
     802             : /************************************************************************
     803             :  * Set up information on possible denominators                          *
     804             :  * when polynomial is of odd degree with leading coefficient != +-1     *
     805             :  ************************************************************************/
     806             : 
     807             : static void
     808        1351 : setup_us1(ratpoints_args *args, GEN w0)
     809             : {
     810        1351 :   GEN F = Z_issmooth_fact(w0, 1000), P, E, S, D;
     811             :   long i, l;
     812             : 
     813        1351 :   if (!F) return;
     814        1351 :   P = gel(F,1); l = lg(P);
     815        1351 :   E = gel(F,2);
     816        1351 :   D  = cgetg(1+(1<<(l-1)), t_VECSMALL);
     817             :   /* factorization is complete, set up array of squarefree divisors */
     818        1351 :   D[1] = 1;
     819        2828 :   for (i = 1; i < l; i++)
     820             :   { /* multiply all divisors known so far by next prime */
     821        1477 :     long k, n = 1<<(i-1);
     822        3080 :     for (k=0; k<n; k++) uel(D,1+n+k) = uel(D,1+k) * P[i];
     823             :   }
     824        1351 :   S = cgetg(l, t_VECSMALL);
     825             :   /* set slopes in den_info */
     826        2828 :   for (i = 1; i < l; i++)
     827             :   { /* compute min{n : (d-k)*n > v_p(f_d) - v_p(f_k), k = 0,...,d-1} */
     828        1477 :     GEN c = args->cof;
     829        1477 :     long p = P[i], v = E[i];
     830        1477 :     long k, n = 1, d = degpol(c);
     831             : 
     832        7042 :     for (k = d - 1; k >= 0; k--)
     833             :     {
     834        5565 :       long t = 1 + v - Z_lval(gel(c,k+2), p);
     835        5565 :       long m = CEIL(t, d - k);
     836             : 
     837        5565 :       if (m > n) n = m;
     838             :     }
     839        1477 :     S[i] = n;
     840             :   }
     841        1351 :   args->divisors = D;
     842        1351 :   args->flags |= RATPOINTS_USE_SQUARES1;
     843        1351 :   args->den_info = mkvec3(P, E, S);
     844             : }
     845             : 
     846             : /************************************************************************
     847             :  * Consider 2-adic information                                          *
     848             :  ************************************************************************/
     849             : 
     850             : static bit_selection
     851       12428 : get_2adic_info(ratpoints_args *args, ulong *den_bits,
     852             :                ratpoints_bit_array *num_bits)
     853             : {
     854       12428 :   GEN c = args->cof;
     855       12428 :   long degree = degpol(c);
     856             :   int is_f_square16[24];
     857       12428 :   long *cmp = new_chunk(degree+1);
     858       12428 :   long npe = 0, npo = 0;
     859             :   bit_selection result;
     860             :   long n, a, b;
     861             : 
     862             :   /* compute coefficients mod 16 */
     863       87175 :   for (n = 0; n <= degree; n++) cmp[n] = Mod16(gel(c,n+2));
     864      211276 :   for (a = 0 ; a < 16; a++)
     865             :   {
     866      198848 :     ulong s = cmp[degree];
     867             :     long n;
     868     1195952 :     for (n = degree - 1 ; n >= 0 ; n--) s = s*a + cmp[n];
     869      198848 :     s &= 0xf;
     870      198848 :     if ((is_f_square16[a] = squares16[s])) { if (odd(a)) npo++; else npe++; }
     871             :   }
     872             : 
     873             :   /* even denominators:
     874             :      is_f_square16[16+k] says if f((2k+1)/2) is a square, k = 0..3
     875             :      is_f_square16[20+k] says if f((2k+1)/4) is a square, k = 0,1
     876             :      is_f_square16[22]   says if f(odd/8) is a square
     877             :      is_f_square16[23]   says if f(odd/2^n), n >= 4, can be a square */
     878             :   {
     879       12428 :     long np1 = 0, np2 = 0, np3 = 0, np4 = 0;
     880             : 
     881       12428 :     if (odd(degree))
     882             :     {
     883        1421 :       long a, cf = 4*cmp[degree-1];
     884             : 
     885        1421 :       if (degree >= 2) cf += 8*cmp[degree-2];
     886        7105 :       for (a = 0; a < 4; a++)
     887             :       { /* Compute  2 c[d] k^d + 4 c[d-1] k^(d-1) + 8 c[d-2] k^(d-2), k = 2a+1.
     888             :            Note that k^d = k mod 8, k^(d-1) = 1 mod 8. */
     889        5684 :         long k = 2*a+1;
     890        5684 :         long s = (2*k*cmp[degree] + cf) & 0xf;
     891        5684 :         if ((is_f_square16[16+a] = squares16[s])) np1++;
     892             :       }
     893        1421 :       if ((is_f_square16[20] = squares16[(4*cmp[degree])  & 0xf])) np2++;
     894        1421 :       if ((is_f_square16[21] = squares16[(12*cmp[degree]) & 0xf])) np2++;
     895        1421 :       if ((is_f_square16[22] = squares16[(8*cmp[degree])  & 0xf])) np3++;
     896        1421 :       is_f_square16[23] = 1; np4++;
     897             :     }
     898             :     else
     899             :     {
     900       11007 :       long a, cf = (degree >= 2) ? 4*cmp[degree-2] : 0;
     901             : 
     902       11007 :       if (degree >= 3) cf += 8*cmp[degree-3];
     903       55035 :       for (a = 0; a < 4; a++)
     904             :       { /* compute c[d] k^d + 2 c[d-1] k^(d-1) + ... + 8 c[d-3] k^(d-3),
     905             :            k = 2a+1. Note that k^d = k^2 mod 16, k^(d-1) = k mod 8. */
     906       44028 :         long k = 2*a+1;
     907       44028 :         long s = ((cmp[degree]*k + 2*cmp[degree-1])*k + cf) & 0xf;
     908       44028 :         if ((is_f_square16[16+a] = squares16[s])) np1++;
     909             :       }
     910       11007 :       if ((is_f_square16[20] = squares16[(cmp[degree]+4*cmp[degree-1])  & 0xf]))
     911        4715 :         np2++;
     912       11007 :       if ((is_f_square16[21] = squares16[(cmp[degree]+12*cmp[degree-1]) & 0xf]))
     913        4687 :         np2++;
     914       11007 :       if ((is_f_square16[22] = squares16[(cmp[degree]+8*cmp[degree-1])  & 0xf]))
     915        4561 :         np3++;
     916       11007 :       if ((is_f_square16[23] = squares16[cmp[degree]])) np4++;
     917             :     }
     918             : 
     919             :     /* set den_bits */
     920       12428 :     { ulong db = 0;
     921             :       long i;
     922             : 
     923       12428 :       if (npe + npo > 0) db |= 0xaaaaUL; /* odd denominators */
     924       12428 :       if (np1 > 0)       db |= 0x4444UL; /* v_2(den) = 1 */
     925       12428 :       if (np2 > 0)       db |= 0x1010UL; /* v_2(den) = 2 */
     926       12428 :       if (np3 > 0)       db |= 0x0100UL; /* v_2(den) = 3 */
     927       12428 :       if (np4 > 0)       db |= 0x0001UL; /* v_2(den) >= 4 */
     928       12428 :       if (db == 0)
     929             :       {
     930        2975 :         for (i = 0 ; i < 16; i++) num_bits[i] = RBA(0UL);
     931         175 :         *den_bits = 0UL; return num_none;
     932             :       }
     933       35012 :       for (i = 16; i < BITS_IN_LONG; i <<= 1) db |= db << i;
     934       12253 :       *den_bits = db;
     935             :     }
     936       12253 :     result = (npe == 0) ? (npo == 0) ? num_none : num_odd
     937       12253 :                         : (npo == 0) ? num_even : num_all;
     938             :   }
     939             : 
     940             :   /* set up num_bits[16] */
     941             : 
     942             :   /* odd denominators */
     943       12253 :   switch(result)
     944             :   {
     945        7939 :     case num_all:
     946       71451 :       for (b = 1; b < 16; b += 2)
     947             :       {
     948       63512 :         ulong work = 0, bit = 1;
     949       63512 :         long i, invb = b; /* inverse of b mod 16 */
     950       63512 :         if (b & 2) invb ^= 8;
     951       63512 :         if (b & 4) invb ^= 8;
     952     1079704 :         for (i = 0; i < 16; i++)
     953             :         {
     954     1016192 :           if (is_f_square16[(invb*i) & 0xf]) work |= bit;
     955     1016192 :           bit <<= 1;
     956             :         }
     957             :         /* now repeat the 16 bits */
     958      181504 :         for (i = 16; i < BITS_IN_LONG; i <<= 1) work |= work << i;
     959       63512 :         num_bits[b] = RBA(work);
     960             :       }
     961        7939 :       break;
     962             : 
     963        1842 :     case num_odd:
     964       16578 :       for (b = 1; b < 16; b += 2)
     965             :       {
     966       14736 :         ulong work = 0, bit = 1;
     967       14736 :         long i, invb = b; /* inverse of b mod 16 */
     968       14736 :         if (b & 2) invb ^= 8;
     969       14736 :         if (b & 4) invb ^= 8;
     970      132624 :         for (i = 1; i < 16; i += 2)
     971             :         {
     972      117888 :           if (is_f_square16[(invb*i) & 0xf]) work |= bit;
     973      117888 :           bit <<= 1;
     974             :         }
     975             :         /* now repeat the 8 bits */
     976       56832 :         for (i = 8; i < BITS_IN_LONG; i <<= 1) { work |= work << i; }
     977       14736 :         num_bits[b] = RBA(work);
     978             :       }
     979        1842 :       break;
     980             : 
     981        2059 :     case num_even:
     982       18531 :       for (b = 1; b < 16; b += 2)
     983             :       {
     984       16472 :         ulong work = 0, bit = 1;
     985       16472 :         long i, invb = b; /* inverse of b mod 16 */
     986       16472 :         if (b & 2) invb ^= 8;
     987       16472 :         if (b & 4) invb ^= 8;
     988      148248 :         for (i = 0; i < 16; i += 2)
     989             :         {
     990      131776 :           if (is_f_square16[(invb*i) & 0xf]) work |= bit;
     991      131776 :           bit <<= 1;
     992             :         }
     993             :         /* now repeat the 8 bits */
     994       63528 :         for (i = 8; i < BITS_IN_LONG; i <<= 1) work |= work << i;
     995       16472 :         num_bits[b] = RBA(work);
     996             :       }
     997        2059 :       break;
     998             : 
     999         413 :     case num_none:
    1000        3717 :       for (b = 1; b < 16; b += 2) num_bits[b] = RBA(0UL);
    1001         413 :       break;
    1002             :   }
    1003             : 
    1004             :   /* v_2(den) = 1 : only odd numerators */
    1005       61265 :   for (b = 1; b < 8; b += 2)
    1006             :   {
    1007       49012 :     ulong work = 0, bit = 1;
    1008             :     long i;
    1009      441108 :     for (i = 1; i < 16; i += 2)
    1010             :     {
    1011      392096 :       if (is_f_square16[16 + (((b*i)>>1) & 0x3)]) work |= bit;
    1012      392096 :       bit <<= 1;
    1013             :     }
    1014             :     /* now repeat the 8 bits */
    1015      189060 :     for (i = 8; i < BITS_IN_LONG; i <<= 1) work |= work << i;
    1016       49012 :     num_bits[2*b] = RBA(work);
    1017             :   }
    1018             : 
    1019             :   /* v_2(den) = 2 : only odd numerators */
    1020       36759 :   for (b = 1; b < 4; b += 2)
    1021             :   {
    1022       24506 :     ulong work = 0, bit = 1;
    1023             :     long i;
    1024      122530 :     for (i = 1; i < 8; i += 2)
    1025             :     {
    1026       98024 :       if (is_f_square16[20 + (((b*i)>>1) & 0x1)]) work |= bit;
    1027       98024 :       bit <<= 1;
    1028             :     }
    1029             :     /* now repeat the 4 bits */
    1030      119036 :     for (i = 4; i < BITS_IN_LONG; i <<= 1) work |= work << i;
    1031       24506 :     num_bits[4*b] = RBA(work);
    1032             :   }
    1033             : 
    1034             :   /* v_2(den) = 3, >= 4 : only odd numerators */
    1035       12253 :   num_bits[8] = (is_f_square16[22]) ? RBA(~(0UL)) : RBA(0UL);
    1036       12253 :   num_bits[0] = (is_f_square16[23]) ? RBA(~(0UL)) : RBA(0UL);
    1037             : 
    1038       12253 :   return result;
    1039             : }
    1040             : 
    1041             : /**************************************************************************
    1042             :  * This is a comparison function needed for sorting in order to determine *
    1043             :  * the `best' primes for sieving.                                         *
    1044             :  **************************************************************************/
    1045             : 
    1046             : static int
    1047     1171606 : compare_entries(const void *a, const void *b)
    1048             : {
    1049     1171606 :   double diff = ((entry *)a)->r - ((entry *)b)->r;
    1050     1171606 :   return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
    1051             : }
    1052             : 
    1053             : /************************************************************************
    1054             :  * Collect the sieving information                                      *
    1055             :  ************************************************************************/
    1056             : 
    1057             : static long
    1058       12428 : sieving_info(ratpoints_args *args,
    1059             :              ratpoints_sieve_entry **sieve_list)
    1060             : {
    1061       12428 :   GEN c = args->cof;
    1062       12428 :   GEN inverses = args->inverses, squares;
    1063       12428 :   GEN offsets = args->offsets;
    1064       12428 :   ulong ** sieves0 = args->sieves0;
    1065       12428 :   long degree = degpol(c);
    1066       12428 :   long fba = 0, fdc = 0;
    1067       12428 :   long pn, pnp = 0;
    1068             :   long n;
    1069       12428 :   long nbprime = lg(args->listprime)-1;
    1070             :   long * coeffs_mod_p;
    1071       12428 :   entry *prec = (entry*) stack_malloc(nbprime*sizeof(entry));
    1072             :     /* This array is used for sorting in order to
    1073             :        determine the `best' sieving primes. */
    1074             : 
    1075       12428 :   forbidden_entry *forb_ba = args->forb_ba;
    1076       12428 :   long *forbidden = args->forbidden;
    1077       12428 :   ulong bound = (1UL)<<(BITS_IN_LONG - args->bit_primes);
    1078       12428 :   pari_sp av = avma;
    1079       12428 :   squares = gen_squares(args->listprime);
    1080       12428 :   coeffs_mod_p = (long *) new_chunk(degree+1);
    1081             :   /* initialize sieve in se_buffer */
    1082      381537 :   for (pn = 1; pn <= args->num_primes; pn++)
    1083             :   {
    1084      369235 :     ulong a, p = args->listprime[pn], np;
    1085             :     long n;
    1086      369235 :     int *is_f_square = args->int_next;
    1087             : 
    1088      369235 :     args->int_next += p + 1; /* need space for (p+1) int's */
    1089             : 
    1090             :     /* compute coefficients mod p */
    1091     2586410 :     for (n = 0; n <= degree; n++) coeffs_mod_p[n] = umodiu(pel(c,n), p);
    1092             : 
    1093      369235 :     np = umael(squares,pn,coeffs_mod_p[0]+1);
    1094      369235 :     is_f_square[0] = np;
    1095    21135487 :     for (a = 1 ; a < p; a++)
    1096             :     {
    1097    20766252 :       ulong s = coeffs_mod_p[degree];
    1098    20766252 :       if ((degree+1)*args->bit_primes <= BITS_IN_LONG)
    1099             :       {
    1100   107791784 :         for (n = degree - 1 ; n >= 0 ; n--) s = s*a + coeffs_mod_p[n];
    1101             :         /* here, s < p^(degree+1) <= max. long */
    1102    18028248 :         s %= p;
    1103             :       }
    1104             :       else
    1105             :       {
    1106    16895668 :         for (n = degree - 1 ; n >= 0 ; n--)
    1107             :         {
    1108    14157664 :           s = s*a + coeffs_mod_p[n];
    1109    14157664 :           if (s+1 >= bound) s %= p;
    1110             :         }
    1111     2738004 :         s %= p;
    1112             :       }
    1113    20766252 :       if ((is_f_square[a] = mael(squares,pn,s+1))) np++;
    1114             :     }
    1115      369235 :     is_f_square[p] = odd(degree) || mael(squares,pn,coeffs_mod_p[degree]+1);
    1116             : 
    1117             :     /* check if there are no solutions mod p */
    1118      369235 :     if (np == 0 && !is_f_square[p]) return gc_long(av,p);
    1119             : 
    1120             :     /* Fill arrays with info for p */
    1121      369109 :     if (np < p)
    1122             :     { /* only when there is some information */
    1123             :       ulong i;
    1124      336357 :       ratpoints_sieve_entry *se = args->se_next;
    1125      862442 :       double r = is_f_square[p] ? ((double)(np*(p-1) + p))/((double)(p*p))
    1126      336357 :                                 : (double)np/(double)p;
    1127      336357 :       prec[pnp].r = r;
    1128      336357 :       args->se_next ++;
    1129      336357 :       se->p = p;
    1130      336357 :       se->is_f_square = is_f_square;
    1131      336357 :       se->inverses = gel(inverses,pn);
    1132      336357 :       se->offset = offsets[pn];
    1133      336357 :       se->sieve[0] = (ratpoints_bit_array *)sieves0[pn];
    1134    20237033 :       for (i = 1; i < p; i++) se->sieve[i] = NULL;
    1135      336357 :       prec[pnp].ssp = se;
    1136      336357 :       pnp++;
    1137             :     }
    1138             : 
    1139      369109 :     if ((args->flags & RATPOINTS_CHECK_DENOM)
    1140      321859 :          && fba + fdc < args->max_forbidden
    1141      321859 :          && !is_f_square[p])
    1142             :     { /* record forbidden divisors of the denominator */
    1143      148043 :       if (coeffs_mod_p[degree] == 0)
    1144             :       { /* leading coeff. divisible by p */
    1145             :         GEN r;
    1146           0 :         long v = Z_lvalrem(pel(c,degree), p, &r);
    1147             : 
    1148           0 :         if (odd(v) || !mael(squares,pn, umodiu(r,p)+1))
    1149             :         { /* Can only get something when valuation is odd
    1150             :              or when valuation is even and lcf is not a p-adic square.
    1151             :              Compute smallest n such that if v(den) >= n, the leading
    1152             :              term determines the valuation. Then we must have v(den) < n. */
    1153           0 :           long k, n = 1;
    1154           0 :           for (k = degree-1; k >= 0; k--)
    1155             :           {
    1156           0 :             if (coeffs_mod_p[k] == 0)
    1157             :             {
    1158           0 :               long t = 1 + v - Z_lval(pel(c,k), p);
    1159           0 :               long m = CEIL(t, (degree-k));
    1160           0 :               if (m > n) n = m;
    1161             :             }
    1162             :           }
    1163           0 :           if (n == 1)
    1164             :           {
    1165           0 :             forb_ba[fba].p     = p;
    1166           0 :             forb_ba[fba].start = sieves0[pn];
    1167           0 :             forb_ba[fba].end   = sieves0[pn]+p;
    1168           0 :             forb_ba[fba].curr  = forb_ba[fba].start;
    1169           0 :             fba++;
    1170             :           }
    1171             :           else
    1172             :           {
    1173           0 :             forbidden[fdc] = upowuu(p, n);
    1174           0 :             fdc++;
    1175             :           }
    1176             :         }
    1177             :       }
    1178             :       else /* leading coefficient is a nonsquare mod p */
    1179             :       { /* denominator divisible by p is excluded */
    1180      148043 :         forb_ba[fba].p     = p;
    1181      148043 :         forb_ba[fba].start = sieves0[pn];
    1182      148043 :         forb_ba[fba].end   = sieves0[pn]+p;
    1183      148043 :         forb_ba[fba].curr  = forb_ba[fba].start;
    1184      148043 :         fba++;
    1185             :       }
    1186             :     }
    1187             :   } /* end for pn */
    1188             : 
    1189             :   /* update sp2 and sp1 if necessary */
    1190       12302 :   if (args->sp2 > pnp)       args->sp2 = pnp;
    1191       12302 :   if (args->sp1 > args->sp2) args->sp1 = args->sp2;
    1192             : 
    1193             :   /* sort the array to get at the best primes */
    1194       12302 :   qsort(prec, pnp, sizeof(entry), compare_entries);
    1195             : 
    1196             :   /* put the sorted entries into sieve_list */
    1197      245578 :   for (n = 0; n < args->sp2; n++) sieve_list[n] = prec[n].ssp;
    1198             : 
    1199             :   /* terminate array of forbidden divisors */
    1200       12302 :   if (args->flags & RATPOINTS_CHECK_DENOM)
    1201             :   {
    1202             :     long n;
    1203             : 
    1204       10727 :     for (n = args->num_primes+1;
    1205       10727 :         fba + fdc < args->max_forbidden && n <= nbprime; n++)
    1206             :     {
    1207           0 :       ulong p = args->listprime[n];
    1208             : 
    1209           0 :       if (p*p > (ulong) args->b_high) break;
    1210           0 :       if (kroiu(pel(c,degree), p) == -1)
    1211             :       {
    1212           0 :         forb_ba[fba].p     = p;
    1213           0 :         forb_ba[fba].start = sieves0[n];
    1214           0 :         forb_ba[fba].end   = sieves0[n]+p;
    1215           0 :         forb_ba[fba].curr  = forb_ba[fba].start;
    1216           0 :         fba++;
    1217             :       }
    1218             :     }
    1219       10727 :     forb_ba[fba].p = 0; /* terminating zero */
    1220       10727 :     forbidden[fdc] = 0; /* terminating zero */
    1221       10727 :     args->max_forbidden = fba + fdc; /* note actual number */
    1222             :   }
    1223             : 
    1224       12302 :   if (fba + fdc == 0) args->flags &= ~RATPOINTS_CHECK_DENOM;
    1225       12302 :   return gc_long(av,0);
    1226             : }
    1227             : 
    1228             : /**************************************************************************
    1229             :  * The sieving procedure itself                                           *
    1230             :  **************************************************************************/
    1231             : static void
    1232    31921627 : sift(long b, ratpoints_bit_array *survivors, ratpoints_args *args,
    1233             :      bit_selection which_bits, ratpoints_bit_array bits16,
    1234             :      ratpoints_sieve_entry **sieve_list, long *bp_list, int *quit,
    1235             :      int process(long, long, GEN, void*, int*), void *info)
    1236             : {
    1237    31921627 :   pari_sp av = avma;
    1238    31921627 :   int do_setup = 1;
    1239    31921627 :   long k, height = args->height, nb;
    1240    31921627 :   sieve_spec *ssp = (sieve_spec *) stack_malloc(args->sp2*sizeof(sieve_spec));
    1241             : 
    1242    31921627 :   if (odd(b) == 0) which_bits = num_odd; /* even denominator */
    1243             : 
    1244             :   /* Note that b is new */
    1245    31921627 :   args->bc = NULL;
    1246    31921627 :   nb = 0;
    1247             : 
    1248    75778222 :   for (k = 0; k < args->num_inter; k++)
    1249             :   {
    1250    47850070 :     ratpoints_interval inter = args->domain[k];
    1251             :     long low, high;
    1252             : 
    1253             :     /* Determine relevant interval [low, high] of numerators. */
    1254    47850070 :     if (b*inter.low <= -height)
    1255    24074646 :       low = -height;
    1256             :     else
    1257             :     {
    1258    23775424 :       if (b*inter.low > height) break;
    1259    19783706 :       low = ceil(b*inter.low);
    1260             :     }
    1261    43858352 :     if (b*inter.up >= height)
    1262    19682387 :       high = height;
    1263             :     else
    1264             :     {
    1265    24175965 :       if (b*inter.up < -height) continue;
    1266    20259631 :       high = floor(b*inter.up);
    1267             :     }
    1268             : 
    1269    39942018 :     if (do_setup)
    1270             :     { /* set up the sieve information */
    1271             :       long n;
    1272             : 
    1273    29574009 :       do_setup = 0; /* only do it once for every b */
    1274   591086500 :       for (n = 0; n < args->sp2; n++)
    1275             :       {
    1276   561512491 :         ratpoints_sieve_entry *se = sieve_list[n];
    1277   561512491 :         long p = se->p;
    1278   561512491 :         long bp = bp_list[n];
    1279             :         ratpoints_bit_array *sptr;
    1280             : 
    1281   561512491 :         if (which_bits != num_all) /* divide by 2 mod p */
    1282   322763170 :           bp = odd(bp) ? (bp+p) >> 1 : bp >> 1;
    1283   561512491 :         sptr = se->sieve[bp];
    1284             : 
    1285   561512491 :         ssp[n].p = p;
    1286   561512491 :         ssp[n].offset = (which_bits == num_odd) ? se->offset : 0;
    1287             : 
    1288             :         /* copy if already initialized, else initialize */
    1289   574189119 :         ssp[n].ptr = sptr ? sptr : (p<BITS_IN_LONG?sieve_init1(p, se, bp, args)
    1290    12676628 :                                                   :sieve_init2(p, se, bp, args));
    1291   561512491 :         ssp[n].start = ssp[n].ptr;
    1292   561512491 :         ssp[n].end = ssp[n].ptr + p;
    1293             : 
    1294             :       }
    1295             :     }
    1296             : 
    1297    39942018 :     switch(which_bits)
    1298             :     {
    1299    17083285 :       case num_all: break;
    1300           0 :       case num_none: break;
    1301    18217195 :       case num_odd: low >>= 1; high--; high >>= 1; break;
    1302     4641538 :       case num_even: low++; low >>= 1; high >>= 1; break;
    1303             :     }
    1304             : 
    1305             :     /* now turn the bit interval into [low, high[ */
    1306    39942018 :     high++;
    1307             : 
    1308    39942018 :     if (low < high)
    1309             :     {
    1310    39939892 :       long w_low, w_high, w_low0, w_high0, range = args->array_size;
    1311             : 
    1312             :       /* Now the range of longwords (= bit_arrays) */
    1313    39939892 :       w_low = low >> RBA_SHIFT;
    1314    39939892 :       w_high = (high + (long)(RBA_LENGTH-1)) >> RBA_SHIFT;
    1315    39939892 :       w_low0 = w_low;
    1316    39939892 :       w_high0 = w_low0 + range;
    1317    86489110 :       for ( ; w_low0 < w_high; w_low0 = w_high0, w_high0 += range)
    1318             :       {
    1319             :         long i;
    1320    46550975 :         if (w_high0 > w_high) { w_high0 = w_high; range = w_high0 - w_low0; }
    1321             :         /* initialise the bits */
    1322  5205242181 :         for (i = range; i; i--) survivors[i-1] = bits16;
    1323             :         /* boundary words */
    1324    46550975 :         if (w_low0 == w_low)
    1325    39939892 :           MASKL(survivors,low - RBA_LENGTH * w_low)
    1326    46550975 :         if (w_high0 == w_high)
    1327    39939748 :           MASKU(&survivors[range-1], RBA_LENGTH * w_high - high)
    1328             : 
    1329             : #if (RATPOINTS_CHUNK > 1)
    1330   248813166 :         while(range%RATPOINTS_CHUNK != 0)
    1331   213157776 :           { survivors[range] = RBA(0); range++; w_high0++; }
    1332             : #endif
    1333    46550975 :         nb += _ratpoints_sift0(b, w_low0, w_high0, args, which_bits,
    1334             :                          survivors, &ssp[0], quit, process, info);
    1335    46550975 :         if (*quit) return;
    1336             :       }
    1337             :     }
    1338             :   }
    1339    31919870 :   if (nb==0) set_avma(av);
    1340             : }
    1341             : 
    1342             : /**************************************************************************
    1343             :  * Find points by looping over the denominators and sieving numerators    *
    1344             :  **************************************************************************/
    1345             : static void
    1346       12428 : find_points_work(ratpoints_args *args,
    1347             :                  int process(long, long, GEN, void*, int*), void *info)
    1348             : {
    1349       12428 :   int quit = 0;
    1350       12428 :   GEN c = args->cof;
    1351       12428 :   long degree = degpol(c);
    1352       12428 :   long nbprime = lg(args->listprime)-1;
    1353       12428 :   long height = args->height;
    1354             : 
    1355       12428 :   int point_at_infty = 0; /* indicates if there are points at infinity */
    1356       12428 :   int lcfsq = Z_issquare(pel(c,degree));
    1357             : 
    1358       12428 :   forbidden_entry *forb_ba = args->forb_ba;
    1359       12428 :   long *forbidden = args->forbidden;
    1360             :     /* The forbidden divisors, a zero-terminated array.
    1361             :        Used when degree is even and leading coefficient is not a square */
    1362             : 
    1363             :     /* These are used when degree is odd and leading coeff. is not +-1 */
    1364             : 
    1365             :   ratpoints_sieve_entry **sieve_list = (ratpoints_sieve_entry**)
    1366       12428 :      stack_malloc(nbprime*sizeof(ratpoints_sieve_entry*));
    1367       12428 :   bit_selection which_bits = num_all;
    1368             :   ulong den_bits;
    1369             :   ratpoints_bit_array num_bits[16];
    1370             : 
    1371       12428 :   args->flags &= RATPOINTS_FLAGS_INPUT_MASK;
    1372       12428 :   args->flags |= RATPOINTS_CHECK_DENOM;
    1373             : 
    1374             :   /* initialize memory management */
    1375       12428 :   args->se_next = args->se_buffer;
    1376       12428 :   args->ba_next = args->ba_buffer;
    1377       12428 :   args->int_next = args->int_buffer;
    1378             : 
    1379             :   /* Some sanity checks */
    1380       12428 :   args->num_inter = 0;
    1381             : 
    1382       12428 :   if (args->num_primes > nbprime) args->num_primes = nbprime;
    1383       12428 :   if (args->sp2 > args->num_primes) args->sp2 = args->num_primes;
    1384       12428 :   if (args->sp1 > args->sp2)        args->sp1 = args->sp2;
    1385             : 
    1386       12428 :   if (args->b_low < 1)  args->b_low = 1;
    1387       12428 :   if (args->b_high < 1) args->b_high = height;
    1388       12428 :   if (args->max_forbidden < 0)
    1389           0 :     args->max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN;
    1390       12428 :   if (args->max_forbidden > nbprime)
    1391           0 :     args->max_forbidden = nbprime;
    1392       12428 :   if (args->array_size <= 0) args->array_size = RATPOINTS_ARRAY_SIZE;
    1393             :   {
    1394       12428 :     long s = 2*maxss(1,CEIL(height, BITS_IN_LONG));
    1395       12428 :     if (args->array_size > s) args->array_size = s;
    1396             :   }
    1397             :   /* make sure that array size is a multiple of RATPOINTS_CHUNK */
    1398       12428 :   args->array_size = CEIL(args->array_size, RATPOINTS_CHUNK)*RATPOINTS_CHUNK;
    1399             : 
    1400             :   /* Don't reverse if intervals are specified or limits for the denominator
    1401             :      are given */
    1402       12428 :   if (args->num_inter > 0 || args->b_low > 1 || args->b_high != height)
    1403          35 :     args->flags |= RATPOINTS_NO_REVERSE;
    1404             : 
    1405             :   /* Check if reversal of polynomial might be better:
    1406             :    * case 1: degree is even, but trailing coefficient is zero
    1407             :    * case 2: degree is even, leading coefficient is a square, but
    1408             :    *         trailing coefficient is not
    1409             :    * case 3: degree is odd, |leading coefficient| > 1,
    1410             :    *         trailing coefficient is zero, |coeff. of x| = 1 */
    1411       12428 :   if (!(args->flags & RATPOINTS_NO_REVERSE))
    1412             :   {
    1413       12393 :     if (!odd(degree) && degree>0)
    1414             :     {
    1415       11210 :       if (signe(pel(c,0)) == 0 && signe(pel(c,1))!=0)
    1416         224 :       { /* case 1 */
    1417             :         long n;
    1418         224 :         args->flags |= RATPOINTS_REVERSED;
    1419         896 :         for (n = 0; n < degree>>1; n++) swap(pel(c,n), pel(c,degree-n));
    1420         224 :         degree--;
    1421         224 :         setlg(c,degree+3);
    1422             :       }
    1423       10986 :       else if (lcfsq && !Z_issquare(pel(c,0)))
    1424             :       { /* case 2 */
    1425             :         long n;
    1426         735 :         args->flags |= RATPOINTS_REVERSED;
    1427        2940 :         for (n = 0; n < degree>>1; n++) swap(pel(c,n), pel(c,degree-n));
    1428         735 :         lcfsq = 0;
    1429             :       }
    1430             :     }
    1431             :     else
    1432             :     { /* odd degree, case 3*/
    1433        1183 :       if (!is_pm1(pel(c,degree)) && !signe(pel(c,0)) && is_pm1(pel(c,1)))
    1434             :       {
    1435             :         long n;
    1436           7 :         args->flags |= RATPOINTS_REVERSED;
    1437          21 :         for (n = 1; n <= degree>>1; n++) swap(pel(c,n),pel(c,degree+1-n));
    1438             :       }
    1439             :     }
    1440             :   }
    1441             : 
    1442             :   /* Deal with the intervals */
    1443       12428 :   if (args->num_inter == 0)
    1444             :   { /* default interval (effectively ]-oo,oo[) if none is given */
    1445       12428 :     args->domain = (ratpoints_interval*) stack_malloc(2*degree*sizeof(ratpoints_interval));
    1446       12428 :     args->domain[0].low = -height; args->domain[0].up = height;
    1447       12428 :     args->num_inter = 1;
    1448             :   }
    1449             : 
    1450       12428 :   ratpoints_compute_sturm(args);
    1451             : 
    1452             :   /* Point(s) at infinity? */
    1453       12428 :   if (odd(degree) || lcfsq)
    1454             :   {
    1455        1575 :     args->flags &= ~RATPOINTS_CHECK_DENOM;
    1456        1575 :     point_at_infty = 1;
    1457             :   }
    1458             : 
    1459             :   /* Can use only squares as denoms if degree is odd and poly is +-monic */
    1460       12428 :   if (odd(degree))
    1461             :   {
    1462        1421 :     GEN w1 = pel(c,degree);
    1463        1421 :     if (is_pm1(w1))
    1464          70 :       args->flags |= RATPOINTS_USE_SQUARES;
    1465             :     else /* set up information on divisors of leading coefficient */
    1466        1351 :       setup_us1(args, absi_shallow(w1));
    1467             :   }
    1468             : 
    1469             :   /* deal with f mod powers of 2 */
    1470       12428 :   which_bits = get_2adic_info(args, &den_bits, &num_bits[0]);
    1471             :   /* which_bits says whether to consider even and/or odd numerators
    1472             :    * when the denominator is odd.
    1473             :    *
    1474             :    * Bit k in den_bits is 0 if b congruent to k mod BITS_IN_LONG need
    1475             :    * not be considered as a denominator.
    1476             :    *
    1477             :    * Bit k in num_bits[b] is 0 is numerators congruent to
    1478             :    *  k (which_bits = den_all)
    1479             :    *  2k (which_bits = den_even)
    1480             :    *  2k+1 (which_bits = den_odd)
    1481             :    * need not be considered for denominators congruent to b mod 16. */
    1482             : 
    1483             :   /* set up the sieve data structure */
    1484       12428 :   if (sieving_info(args, sieve_list)) return;
    1485             : 
    1486             :   /* deal with point(s) at infinity */
    1487       12302 :   if (point_at_infty)
    1488             :   {
    1489        1575 :     long a = 1, b = 0;
    1490             : 
    1491        1575 :     if (args->flags & RATPOINTS_REVERSED) { a = 0; b = 1; }
    1492        1575 :     if (odd(degree))
    1493        1421 :       (void)process(a, b, gen_0, info, &quit);
    1494             :     else
    1495             :     {
    1496         154 :       GEN w0 = sqrti(pel(c,degree));
    1497         154 :       (void)process(a, b, w0, info, &quit);
    1498         154 :       (void)process(a, b, negi(w0), info, &quit);
    1499             :     }
    1500        1575 :     if (quit) return;
    1501             :   }
    1502             :   /* now do the sieving */
    1503             :   {
    1504             :     ratpoints_bit_array *survivors = (ratpoints_bit_array *)
    1505       12302 :       stack_malloc_align((args->array_size)*RBA_SIZE, RBA_SIZE);
    1506       12302 :     long *bp_list = (long *) new_chunk(args->sp2);
    1507       12302 :     if (args->flags & (RATPOINTS_USE_SQUARES | RATPOINTS_USE_SQUARES1))
    1508             :     {
    1509        1421 :       if (args->flags & RATPOINTS_USE_SQUARES)
    1510             :       /* need only take squares as denoms */
    1511             :       {
    1512             :         long b, bb;
    1513          70 :         long last_b = args->b_low;
    1514             :         long n;
    1515        1400 :         for (n = 0; n < args->sp2; n++)
    1516        1330 :           bp_list[n] = mod(args->b_low, sieve_list[n]->p);
    1517             : 
    1518        8771 :         for (b = 1; bb = b*b, bb <= args->b_high; b++)
    1519        8701 :           if (bb >= args->b_low)
    1520             :           {
    1521        8701 :             ratpoints_bit_array bits = num_bits[bb & 0xf];
    1522        8701 :             if (TEST(bits))
    1523             :             {
    1524             :               long n;
    1525        7805 :               long d = bb - last_b;
    1526             : 
    1527             :               /* fill bp_list */
    1528      156100 :               for (n = 0; n < args->sp2; n++)
    1529      148295 :                 bp_list[n] = mod(bp_list[n] + d, sieve_list[n]->p);
    1530        7805 :               last_b = bb;
    1531             : 
    1532        7805 :               sift(bb, survivors, args, which_bits, bits,
    1533             :                    sieve_list, &bp_list[0], &quit, process, info);
    1534        7805 :               if (quit) break;
    1535             :             }
    1536             :           }
    1537             :       }
    1538             :       else /* args->flags & RATPOINTS_USE_SQUARES1 */
    1539             :       {
    1540        1351 :         GEN den_info = args->den_info;
    1541        1351 :         GEN divisors = args->divisors;
    1542        1351 :         long ld = lg(divisors);
    1543             :         long k;
    1544             :         long b, bb;
    1545             : 
    1546        4291 :         for (k = 1; k < ld; k++)
    1547             :         {
    1548        2947 :           long d = divisors[k];
    1549        2947 :           long last_b = d;
    1550             :           long n;
    1551        2947 :           if (d > args->b_high) continue;
    1552       58800 :           for (n = 0; n < args->sp2; n++)
    1553       55860 :             bp_list[n] = mod(d, sieve_list[n]->p);
    1554             : 
    1555      279097 :           for (b = 1; bb = d*b*b, bb <= args->b_high; b++)
    1556             :           {
    1557      276164 :             if (bb >= args->b_low)
    1558             :             {
    1559      276143 :               int flag = 1;
    1560      276143 :               ratpoints_bit_array bits = num_bits[bb & 0xf];
    1561             : 
    1562      276143 :               if (EXT0(bits))
    1563             :               {
    1564      227801 :                 long i, n, l = lg(gel(den_info,1));
    1565      227801 :                 long d = bb - last_b;
    1566             : 
    1567             :                 /* fill bp_list */
    1568     4556020 :                 for (n = 0; n < args->sp2; n++)
    1569     4328219 :                   bp_list[n] = mod(bp_list[n] + d, sieve_list[n]->p);
    1570      227801 :                 last_b = bb;
    1571             : 
    1572      431893 :                 for(i = 1; i < l; i++)
    1573             :                 {
    1574      256088 :                   long v = z_lval(bb, mael(den_info,1,i));
    1575      256088 :                   if((v >= mael(den_info,3,i))
    1576      124089 :                       && odd(v + (mael(den_info,2,i)))) { flag = 0; break; }
    1577             :                 }
    1578      227801 :                 if (flag)
    1579             :                 {
    1580      175805 :                   sift(bb, survivors, args, which_bits, bits,
    1581             :                        sieve_list, &bp_list[0], &quit, process, info);
    1582      175805 :                   if (quit) break;
    1583             :                 }
    1584             :               }
    1585             :             }
    1586             :           }
    1587        2940 :           if (quit) break;
    1588             :         }
    1589             :       }
    1590             :     }
    1591             :     else
    1592             :     {
    1593       10881 :       if (args->flags & RATPOINTS_CHECK_DENOM)
    1594             :       {
    1595             :         long *forb;
    1596             :         long b;
    1597       10727 :         long last_b = args->b_low;
    1598             :         ulong b_bits;
    1599             :         long n;
    1600      214211 :         for (n = 0; n < args->sp2; n++)
    1601      203484 :           bp_list[n] = mod(args->b_low, sieve_list[n]->p);
    1602             :         {
    1603       10727 :           forbidden_entry *fba = &forb_ba[0];
    1604       10727 :           long b_low = args->b_low;
    1605       10727 :           long w_low = (b_low-1) >> TWOPOTBITS_IN_LONG;
    1606             : 
    1607       10727 :           b_bits = den_bits;
    1608      158756 :           while (fba->p)
    1609             :           {
    1610      148029 :             fba->curr = fba->start + mod(w_low, fba->p);
    1611      148029 :             b_bits &= *(fba->curr);
    1612      148029 :             fba++;
    1613             :           }
    1614       10727 :           b_bits >>= (b_low-1) & LONG_MASK;
    1615             :         }
    1616             : 
    1617   135533359 :         for (b = args->b_low; b <= args->b_high; b++)
    1618             :         {
    1619   135524375 :           ratpoints_bit_array bits = num_bits[b & 0xf];
    1620             : 
    1621   135524375 :           if ((b & LONG_MASK) == 0)
    1622             :           { /* next b_bits */
    1623     2411862 :             forbidden_entry *fba = &forb_ba[0];
    1624             : 
    1625     2411862 :             b_bits = den_bits;
    1626    37831362 :             while (fba->p)
    1627             :             {
    1628    35419500 :               fba->curr++;
    1629    35419500 :               if (fba->curr == fba->end) fba->curr = fba->start;
    1630    35419500 :               b_bits &= *(fba->curr);
    1631    35419500 :               fba++;
    1632             :             }
    1633             :           }
    1634             :           else
    1635   133112513 :             b_bits >>= 1;
    1636             : 
    1637   135524375 :           if (odd(b_bits) && EXT0(bits))
    1638             :           { /* check if denominator is excluded */
    1639    51429838 :             for (forb = &forbidden[0] ; *forb && (b % (*forb)); forb++)
    1640           0 :               continue;
    1641    51429838 :             if (*forb == 0 && rpjacobi(b, pel(c,degree)) == 1)
    1642             :             {
    1643    30060768 :               long n, d = b - last_b;
    1644             : 
    1645             :               /* fill bp_list */
    1646   600822079 :               for (n = 0; n < args->sp2; n++)
    1647             :               {
    1648   570761311 :                 long bp = bp_list[n] + d;
    1649   570761311 :                 long p = sieve_list[n]->p;
    1650             : 
    1651   641901231 :                 while (bp >= p) bp -= p;
    1652   570761311 :                 bp_list[n] = bp;
    1653             :               }
    1654    30060768 :               last_b = b;
    1655             : 
    1656    30060768 :               sift(b, survivors, args, which_bits, bits,
    1657             :                    sieve_list, &bp_list[0], &quit, process, info);
    1658    30060768 :               if (quit) break;
    1659             :             }
    1660             :           }
    1661             :         }
    1662             :       } /* if (args->flags & RATPOINTS_CHECK_DENOM) */
    1663             :       else
    1664             :       {
    1665             :         long b, n;
    1666         154 :         long last_b = args->b_low;
    1667        2947 :         for (n = 0; n < args->sp2; n++)
    1668        2793 :           bp_list[n] = mod(args->b_low, sieve_list[n]->p);
    1669     2179184 :         for (b = args->b_low; b <= args->b_high; b++)
    1670             :         {
    1671     2179037 :           ratpoints_bit_array bits = num_bits[b & 0xf];
    1672     2179037 :           if (EXT0(bits))
    1673             :           {
    1674             :             long n;
    1675     1677249 :             long d = b - last_b;
    1676             : 
    1677             :             /* fill bp_list */
    1678    33544581 :             for (n = 0; n < args->sp2; n++)
    1679             :             {
    1680    31867332 :               long bp = bp_list[n] + d;
    1681    31867332 :               long p = sieve_list[n]->p;
    1682             : 
    1683    32980773 :               while (bp >= p) bp -= p;
    1684    31867332 :               bp_list[n] = bp;
    1685             :             }
    1686     1677249 :             last_b = b;
    1687             : 
    1688     1677249 :             sift(b, survivors, args, which_bits, bits,
    1689             :                  sieve_list, &bp_list[0], &quit, process, info);
    1690     1677249 :             if (quit) break;
    1691             :           }
    1692             :         }
    1693             :       }
    1694             :     }
    1695             :   }
    1696             : }
    1697             : 
    1698             : static GEN
    1699       86198 : vec_append_grow(GEN z, long i, GEN x)
    1700             : {
    1701       86198 :   long n = lg(z)-1;
    1702       86198 :   if (i > n)
    1703             :   {
    1704        1435 :     n <<= 1;
    1705        1435 :     z = vec_lengthen(z,n);
    1706             :   }
    1707       86198 :   gel(z,i) = x;
    1708       86198 :   return z;
    1709             : }
    1710             : 
    1711             : struct points
    1712             : {
    1713             :   GEN z;
    1714             :   long i, f;
    1715             : };
    1716             : 
    1717             : static int
    1718       89229 : process(long a, long b, GEN y, void *info0, int *quit)
    1719             : {
    1720       89229 :   struct points *p = (struct points *) info0;
    1721       89229 :   if (b==0 && (p->f&2L)) return 0;
    1722       86198 :   *quit = (p->f&1);
    1723       86198 :   p->z = vec_append_grow(p->z, ++p->i, mkvec3(stoi(a),y,stoi(b)));
    1724       86198 :   return 1;
    1725             : }
    1726             : 
    1727             : static int
    1728       12435 : args_h(ratpoints_args *args, GEN D)
    1729             : {
    1730       12435 :   long H, h, l = 1;
    1731             :   GEN L;
    1732       12435 :   switch(typ(D))
    1733             :   {
    1734       12393 :     case t_INT: if (signe(D) <= 0) return 0;
    1735       12393 :       H = h = itos(D); break;
    1736          42 :     case t_VEC: if (lg(D) != 3) return 0;
    1737          42 :       H = gtos(gel(D,1));
    1738          42 :       L = gel(D,2);
    1739          42 :       if (typ(L)==t_INT) { h = itos(L); break; }
    1740          14 :       if (typ(L)==t_VEC && lg(L)==3)
    1741             :       {
    1742           7 :         l = gtos(gel(L,1));
    1743           7 :         h = gtos(gel(L,2)); break;
    1744             :       }
    1745           7 :     default: return 0;
    1746             :   }
    1747       12428 :   args->height = H;
    1748       12428 :   args->b_low  = l;
    1749       12428 :   args->b_high = h; return 1;
    1750             : }
    1751             : 
    1752             : static GEN
    1753       12435 : ZX_hyperellratpoints(GEN P, GEN h, long flag)
    1754             : {
    1755       12435 :   pari_sp av = avma;
    1756             :   ratpoints_args args;
    1757             :   struct points data;
    1758       12435 :   ulong flags = 0;
    1759             : 
    1760       12435 :   if (!args_h(&args, h))
    1761             :   {
    1762           7 :     pari_err_TYPE("hyperellratpoints", h);
    1763             :     return NULL;/*LCOV_EXCL_LINE*/
    1764             :   }
    1765       12428 :   find_points_init(&args, RATPOINTS_DEFAULT_BIT_PRIMES);
    1766             : 
    1767       12428 :   args.cof           = shallowcopy(P);
    1768       12428 :   args.num_inter     = 0;
    1769       12428 :   args.sp1           = RATPOINTS_DEFAULT_SP1;
    1770       12428 :   args.sp2           = RATPOINTS_DEFAULT_SP2;
    1771       12428 :   args.array_size    = RATPOINTS_ARRAY_SIZE;
    1772       12428 :   args.num_primes    = RATPOINTS_DEFAULT_NUM_PRIMES;
    1773       12428 :   args.bit_primes    = RATPOINTS_DEFAULT_BIT_PRIMES;
    1774       12428 :   args.max_forbidden = RATPOINTS_DEFAULT_MAX_FORBIDDEN;
    1775       12428 :   args.flags         = flags;
    1776       12428 :   data.z = cgetg(17,t_VEC);
    1777       12428 :   data.i = 0;
    1778       12428 :   data.f = flag;
    1779       12428 :   find_points_work(&args, process, (void *)&data);
    1780             : 
    1781       12428 :   setlg(data.z, data.i+1);
    1782       12428 :   return gerepilecopy(av, data.z);
    1783             : }
    1784             : 
    1785             : /* The ordinates of the points returned need to be divided by den
    1786             :  * by the caller to get the actual solutions */
    1787             : static GEN
    1788       12435 : QX_hyperellratpoints(GEN P, GEN h, long flag, GEN *den)
    1789             : {
    1790       12435 :   GEN Q = Q_remove_denom(P, den);
    1791       12435 :   if (*den) Q = ZX_Z_mul(Q, *den);
    1792       12435 :   return ZX_hyperellratpoints(Q, h, flag);
    1793             : }
    1794             : 
    1795             : static GEN
    1796         168 : ZX_homogenous_evalpow(GEN Q, GEN A, GEN B)
    1797             : {
    1798         168 :   pari_sp av = avma;
    1799         168 :   long i, d = degpol(Q);
    1800         168 :   GEN s = gel(Q, d+2);
    1801         672 :   for (i = d-1; i >= 0; i--)
    1802         504 :     s = addii(mulii(s, A), mulii(gel(B,d+1-i), gel(Q,i+2)));
    1803         168 :   return d? gerepileupto(av, s): s;
    1804             : }
    1805             : 
    1806             : static GEN
    1807          70 : to_RgX(GEN a, long v) { return typ(a)==t_POL? a: scalarpol(a,v); }
    1808             : 
    1809             : static int
    1810       11539 : hyperell_check(GEN PQ, GEN *P, GEN *Q)
    1811             : {
    1812       11539 :   *P = *Q = NULL;
    1813       11539 :   if (typ(PQ) == t_POL)
    1814             :   {
    1815       11504 :     if (!RgX_is_QX(PQ)) return 0;
    1816       11504 :     *P = PQ;
    1817             :   }
    1818             :   else
    1819             :   {
    1820          35 :     long v = gvar(PQ);
    1821          35 :     if (v == NO_VARIABLE || typ(PQ) != t_VEC || lg(PQ) != 3) return 0;
    1822          35 :     *P = to_RgX(gel(PQ,1), v); if (!RgX_is_QX(*P)) return 0;
    1823          35 :     *Q = to_RgX(gel(PQ,2), v); if (!RgX_is_QX(*Q)) return 0;
    1824          35 :     if (!signe(*Q)) *Q = NULL;
    1825             :   }
    1826       11539 :   return 1;
    1827             : }
    1828             : 
    1829             : GEN
    1830       11539 : hyperellratpoints(GEN PQ, GEN h, long flag)
    1831             : {
    1832       11539 :   pari_sp av = avma;
    1833             :   GEN P, Q, H, L, den, denQ;
    1834             :   long i, l, dy, dQ;
    1835             : 
    1836       11539 :   if (flag<0 || flag>1) pari_err_FLAG("ellratpoints");
    1837       11539 :   if (!hyperell_check(PQ, &P, &Q)) pari_err_TYPE("hyperellratpoints",PQ);
    1838       11539 :   if (!Q)
    1839             :   {
    1840       11518 :     L = QX_hyperellratpoints(P, h, flag|2L, &den);
    1841       11518 :     dy = (degpol(P)+1)>>1;
    1842       11518 :     l = lg(L);
    1843       25434 :     for (i = 1; i < l; i++)
    1844             :     {
    1845       13916 :       GEN Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3);
    1846       13916 :       GEN zdy = powiu(z, dy);
    1847       13916 :       if (den) zdy = mulii(zdy, den);
    1848       13916 :       gel(L,i) = mkvec2(gdiv(x,z), gdiv(y, zdy));
    1849             :     }
    1850       11518 :     return gerepilecopy(av, L);
    1851             :   }
    1852          21 :   H = RgX_add(RgX_muls(P,4), RgX_sqr(Q));
    1853          21 :   dy = (degpol(H)+1)>>1; dQ = degpol(Q);
    1854          21 :   L = QX_hyperellratpoints(H, h, flag|2L, &den);
    1855          21 :   Q = Q_remove_denom(Q, &denQ);
    1856          21 :   l = lg(L);
    1857         189 :   for (i = 1; i < l; i++)
    1858             :   {
    1859         168 :     GEN Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3);
    1860         168 :     GEN Qx, B = gpowers(z, dQ), zdy = powiu(z, dy), dQx = gel(B, dQ+1);
    1861         168 :     if (denQ) dQx = mulii(dQx, denQ);
    1862         168 :     Qx = gdiv(ZX_homogenous_evalpow(Q, x, B), dQx);
    1863         168 :     if (den) zdy = mulii(zdy, den);
    1864         168 :     gel(L,i) = mkvec2(gdiv(x,z), gmul2n(gsub(gdiv(y,zdy),Qx),-1));
    1865             :   }
    1866          21 :   return gerepilecopy(av, L);
    1867             : }
    1868             : 
    1869             : GEN
    1870         896 : ellratpoints(GEN E, GEN h, long flag)
    1871             : {
    1872         896 :   pari_sp av = avma;
    1873             :   GEN L, a1, a3, den;
    1874             :   long i, l;
    1875         896 :   checkell_Q(E);
    1876         896 :   if (flag<0 || flag>1) pari_err_FLAG("ellratpoints");
    1877         896 :   if (!RgV_is_QV(vecslice(E,1,5))) pari_err_TYPE("ellratpoints",E);
    1878         896 :   a1 = ell_get_a1(E);
    1879         896 :   a3 = ell_get_a3(E);
    1880         896 :   L = QX_hyperellratpoints(ec_bmodel(E,0), h, flag|2L, &den);
    1881         889 :   l = lg(L);
    1882       73003 :   for (i = 1; i < l; i++)
    1883             :   {
    1884       72114 :     GEN P, Li = gel(L,i), x = gel(Li,1), y = gel(Li,2), z = gel(Li,3);
    1885       72114 :     if (!signe(z))
    1886           0 :       P = ellinf();
    1887             :     else
    1888             :     {
    1889       72114 :       GEN z2 = sqri(z);
    1890       72114 :       if (den) y = gdiv(y, den);
    1891       72114 :       y = gsub(y, gadd(gmul(a1, mulii(x,z)), gmul(a3,z2)));
    1892       72114 :       P = mkvec2(gdiv(x,z), gdiv(y,shifti(z2,1)));
    1893             :     }
    1894       72114 :     gel(L,i) = P;
    1895             :   }
    1896         889 :   return gerepilecopy(av, L);
    1897             : }

Generated by: LCOV version 1.16