1 // -*- mode:C++ ; compile-command: "g++-3.4 -I.. -g -c ifactor.cc -DHAVE_CONFIG_H -DIN_GIAC" -*-
2 #include "giacPCH.h"
3 #if !defined __MINGW_H && !defined KHICAS
4 #define GIAC_MPQS // define if you want to use giac for sieving
5 #endif
6 
7 #ifdef HAVE_LIBECM
8 #include <ecm.h>
9 #endif
10 
11 #include "path.h"
12 /*
13  *  Copyright (C) 2003,14 R. De Graeve & B. Parisse,
14  *  Institut Fourier, 38402 St Martin d'Heres
15  *
16  *  This program is free software; you can redistribute it and/or modify
17  *  it under the terms of the GNU General Public License as published by
18  *  the Free Software Foundation; either version 3 of the License, or
19  *  (at your option) any later version.
20  *
21  *  This program is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *  GNU General Public License for more details.
25  *
26  *  You should have received a copy of the GNU General Public License
27  *  along with this program. If not, see <http://www.gnu.org/licenses/>.
28  */
29 
30 using namespace std;
31 #ifdef GIAC_HAS_STO_38
32 //#undef clock
33 //#undef clock_t
34 #else
35 #include <fstream>
36 //#include <unistd.h> // For reading arguments from file
37 #include "ifactor.h"
38 #include "pari.h"
39 #include "usual.h"
40 #include "sym2poly.h"
41 #include "rpn.h"
42 #include "prog.h"
43 #include "misc.h"
44 #include "giacintl.h"
45 #endif
46 
47 #ifdef GIAC_HAS_STO_38
48 #define BESTA_OS
49 #endif
50 // Trying to make ifactor(2^128+1) work on ARM
51 #if defined(RTOS_THREADX) || defined(BESTA_OS) || defined NSPIRE
52 //#define OLD_AFACT
53 #define GIAC_ADDITIONAL_PRIMES 16// if defined, additional primes are used in sieve
54 #else
55 #define GIAC_ADDITIONAL_PRIMES 32// if defined, additional primes are used in sieve
56 #endif
57 
58 
59 #ifndef NO_NAMESPACE_GIAC
60 namespace giac {
61 #endif // ndef NO_NAMESPACE_GIAC
62 
63 #if 0
64   struct int256 {
65     longlong a;
66     ulonglong b,c,d;
67   };
68   struct int128 {
69     longlong a;
70     ulonglong b;
71   };
72 
73   void sub(int256 A,int b,int256 & C){
74     bool Apos=A.a>=0;
75     if (Apos){
76       if (b<0){
77 	add(A,b,C);
78 	return;
79       }
80       bool carry=A.d<b;
81       A.d -= b;
82       if (carry){
83 	carry=A.c<1;
84 	A.c--;
85 	if (carry){
86 	  carry=A.b<1;
87 	  A.b--;
88 	  if (carry)
89 	    A.a--;
90 	}
91       }
92       C=A;
93       return;
94     }
95     A.a = -A.a;
96     sub(A,-b,C);
97     C.a = -C.a;
98   }
99 
100   void add(const int192 & A,int b,int192 & C){
101     bool Apos=A.a>=0;
102     if (Apos){
103       if (b<0){
104 	sub(A,-b,C);
105 	return;
106       }
107       A.d += b;
108       if (A.d<b){
109 	A.c++;
110 	if (A.c==0){
111 	  A.b++;
112 	  if (A.n==0)
113 	    A.a++;
114 	}
115       }
116       C=A;
117       return;
118     }
119     A.a = -A.a;
120     sub(A,-b,C);
121     C.a = -C.a;
122   }
123 
124   inline void int128tounsigned(const int128 & A,unsigned & Aa,unsigned & Ab,unsigned & Ac,unsigned & Ad){
125     Aa = (* ((unsigned *) (&A.a)+1)) & 0x7fff;
126     Ab = *(unsigned *) A.a;
127     Ac = *( (unsigned *) &A.b)+1;
128     Ad = *(unsigned *) A.d;
129   }
130 
131   void mul(int128 A,int128 B,int256 & C){
132     bool neg=(A.a<0) ^ (B.a<0);
133     unsigned A3,A2,A1,A0,B3,B2,B1,B0,C6,C5,C4,C3,C2,C1,C0;
134     int128tounsigned(A,A3,A2,A1,A0);
135     int128tounsigned(B,B3,B2,B1,B0);
136     ulonglong p1,p2,p3,p;
137     p1=A0; p2=B0;
138     p3=p1*p2;
139     C0=p3;
140     C1=p3>>32;
141     p1=A1;
142     p = p1*p2;
143     p += C1;
144     unsigned short carry = (p<C1);
145     p1=A0; p2=B1;
146     p3=p1*p2;
147     p += p3;
148     carry += (p<p3);
149     C1 = p;
150     C2 = p>>32;
151     C2 += carry;
152     carry = (C2<carry);
153   }
154 
155 #endif
156 
157   const short int giac_primes[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997,1009,1013,1019,1021,1031,1033,1039,1049,1051,1061,1063,1069,1087,1091,1093,1097,1103,1109,1117,1123,1129,1151,1153,1163,1171,1181,1187,1193,1201,1213,1217,1223,1229,1231,1237,1249,1259,1277,1279,1283,1289,1291,1297,1301,1303,1307,1319,1321,1327,1361,1367,1373,1381,1399,1409,1423,1427,1429,1433,1439,1447,1451,1453,1459,1471,1481,1483,1487,1489,1493,1499,1511,1523,1531,1543,1549,1553,1559,1567,1571,1579,1583,1597,1601,1607,1609,1613,1619,1621,1627,1637,1657,1663,1667,1669,1693,1697,1699,1709,1721,1723,1733,1741,1747,1753,1759,1777,1783,1787,1789,1801,1811,1823,1831,1847,1861,1867,1871,1873,1877,1879,1889,1901,1907,1913,1931,1933,1949,1951,1973,1979,1987,1993,1997,1999,2003,2011,2017,2027,2029,2039,2053,2063,2069,2081,2083,2087,2089,2099,2111,2113,2129,2131,2137,2141,2143,2153,2161,2179,2203,2207,2213,2221,2237,2239,2243,2251,2267,2269,2273,2281,2287,2293,2297,2309,2311,2333,2339,2341,2347,2351,2357,2371,2377,2381,2383,2389,2393,2399,2411,2417,2423,2437,2441,2447,2459,2467,2473,2477,2503,2521,2531,2539,2543,2549,2551,2557,2579,2591,2593,2609,2617,2621,2633,2647,2657,2659,2663,2671,2677,2683,2687,2689,2693,2699,2707,2711,2713,2719,2729,2731,2741,2749,2753,2767,2777,2789,2791,2797,2801,2803,2819,2833,2837,2843,2851,2857,2861,2879,2887,2897,2903,2909,2917,2927,2939,2953,2957,2963,2969,2971,2999,3001,3011,3019,3023,3037,3041,3049,3061,3067,3079,3083,3089,3109,3119,3121,3137,3163,3167,3169,3181,3187,3191,3203,3209,3217,3221,3229,3251,3253,3257,3259,3271,3299,3301,3307,3313,3319,3323,3329,3331,3343,3347,3359,3361,3371,3373,3389,3391,3407,3413,3433,3449,3457,3461,3463,3467,3469,3491,3499,3511,3517,3527,3529,3533,3539,3541,3547,3557,3559,3571,3581,3583,3593,3607,3613,3617,3623,3631,3637,3643,3659,3671,3673,3677,3691,3697,3701,3709,3719,3727,3733,3739,3761,3767,3769,3779,3793,3797,3803,3821,3823,3833,3847,3851,3853,3863,3877,3881,3889,3907,3911,3917,3919,3923,3929,3931,3943,3947,3967,3989,4001,4003,4007,4013,4019,4021,4027,4049,4051,4057,4073,4079,4091,4093,4099,4111,4127,4129,4133,4139,4153,4157,4159,4177,4201,4211,4217,4219,4229,4231,4241,4243,4253,4259,4261,4271,4273,4283,4289,4297,4327,4337,4339,4349,4357,4363,4373,4391,4397,4409,4421,4423,4441,4447,4451,4457,4463,4481,4483,4493,4507,4513,4517,4519,4523,4547,4549,4561,4567,4583,4591,4597,4603,4621,4637,4639,4643,4649,4651,4657,4663,4673,4679,4691,4703,4721,4723,4729,4733,4751,4759,4783,4787,4789,4793,4799,4801,4813,4817,4831,4861,4871,4877,4889,4903,4909,4919,4931,4933,4937,4943,4951,4957,4967,4969,4973,4987,4993,4999,5003,5009,5011,5021,5023,5039,5051,5059,5077,5081,5087,5099,5101,5107,5113,5119,5147,5153,5167,5171,5179,5189,5197,5209,5227,5231,5233,5237,5261,5273,5279,5281,5297,5303,5309,5323,5333,5347,5351,5381,5387,5393,5399,5407,5413,5417,5419,5431,5437,5441,5443,5449,5471,5477,5479,5483,5501,5503,5507,5519,5521,5527,5531,5557,5563,5569,5573,5581,5591,5623,5639,5641,5647,5651,5653,5657,5659,5669,5683,5689,5693,5701,5711,5717,5737,5741,5743,5749,5779,5783,5791,5801,5807,5813,5821,5827,5839,5843,5849,5851,5857,5861,5867,5869,5879,5881,5897,5903,5923,5927,5939,5953,5981,5987,6007,6011,6029,6037,6043,6047,6053,6067,6073,6079,6089,6091,6101,6113,6121,6131,6133,6143,6151,6163,6173,6197,6199,6203,6211,6217,6221,6229,6247,6257,6263,6269,6271,6277,6287,6299,6301,6311,6317,6323,6329,6337,6343,6353,6359,6361,6367,6373,6379,6389,6397,6421,6427,6449,6451,6469,6473,6481,6491,6521,6529,6547,6551,6553,6563,6569,6571,6577,6581,6599,6607,6619,6637,6653,6659,6661,6673,6679,6689,6691,6701,6703,6709,6719,6733,6737,6761,6763,6779,6781,6791,6793,6803,6823,6827,6829,6833,6841,6857,6863,6869,6871,6883,6899,6907,6911,6917,6947,6949,6959,6961,6967,6971,6977,6983,6991,6997,7001,7013,7019,7027,7039,7043,7057,7069,7079,7103,7109,7121,7127,7129,7151,7159,7177,7187,7193,7207,7211,7213,7219,7229,7237,7243,7247,7253,7283,7297,7307,7309,7321,7331,7333,7349,7351,7369,7393,7411,7417,7433,7451,7457,7459,7477,7481,7487,7489,7499,7507,7517,7523,7529,7537,7541,7547,7549,7559,7561,7573,7577,7583,7589,7591,7603,7607,7621,7639,7643,7649,7669,7673,7681,7687,7691,7699,7703,7717,7723,7727,7741,7753,7757,7759,7789,7793,7817,7823,7829,7841,7853,7867,7873,7877,7879,7883,7901,7907,7919,7927,7933,7937,7949,7951,7963,7993,8009,8011,8017,8039,8053,8059,8069,8081,8087,8089,8093,8101,8111,8117,8123,8147,8161,8167,8171,8179,8191,8209,8219,8221,8231,8233,8237,8243,8263,8269,8273,8287,8291,8293,8297,8311,8317,8329,8353,8363,8369,8377,8387,8389,8419,8423,8429,8431,8443,8447,8461,8467,8501,8513,8521,8527,8537,8539,8543,8563,8573,8581,8597,8599,8609,8623,8627,8629,8641,8647,8663,8669,8677,8681,8689,8693,8699,8707,8713,8719,8731,8737,8741,8747,8753,8761,8779,8783,8803,8807,8819,8821,8831,8837,8839,8849,8861,8863,8867,8887,8893,8923,8929,8933,8941,8951,8963,8969,8971,8999,9001,9007,9011,9013,9029,9041,9043,9049,9059,9067,9091,9103,9109,9127,9133,9137,9151,9157,9161,9173,9181,9187,9199,9203,9209,9221,9227,9239,9241,9257,9277,9281,9283,9293,9311,9319,9323,9337,9341,9343,9349,9371,9377,9391,9397,9403,9413,9419,9421,9431,9433,9437,9439,9461,9463,9467,9473,9479,9491,9497,9511,9521,9533,9539,9547,9551,9587,9601,9613,9619,9623,9629,9631,9643,9649,9661,9677,9679,9689,9697,9719,9721,9733,9739,9743,9749,9767,9769,9781,9787,9791,9803,9811,9817,9829,9833,9839,9851,9857,9859,9871,9883,9887,9901,9907,9923,9929,9931,9941,9949,9967,9973};
158 
159   // #define PRIME_SIEVE
160 #ifdef PRIME_SIEVE
161   // fill Erathosthene sieve crible for searching primes up to 2*crible.size()*32+1
162   // crible is a (packed) bit array, crible[i] is true if 2*i+1 is a prime
163   // crible must be set to true at startup
fill_crible(vector<unsigned> & crible,unsigned p)164   void fill_crible(vector<unsigned> & crible,unsigned p){
165     crible.resize((p-1)/64+1);
166     unsigned cs=crible.size();
167     unsigned lastnum=64*cs;
168     unsigned lastsieve=int(std::sqrt(double(lastnum)));
169     unsigned primesieved=1;
170     crible[0] = 0xfffffffe; // 1 is not prime and not sieved (2 is not sieved)
171     for (unsigned i=1;i<cs;++i)
172       crible[i]=0xffffffff;
173     for (;primesieved<=lastsieve;primesieved+=2){
174       // find next prime
175       unsigned pos=primesieved/2;
176       for (;pos<cs;pos++){
177 	if (crible[pos/32] & (1 << (pos %32)))
178 	  break;
179       }
180       // set mutiples of (2*pos+1) to false
181       primesieved=2*pos+1;
182       unsigned n=3*primesieved;
183       for (;n<lastnum;n+=2*primesieved){
184 	pos=(n-1)/2;
185 	crible[(pos/32)] &= ~(1<<(pos %32));
186       }
187     }
188   }
nextprime(vector<unsigned> & crible,unsigned p)189   unsigned nextprime(vector<unsigned> & crible,unsigned p){
190     // assumes crible has been filled
191     ++p;
192     if (p%2==0)
193       ++p;
194     unsigned pos=(p-1)/2,cs=crible.size()*32;
195     if (2*cs+1<=p)
196       return nextprime(int(p)).val;
197     for (;pos<cs;++pos){
198       if (crible[pos/32] & (1<<(pos%32))){
199 	pos=2*pos+1;
200 	// if (pos!=nextprime(int(p)).val) CERR << "error " << p << '\n';
201 	return pos;
202       }
203     }
204     return nextprime(int(p)).val; // not found
205   }
206 #endif
207 
208   static const int giac_last_prime=giac_primes[sizeof(giac_primes)/sizeof(short)-1];
209 #if defined RTOS_THREADX || defined BESTA_OS || defined NSPIRE
210   const unsigned QS_SIZE=65536; // number of slicetype in a sieve slice
211   typedef unsigned char slicetype; // define to unsigned char if not enough
212 #else
213   const unsigned QS_SIZE=65536; // number of slicetype in a sieve slice
214   typedef unsigned char slicetype; // define to unsigned char if not enough
215 #endif
216 
217 #ifdef NSPIRE
218   template<class T>
printbool(nio::ios_base<T> & os,const vector<unsigned> & v,int C=1)219   static void printbool(nio::ios_base<T> & os,const vector<unsigned> & v,int C=1){
220     if (C)
221       C=giacmin(C,int(v.size()));
222     else
223       C=v.size();
224     for (int c=0;c<C;++c){
225       for (int s=0;s<32;++s){
226 	os << (((v[c] >> s & 1)==1)?1:0) << " ";
227       }
228     }
229     os << '\n';
230   }
231 
232   template<class T>
printbool(nio::ios_base<T> & os,const vector<vector<unsigned>> & m,int L=32)233   void printbool(nio::ios_base<T> & os,const vector< vector<unsigned> > & m,int L=32){
234     if (L)
235       L=giacmin(L,int(m.size()));
236     else
237       L=m.size();
238     for (int l=0;l<L;++l){
239       printbool(os,m[l]);
240     }
241   }
242 #else
printbool(ostream & os,const vector<unsigned> & v,int C=1)243   static void printbool(ostream & os,const vector<unsigned> & v,int C=1){
244     if (C)
245       C=giacmin(C,int(v.size()));
246     else
247       C=int(v.size());
248     for (int c=0;c<C;++c){
249       for (int s=0;s<32;++s){
250 	os << (((v[c] >> s & 1)==1)?1:0) << " ";
251       }
252     }
253     os << '\n';
254   }
255 
printbool(ostream & os,const vector<vector<unsigned>> & m,int L=32)256   void printbool(ostream & os,const vector< vector<unsigned> > & m,int L=32){
257     if (L)
258       L=giacmin(L,int(m.size()));
259     else
260       L=int(m.size());
261     for (int l=0;l<L;++l){
262       printbool(os,m[l]);
263     }
264   }
265 #endif
266 
267   template <class T>
swap(T * & ptr1,T * & ptr2)268   inline void swap(T * & ptr1, T * & ptr2){
269     T * tmp=ptr1;
270     ptr1=ptr2;
271     ptr2=tmp;
272   }
273 
274 #ifdef x86_64
275 #define GIAC_RREF_UNROLL 4
276 #else
277 #define GIAC_RREF_UNROLL 4
278 #endif
279 
280   // #define RREF_SORT
281 #ifdef RREF_SORT
282   struct line_t {
283     unsigned * tab;
284     unsigned count;
285   };
286 
operator <(const line_t & l1,const line_t & l2)287   bool operator < (const line_t & l1,const line_t & l2){
288     if (!l1.count)
289       return false;
290     if (!l2.count)
291       return true;
292     return l1.count<l2.count;
293   }
294 
count_ones(unsigned * tab,int C32)295   unsigned count_ones(unsigned * tab,int C32){
296     register unsigned r=0;
297     register unsigned * tabend=tab+C32;
298     for (;tab!=tabend;++tab){
299       register unsigned u=*tab;
300       while (u){
301 	r += u & 1;
302 	u >>= 1;
303       }
304     }
305     return r;
306   }
307 
308 #else
309   struct line_t {
310     unsigned * tab;
311   };
312 #endif
313 
314 
315   // mode=0: full reduction, 1 subreduction, 2 finish full reduction from subreduction
rref(vector<line_t> & m,int L,int C32,int mode)316   void rref(vector< line_t > & m,int L,int C32,int mode){
317     int i,l=0,c=0,C=C32*32;
318     for (;l<L && c<C;){
319       // printbool(CERR,m);
320       int c1=c/32,c2=c%32;
321       // find first non-0 pivot in col c starting at row l
322       for (i=l;i<L;++i){
323 	if ((m[i].tab[c1] >> c2) & 1)
324 	  break;
325       }
326       if (i==L){ // none found in this column
327 	++c;
328 	continue;
329       }
330       if (i!=l)
331 	swap(m[i].tab,m[l].tab); // don't care about count...
332       int start=mode==1?l+1:0, end=mode==2?l:L;
333 #ifdef x86_64
334       ulonglong * pivend, * pivbeg;
335       pivbeg = (ulonglong *) (m[l].tab+(c1/GIAC_RREF_UNROLL)*GIAC_RREF_UNROLL);
336       pivend = (ulonglong *) (m[l].tab+C32);
337 #else
338       unsigned * pivbeg = m[l].tab+(c1/GIAC_RREF_UNROLL)*GIAC_RREF_UNROLL, * pivend = m[l].tab+C32;
339 #endif
340       for (i=start;i<end;++i){
341 	if (i==l || ( (m[i].tab[c1] >> c2) & 1)!=1)
342 	  continue;
343 	// line combination l and i
344 #ifdef x86_64
345 	ulonglong * curptr=(ulonglong *) (m[i].tab+(c1/GIAC_RREF_UNROLL)*GIAC_RREF_UNROLL);
346 	for (ulonglong * pivptr=pivbeg;pivptr!=pivend;curptr += GIAC_RREF_UNROLL/2,pivptr += GIAC_RREF_UNROLL/2){
347 	  // small optimization (loop unroll), assumes mult of 4(*32) columns
348 	  // PREFETCH(curptr+8);
349 	  *curptr ^= *pivptr;
350 	  curptr[1] ^= pivptr[1];
351 #if GIAC_RREF_UNROLL==8
352 	  curptr[2] ^= pivptr[2];
353 	  curptr[3] ^= pivptr[3];
354 #endif
355 	}
356 #else
357 	unsigned * curptr=m[i].tab+(c1/GIAC_RREF_UNROLL)*GIAC_RREF_UNROLL;
358 	for (unsigned * pivptr=pivbeg;pivptr!=pivend;curptr += GIAC_RREF_UNROLL,pivptr += GIAC_RREF_UNROLL){
359 	  // small optimization (loop unroll), assumes mult of 4(*32) columns
360 	  // PREFETCH(curptr+16);
361 	  *curptr ^= *pivptr;
362 	  curptr[1] ^= pivptr[1];
363 	  curptr[2] ^= pivptr[2];
364 	  curptr[3] ^= pivptr[3];
365 #if GIAC_RREF_UNROLL==8
366 	  curptr[4] ^= pivptr[4];
367 	  curptr[5] ^= pivptr[5];
368 	  curptr[6] ^= pivptr[6];
369 	  curptr[7] ^= pivptr[7];
370 #endif
371 	}
372 #endif
373       }
374       ++l;
375       ++c;
376     }
377   }
378 
379   template <class T>
release_memory(vector<T> & slice)380   void release_memory(vector<T> & slice){
381     // release memory from slice
382     vector<T> tmp;
383     swap(slice,tmp);
384   }
385 
386 #ifdef USE_GMP_REPLACEMENTS
modulo(const mpz_t & a,unsigned b)387   int modulo(const mpz_t & a,unsigned b){
388     if (mpz_cmp_ui(a,0)<0){
389       mpz_neg(*(mpz_t *)&a,a);
390       int res=modulo(a,b);
391       mpz_neg(*(mpz_t *)&a,a);
392       return b-res;
393     }
394     mp_digit C;
395     mp_mod_d((mp_int *)&a,b,&C);
396     return C;
397   }
398 #else
modulo(const mpz_t & a,unsigned b)399   int modulo(const mpz_t & a,unsigned b){
400     return mpz_fdiv_ui(a,b);
401   }
402 #endif
403 
404 #if defined RTOS_THREADX || defined BESTA_OS || defined NSPIRE
405   typedef unsigned short pui_t ;
406   typedef unsigned short ushort_t;
407   typedef short short_t;
408 #else
409   typedef unsigned pui_t ;
410   // #ifndef USE_GMP_REPLACEMENTS // uncomment for Aspen debugging
411 #define PRIMES32
412   // #endif
413 #ifdef PRIMES32
414   typedef unsigned ushort_t;
415   typedef int short_t;
416 #else
417   typedef unsigned short ushort_t;
418   typedef unsigned short int short_t;
419 #endif
420 
421 #ifdef EMCC
422 #include <map>
423 #endif
424 #if (defined EMCC || defined(HASH_MAP_NAMESPACE)) && defined(PRIMES32)
425 #define ADDITIONAL_PRIMES_HASHMAP
426 #endif
427 #endif // RTOS_THREADX || BESTA_OS
428 
429   struct axbinv {
430 #if 0
431     unsigned short aindex;
432     unsigned short bindex;
433 #else
434     unsigned aindex;
435     unsigned bindex;
436 #endif
437     int shiftpos;
438     pui_t first,second; // indexes in the "puissancestab" table
axbinvgiac::axbinv439     axbinv(ushort_t a_,int shiftpos_,ushort_t b_,pui_t f_,pui_t s_):aindex(a_),bindex(b_),shiftpos(shiftpos_),first(f_),second(s_) {};
axbinvgiac::axbinv440     axbinv() {};
441   };
442 
443 #ifdef ADDITIONAL_PRIMES_HASHMAP
largep(const axbinv & A,ushort_t * puissancestab)444   unsigned largep(const axbinv & A,ushort_t * puissancestab) {
445     // return A.largeprime;
446     if (A.second-A.first<3) return 0;
447 #ifdef PRIMES32
448     if (*(puissancestab+A.second-2)!=1)
449       return 0;
450     return *(puissancestab+A.second-1);
451 #else
452     if (*(puissancestab+A.second-3)!=1)
453       return 0;
454     return (unsigned(*(puissancestab+A.second-2)) << 16)  + *(puissancestab+A.second-1);
455 #endif
456   }
457 #endif
458 
459 #ifdef ADDITIONAL_PRIMES_HASHMAP
460 #ifdef EMCC // container does not seem to be important for <= 70 digits
461   typedef map<unsigned,axbinv> additional_map_t;
462 #else
463   typedef HASH_MAP_NAMESPACE::hash_map<unsigned,axbinv,hash_function_unsigned_object > additional_map_t ;
464 #endif
465 #endif
466 
467 #if !defined(RTOS_THREADX) && !defined(BESTA_OS) && !defined NSPIRE
468   // #define WITH_INVA
469 #if defined(__APPLE__) || defined(x86_64)
470 #define LP_TAB_SIZE 15 // slice size will be 2^LP_TAB_SIZE
471   //  #define LP_SMALL_PRIMES
472 #define LP_TAB_TOGETHER
473 #define USE_MORE_PRIMES
474 #else
475 #define LP_TAB_SIZE 15 // slice size will be 2^LP_TAB_SIZE
476 #endif // APPLE or 64 bits
477 #endif // !defined RTOS_THREADX and BESTA_OS
478 
479 #ifdef LP_TAB_SIZE
480 #define LP_MASK ((1<<LP_TAB_SIZE)-1)
481   struct lp_entry_t {
482     ushort_t pos;
483     ushort_t p;
lp_entry_tgiac::lp_entry_t484     lp_entry_t():pos(0),p(0) {};
lp_entry_tgiac::lp_entry_t485     lp_entry_t(ushort_t pos_,ushort_t p_):pos(pos_),p(p_) {};
486   };
487   typedef vector<lp_entry_t> lp_tab_t;
488 #endif
489 
490 #ifdef LP_TAB_SIZE
491 #define LP_BIT_LIMIT 15
492 #else
493 #define LP_BIT_LIMIT 15
494 #endif
495 
496 #if GIAC_ADDITIONAL_PRIMES==16
497   typedef unsigned short additional_t;
498 #else
499   typedef int additional_t;
500 #endif
501 
_equalposcomp(const std::vector<additional_t> & v,additional_t w)502   inline int _equalposcomp(const std::vector<additional_t> & v, additional_t w){
503     int n=1;
504     for (std::vector<additional_t>::const_iterator it=v.begin(),itend=v.end();it!=itend;++it){
505       if ((*it)==w)
506 	return n;
507       else
508 	n++;
509     }
510     return 0;
511   }
512 
513   // #define SQRTMOD_OUTSIDE
514 #define WITH_LOGP // if defined primes should not exceed 2^24 (perhaps 2^25, choice of sqrt)
515 
516   struct small_basis_t {
517     unsigned short root1;
518     unsigned short root2;
519     unsigned short p;
520     unsigned short logp;
521   };
522 
523 #ifdef SQRTMOD_OUTSIDE
524   struct basis_t {
525     unsigned root1; // first root position in slice
526     unsigned root2; // second root position
527     ushort_t p:24; // the prime p
528 #ifdef WITH_LOGP
529     unsigned char logp:8; // could be unsigned char
530 #endif
basis_tgiac::basis_t531     basis_t():root1(0),root2(0),p(2) {
532 #ifdef WITH_LOGP
533       logp=sizeinbase2(p);
534 #endif
535     }
basis_tgiac::basis_t536     basis_t(ushort_t _p):root1(0),root2(0),p(_p) {
537 #ifdef WITH_LOGP
538       logp=sizeinbase2(p);
539 #endif
540     }
541   } ;
542 
543 #else // SQRTMOD_OUTSIDE
544   struct basis_t {
545     unsigned root1; // first root position in slice
546     unsigned root2; // second root position
547     ushort_t p; // the prime p
548     unsigned sqrtmod:24;
549 #ifdef WITH_LOGP
550     unsigned char logp:8; // could be unsigned char
551 #endif
basis_tgiac::basis_t552     basis_t():root1(0),root2(0),p(2),sqrtmod(0) {
553 #ifdef WITH_LOGP
554       logp=sizeinbase2(p);
555 #endif
556     }
basis_tgiac::basis_t557     basis_t(ushort_t _p):root1(0),root2(0),p(_p),sqrtmod(0) {
558 #ifdef WITH_LOGP
559       logp=sizeinbase2(p);
560 #endif
561     }
basis_tgiac::basis_t562     basis_t(ushort_t _p,ushort_t _sqrtmod):root1(0),root2(0),p(_p),sqrtmod(_sqrtmod) {
563 #ifdef WITH_LOGP
564       logp=sizeinbase2(p);
565 #endif
566 }
567   } ;
568 #endif // SQRTMOD_OUTSIDE
569 
570 #ifdef LP_SMALL_PRIMES
core_sieve(slicetype * slice,small_basis_t * bit,small_basis_t * bitend)571   static inline void core_sieve(slicetype * slice,small_basis_t * bit,small_basis_t * bitend)  {
572     for (;bit!=bitend;++bit){
573       // first root is at bit->root1
574       register unsigned p=bit->p;
575       register unsigned char nbits=bit->logp;
576       register unsigned pos=bit->root1,pos2=bit->root2;
577       if (pos==pos2){
578 	for (;pos<32768; pos += p){
579 	  slice[pos] -= nbits;
580 	}
581 	bit->root2=bit->root1 = pos-32768; // save for next slice
582       }
583       else {
584 	for (;pos<32768; pos += p){
585 	  slice[pos] -= nbits;
586 	}
587 	bit->root1 = pos-32768; // save for next slice
588 	// second root, polynomial has 2 distinct roots
589 	for (;pos2<32768;pos2 += p){
590 	  slice[pos2] -= nbits;
591 	}
592 	bit->root2 = pos2-32768;
593       }
594     }
595   }
596 
597 #else // LP_SMALL_PRIMES
598 
599 #ifdef LP_TAB_SIZE
600 #define SLICEEND (1<<LP_TAB_SIZE)
601 #else
602 #define SLICEEND ss
603 #endif
604 
605   // return position of last prime sieved (useful when large prime hashtable is enabled
core_sieve(slicetype * slice,int ss,basis_t * bit,basis_t * bitend)606   static inline basis_t * core_sieve(slicetype * slice,int ss,basis_t * bit,basis_t * bitend)  {
607     register unsigned char nbits=sizeinbase2(bit->p);
608     // int next=1 << nbits;
609     for (;bit!=bitend;++bit){
610       // first root is at bit->root1
611       register ushort_t p=bit->p;
612 #ifdef WITH_LOGP
613       nbits=bit->logp;
614 #else
615       if (p>next){
616 	++nbits;
617 #if !defined(BESTA_OS) && !defined(RTOS_THREADX) && !defined NSPIRE
618 	if (nbits==LP_BIT_LIMIT+1)
619 	  break;
620 #endif
621 	next *=2;
622       }
623 #endif
624       register unsigned pos=bit->root1,pos2=bit->root2;
625       if (pos==pos2){
626 	for (;int(pos)<SLICEEND; pos += p){
627 	  slice[pos] -= nbits;
628 	}
629 	bit->root2=bit->root1 = pos-SLICEEND; // save for next slice
630       }
631       else {
632 	for (;int(pos)<SLICEEND; pos += p){
633 	  slice[pos] -= nbits;
634 	}
635 	bit->root1 = pos-SLICEEND; // save for next slice
636 	// second root, polynomial has 2 distinct roots
637 	for (;int(pos2)<SLICEEND;pos2 += p){
638 	  slice[pos2] -= nbits;
639 	}
640 	bit->root2 = pos2-SLICEEND;
641       }
642     }
643 #if !defined(RTOS_THREADX) && !defined(BESTA_OS) && !defined NSPIRE
644 #ifndef LP_TAB_SIZE
645     for (;bit!=bitend;++bit){
646       // same as above but we are sieving with primes >2^15, no need to check for nbits increase
647       register ushort_t p=bit->p;
648       register unsigned pos=bit->root1;
649       for (;pos<ss; pos += p){
650 	slice[pos] -= LP_BIT_LIMIT+1;
651       }
652       bit->root1 = pos-ss; // save for next slice
653       // if (sameroot) continue;
654       pos=bit->root2;
655       for (;pos<ss;pos += p){
656 	slice[pos] -= LP_BIT_LIMIT+1;
657       }
658       bit->root2 = pos-ss;
659     }
660 #endif
661 #endif
662     return bit;
663   }
664 #endif // LP_SMALL_PRIMES
665 
666   // sieve in [sqrtN+shift,sqrtN+shift+slice.size()-1]
667   // return -1 if memory problem, or the number of relations
msieve(const gen & a,const vecteur & sqrtavals,const vecteur & bvals,const mpz_t & c,vector<basis_t> & basis,unsigned lp_basis_pos,vector<small_basis_t> & small_basis,unsigned maxadditional,additional_map_t & additional_primes_map,const gen & N,const gen & isqrtN,slicetype * slice,int ss,int shift,ushort_t * puissancesbegin,ushort_t * & puissancesptr,ushort_t * puissancesend,vector<ushort_t> & curpuissances,vector<ushort_t> & recheck,vector<axbinv> & axbmodn,mpz_t & z1,mpz_t & z2,mpz_t & z3,mpz_t & alloc1,mpz_t & alloc2,mpz_t & alloc3,mpz_t & alloc4,mpz_t & alloc5,const lp_tab_t & lp_tab,GIAC_CONTEXT)668   int msieve(const gen & a,const vecteur & sqrtavals,
669 	     const vecteur &bvals,const mpz_t& c,
670 	     vector<basis_t> & basis,unsigned lp_basis_pos,
671 #ifdef LP_SMALL_PRIMES
672 	     vector<small_basis_t> & small_basis,
673 #endif
674 	     unsigned maxadditional,
675 #ifdef ADDITIONAL_PRIMES_HASHMAP
676 	     additional_map_t & additional_primes_map,
677 #else
678 	     vector<additional_t> & additional_primes,vector<bool> & additional_primes_twice,
679 #endif
680 	     const gen & N,const gen & isqrtN,
681 	     slicetype * slice,int ss,int shift,
682 	     ushort_t * puissancesbegin,ushort_t* & puissancesptr,ushort_t * puissancesend,
683 	     vector<ushort_t> & curpuissances,vector<ushort_t> &recheck,
684 	     vector<axbinv> & axbmodn,
685 	     mpz_t & z1,mpz_t & z2,mpz_t & z3,mpz_t & alloc1,mpz_t & alloc2,mpz_t & alloc3,mpz_t & alloc4,mpz_t & alloc5,
686 #ifdef LP_TAB_SIZE
687 	     const lp_tab_t & lp_tab,
688 #endif
689 	     GIAC_CONTEXT){
690     int nrelations=0;
691     // first fill slice with expected number of bits of
692     // (isqrtN+shift)^2-N = 2*shift*isqrtN + negl.
693     // -> log(2*isqrtN)+log(shift)
694     int shiftss=absint(shift+ss),absshift=absint(shift);
695     int nbits=mpz_sizeinbase(*isqrtN._ZINTptr,2)+sizeinbase2(absshift>shiftss?absshift:shiftss);
696     // int nbits1=int(0.5+std::log(evalf_double(isqrtN,1,context0)._DOUBLE_val/2.*(absshift>shiftss?absshift:shiftss))/std::log(2.));
697     // int curbits=0;
698     int bs=int(basis.size());
699     double up_to=1.5;
700     if (nbits>70)
701       up_to += (0.8*(nbits-70))/70;
702     if (debug_infolevel>7)
703       *logptr(contextptr) << CLOCK() << gettext("Sieve tolerance factor ") << up_to << '\n';
704     unsigned char logB=(unsigned char) (nbits-int(up_to*sizeinbase2(basis.back().p)+.5));
705     // unsigned char logB=(unsigned char) (nbits-int(up_to*std::log(double(basis.back().p))/std::log(2.0)+.5));
706     if (debug_infolevel>6)
707       *logptr(contextptr) << CLOCK() << gettext(" reset") << '\n';
708     // assumes slice type is size 1 byte and multiple of 32
709 #ifdef x86_64
710     ulonglong * ptr=(ulonglong *) &slice[0];
711     ulonglong * ptrend=ptr+ss/8;
712     ulonglong pattern=(logB <<24)|(logB<<16)|(logB<<8) | logB;
713     pattern = (pattern << 32) | pattern;
714     for (;ptr!=ptrend;++ptr){
715       *ptr=pattern;
716     }
717 #else
718     unsigned * ptr=(unsigned *) &slice[0];
719     unsigned * ptrend=ptr+ss/4;
720     unsigned pattern=(logB <<24)|(logB<<16)|(logB<<8) | logB;
721     for (;ptr!=ptrend;++ptr){
722       *ptr=pattern;
723     }
724 #endif
725     if (debug_infolevel>8)
726       *logptr(contextptr) << CLOCK() << gettext(" end reset, nbits ") << nbits << '\n';
727     // now for all primes p in basis move in slice from p to p
728     // decrease slice[] by number of bits in p
729     // determines the first prime used in basis
730 #if 0 // def WITH_LOGP
731     nbits=2*mpz_sizeinbase(*isqrtN._ZINTptr,2);
732     int next=50;
733     // note that msieve leaves 20 to 22 primes for normal range, and 15 for large
734     nbits = sizeinbase2(next);
735 #else
736     if (nbits>120)
737       nbits = 7;
738     else {
739       if (nbits>90)
740 	nbits = 6;
741       else {
742 	if (nbits>78)
743 	  nbits=5;
744 	else
745 	  nbits = 4;
746       }
747     }
748     int next = 1 << (nbits-1);
749 #endif
750     unsigned bstart;
751     for (bstart=0;bstart<basis.size();++bstart){
752       int p=basis[bstart].p;
753       if (p>next){
754 	if (debug_infolevel>7)
755 	  *logptr(contextptr) << gettext("Sieve first prime ") << p << " nbits " << nbits << '\n';
756 	break;
757       }
758 #ifdef LP_SMALL_PRIMES
759       int pos=small_basis[bstart].root1;
760       pos=(pos-ss)%p;
761       if (pos<0)
762 	pos+=p;
763       small_basis[bstart].root1=pos;
764       pos=small_basis[bstart].root2;
765       pos=(pos-ss)%p;
766       if (pos<0)
767 	pos+=p;
768       small_basis[bstart].root2=pos;
769 #else
770       // update pos_root_mod for later check
771       int pos=basis[bstart].root1;
772       pos=(pos-ss)%p;
773       if (pos<0)
774 	pos+=p;
775       basis[bstart].root1=pos;
776       pos=basis[bstart].root2;
777       pos=(pos-ss)%p;
778       if (pos<0)
779 	pos+=p;
780       basis[bstart].root2=pos;
781 #endif
782     }
783     next *= 2;
784     if (debug_infolevel>8)
785       *logptr(contextptr) << CLOCK() << gettext(" sieve begin ") << '\n';
786     // bool sameroot; // Should be there to avoid counting twice the same root but it's faster to ignore it..;
787 #ifdef LP_SMALL_PRIMES
788     small_basis_t * bit=&small_basis[bstart], * bitend=&small_basis[0]+small_basis.size();
789     core_sieve(slice,bit,bitend);
790 #else
791     basis_t * bit=&basis[bstart], * bitend=&basis[0]+bs;
792 #ifdef LP_TAB_SIZE
793     bitend=core_sieve(slice,ss,bit,&basis[0]+lp_basis_pos);
794 #else
795     bitend=core_sieve(slice,ss,bit,bitend);
796 #endif
797 #endif
798     slicetype * st=slice, * stend=slice+ss;
799 #ifdef LP_TAB_SIZE
800     // sieve for large prime using saved position
801     if (!lp_tab.empty()){
802       const lp_entry_t * lpit=&lp_tab[0],*lpitend=lpit+lp_tab.size(),*lpitend1=lpitend-8;
803       if (lpitend-lpit>8){
804 	for (;lpit<lpitend1;lpit+=8){
805 	  //PREFETCH(lpit + 16);
806 	  slice[lpit->pos] -= 16;
807 	  slice[lpit[1].pos] -= 16;
808 	  slice[lpit[2].pos] -= 16;
809 	  slice[lpit[3].pos] -= 16;
810 	  slice[lpit[4].pos] -= 16;
811 	  slice[lpit[5].pos] -= 16;
812 	  slice[lpit[6].pos] -= 16;
813 	  slice[lpit[7].pos] -= 16;
814 	}
815       }
816       for (;lpit<lpitend;++lpit)
817 	slice[lpit->pos] -= 16;
818     }
819 #endif
820     unsigned cl=0;
821     if (debug_infolevel>6)
822       cl=CLOCK();
823     if (debug_infolevel>8)
824       *logptr(contextptr) << cl << gettext("relations ") << '\n';
825     // now find relations
826     st=slice; stend=slice+ss;
827 #ifdef x86_64
828     ulonglong * st8=(ulonglong *) &slice[0],*st8end=st8+ss/8;
829 #else
830     unsigned * st4=(unsigned *) &slice[0],*st4end=st4+ss/4;
831 #endif
832     for (
833 #ifdef x86_64
834 	 ;st8!=st8end;st8+=4
835 #else
836 	 ;st4<st4end;st4+=8
837 #endif
838 	 ){
839       // compare slice[pos] to boundary
840 #ifdef x86_64
841       if ( !( (*st8  | st8[1] | st8[2] | st8[3] ) & 0x8080808080808080) )
842 	continue;
843       int pos=int(((slicetype*)st8)-slice);
844 #else
845       if ( !( (*st4  | st4[1] | st4[2] | st4[3] | st4[4] | st4[5] | st4[6] | st4[7]) & 0x80808080) )
846 	continue;
847       int pos=((slicetype*)st4)-slice;
848 #endif
849       st = slice+pos;
850       for (int stpos=0;stpos<32;++st,++pos,++stpos){
851 	if (!(*st&0x80))
852 	  continue;
853 	// factor (isqrtN+shift+pos)^2-N on basis
854 	curpuissances.clear(); recheck.clear();
855 	int shiftpos=shift+pos;
856 #if 0
857 	gen tmp=shiftpos;
858 	tmp=(a*tmp+2*bvals.back())*tmp+c;
859 	tmp.uncoerce(); mpz_set(z1,*tmp._ZINTptr);
860 	*logptr(contextptr) << tmp << '\n';
861 #else
862 	mpz_set_si(z1,shiftpos);
863 	mpz_mul(z2,z1,*a._ZINTptr);
864 	mpz_mul_2exp(z3,*bvals.back()._ZINTptr,1);
865 	mpz_add(z2,z2,z3);
866 	mpz_mul(z3,z1,z2);
867 	mpz_add(z1,z3,c);
868 #endif
869 	if (mpz_cmp_si(z1,0)<0){ // if (is_positive(-tmp,context0))
870 	  curpuissances.push_back(0xffff);
871 	  mpz_neg(z1,z1); // tmp=-tmp;
872 	}
873 	bool done=false;
874 #ifdef LP_TAB_SIZE
875 #ifdef LP_SMALL_PRIMES
876 	small_basis_t * basisptr=&small_basis[0], * basisend=basisptr+(bitend-bit);
877 #else
878 	basis_t * basisptr=&basis[0], * basisend=basisptr+(bitend-bit);
879 #endif
880 #else // LP_TAB_SIZE
881 	basis_t * basisptr=&basis[0], * basisend=basisptr+bs;
882 #endif
883 	// we have modified pos_root_mod1 and pos_root_mod2 -> posss
884 	int posss=ss-pos; // always positive
885 	for (;basisptr!=basisend;++basisptr){
886 	  register int bi=basisptr->p;
887 	  // check if we have a root
888 	  register int check=bi-(posss%bi);
889 	  if (check!=bi && check!=int(basisptr->root1) && check!=int(basisptr->root2))
890 	    continue;
891 	  if (check==bi && basisptr->root1 && basisptr->root2)
892 	    continue;
893 	  recheck.push_back(bi);
894 	} // end for on (small) primes
895 #ifdef LP_TAB_SIZE
896 	// add primes from large prime hashtable
897 	lp_tab_t::const_iterator lpit=lp_tab.begin(),lpend=lp_tab.end();
898 	int hash_pos=recheck.size();
899 	for (;lpit!=lpend;++lpit){
900 	  if (pos==int(lpit->pos)){
901 	    recheck.push_back(lpit->p);
902 	  }
903 	}
904 	if (int(recheck.size())>hash_pos+1)
905 	  sort(recheck.begin(),recheck.end());
906 #endif
907 	// now divide first by product of elements of recheck
908 	double prod=1,nextprod=1;
909 	for (unsigned k=0;k<recheck.size();++k){
910 	  nextprod=prod*recheck[k];
911 	  if (nextprod< 2147483648. )
912 	    prod=nextprod;
913 	  else {
914 	    // mpz_fdiv_q_ui(z1,z1,prod);
915 	    mpz_set_si(z2,int(prod));
916 #ifdef USE_GMP_REPLACEMENTS
917 	    mp_grow(&alloc1,z1.used+2);
918 	    mpz_set_ui(alloc1,0);
919 	    alloc1.used = z1.used +2 ;
920 	    mpz_set(alloc2,z1);
921 	    mpz_set(alloc3,z2);
922 	    alloc_mp_div(&z1,&z2,&z1,&z3,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
923 #else
924 	    mpz_divexact(z3,z1,z2);
925 	    mpz_swap(z1,z3);
926 #endif
927 	    prod=recheck[k];
928 	  }
929 	}
930 	if (prod!=1){
931 	  // mpz_fdiv_q_ui(z1,z1,prod);
932 	  mpz_set_si(z2,int(prod));
933 #ifdef USE_GMP_REPLACEMENTS
934 	  mp_grow(&alloc1,z1.used+2);
935 	  mpz_set_ui(alloc1,0);
936 	  alloc1.used = z1.used +2 ;
937 	  mpz_set(alloc2,z1);
938 	  mpz_set(alloc3,z2);
939 	  alloc_mp_div(&z1,&z2,&z1,&z3,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
940 #else
941 	  mpz_divexact(z3,z1,z2);
942 	  mpz_swap(z1,z3);
943 #endif
944 	}
945 	// then set curpuissances
946 	bool small_=false;
947 	int Z1=0;
948 	for (unsigned k=0;k<recheck.size();++k){
949 	  int j=0;
950 	  int bi=recheck[k];
951 #ifdef USE_GMP_REPLACEMENTS
952 	  if (!small_){
953 	    small_=mpz_sizeinbase(z1,2)<32;
954 	    if (small_)
955 	      Z1=mpz_get_si(z1);
956 	  }
957 	  if (small_){
958 	    for (++j;;++j){
959 #if 0 // def FXCG
960 	      if (Z1 % bi)
961 		break;
962 	      Z1 /= bi;
963 #else
964 	      div_t qr;
965 	      qr=div(Z1,bi);
966 	      if (qr.rem)
967 		break;
968 	      Z1=qr.quot;
969 #endif
970 	    }
971 	  }
972 	  else {
973 	    for (++j;;++j){
974 #if 1
975 	      mpz_set_ui(z2,bi);
976 	      mp_grow(&alloc1,z1.used+2);
977 	      mpz_set_ui(alloc1,0);
978 	      alloc1.used = z1.used +2 ;
979 	      mpz_set(alloc2,z1);
980 	      mpz_set(alloc3,z2);
981 	      alloc_mp_div(&z1,&z2,&z2,&z3,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
982 #else
983 	      mpz_fdiv_qr_ui(z2,z3,z1,bi);
984 #endif
985 	      if (mpz_cmp_si(z3,0))
986 		break;
987 	      mpz_set(z1,z2);
988 	    }
989 	  }
990 #else
991 	  for (++j;;++j){
992 	    mpz_fdiv_qr_ui(z2,z3,z1,bi);
993 	    if (mpz_cmp_si(z3,0))
994 	      break;
995 	    mpz_set(z1,z2);
996 	  }
997 #endif
998 	  /*
999 	    while (is_zero(smod(tmp,bi))){
1000 	    tmp=tmp/bi;
1001 	    ++j;
1002 	    }
1003 	  */
1004 	  if (!done && bi>255){
1005 	    curpuissances.push_back(0);
1006 	    done=true;
1007 	  }
1008 	  if (done){
1009 	    for (;j;--j)
1010 	      curpuissances.push_back(bi);
1011 	  }
1012 	  else {
1013 	    for (;j>=256;j-=256)
1014 	      curpuissances.push_back(bi<<8);
1015 	    if (j)
1016 	      curpuissances.push_back( (bi << 8) | j);
1017 	  }
1018 	}
1019 	if (small_)
1020 	  mpz_set_si(z1,Z1);
1021 	if (mpz_cmp_si(z1,1)==0){ // is_one(tmp)){
1022 	  ++nrelations;
1023 	  if (debug_infolevel>6)
1024 	    *logptr(contextptr) << CLOCK() << gettext(" true relation ") << '\n';
1025 	  axbmodn.push_back(axbinv(int(sqrtavals.size())-1,shiftpos,int(bvals.size())-1,int(puissancesptr-puissancesbegin),int(puissancesptr-puissancesbegin)+int(curpuissances.size())));
1026 	  for (unsigned i=0;i<curpuissances.size();++puissancesptr,++i){
1027 	    if (puissancesptr>=puissancesend)
1028 	      return -1;
1029 	    *puissancesptr=curpuissances[i];
1030 	  }
1031 	}
1032 	else {
1033 	  unsigned param2;
1034 #if (GIAC_ADDITIONAL_PRIMES==16)
1035 	  param2=0xffff;
1036 #else
1037 	  param2=maxadditional;
1038 #endif
1039 	  if (mpz_cmp_ui(z1,param2)>0){
1040 	    if (debug_infolevel>6)
1041 	      *logptr(contextptr) << gen(z1) << gettext(" Sieve large remainder:") << '\n';
1042 	  }
1043 	  else {
1044 #ifdef GIAC_ADDITIONAL_PRIMES
1045 	    additional_t P=mpz_get_ui(z1);
1046 	    // if (int(P)>2*int(basis.back())) continue;
1047 	    // if (debug_infolevel>5)
1048 	    if (debug_infolevel>6)
1049 	      *logptr(contextptr) << CLOCK() << " " << P << " remain " << '\n';
1050 #ifdef ADDITIONAL_PRIMES_HASHMAP
1051 	    // add relation
1052 	    ++nrelations;
1053 	    curpuissances.push_back(1); // marker
1054 #if (GIAC_ADDITIONAL_PRIMES==32)
1055 #ifndef PRIMES32
1056 	    curpuissances.push_back(P >> 16);
1057 #endif
1058 #endif
1059 	    curpuissances.push_back(P);
1060 	    for (unsigned i=0;i<curpuissances.size();++puissancesptr,++i){
1061 	      if (puissancesptr>=puissancesend)
1062 		return -1;
1063 	      *puissancesptr=curpuissances[i];
1064 	    }
1065 	    additional_map_t::iterator it=additional_primes_map.find(P),itend=additional_primes_map.end();
1066 	    if (it!=itend) // build a large prime relation (P is the large prime)
1067 	      axbmodn.push_back(axbinv(sqrtavals.size()-1,shiftpos,bvals.size()-1,(puissancesptr-puissancesbegin)-curpuissances.size(),(puissancesptr-puissancesbegin)));
1068 	    else // record a partial relation
1069 	      additional_primes_map[P]=axbinv(sqrtavals.size()-1,shiftpos,bvals.size()-1,(puissancesptr-puissancesbegin)-curpuissances.size(),(puissancesptr-puissancesbegin));
1070 #else
1071 	    int Ppos=_equalposcomp(additional_primes,P); // this is in O(additional^2)=o(B^3)
1072 	    if (Ppos){
1073 	      if (debug_infolevel>6)
1074 		*logptr(contextptr) << P << gettext(" already additional") << '\n';
1075 	      --Ppos;
1076 	      additional_primes_twice[Ppos]=true;
1077 	    } else {
1078 	      // add a prime in additional_primes if <=QS_B_BOUND
1079 	      if (int(additional_primes.size())>=4*bs
1080 #if defined(RTOS_THREADX) || defined(BESTA_OS) || defined NSPIRE
1081 		  || bs+additional_primes.size()>700
1082 #endif
1083 		  )
1084 		continue;
1085 	      additional_primes.push_back(P);
1086 	      additional_primes_twice.push_back(false);
1087 	      Ppos=int(additional_primes.size())-1;
1088 	    }
1089 	    // add relation
1090 	    curpuissances.push_back(1); // marker
1091 #if GIAC_ADDITIONAL_PRIMES==32
1092 #ifndef PRIMES32
1093 	    curpuissances.push_back(P >> 16);
1094 #endif
1095 #endif
1096 	    curpuissances.push_back(P);
1097 	    axbmodn.push_back(axbinv(int(sqrtavals.size())-1,shiftpos,int(bvals.size())-1,int(puissancesptr-puissancesbegin),int(puissancesptr-puissancesbegin)+int(curpuissances.size())));
1098 	    for (unsigned i=0;i<curpuissances.size();++puissancesptr,++i){
1099 	      if (puissancesptr>=puissancesend)
1100 		return -1;
1101 	      *puissancesptr=curpuissances[i];
1102 	    }
1103 #endif // ADDITIONAL_PRIMES_HASHMAP
1104 #endif // GIAC_ADDITIONAL_PRIMES
1105 	  }
1106 	}
1107       }
1108     } // end for loop on slice array
1109     if (debug_infolevel>6){
1110       unsigned cl2=CLOCK();
1111       *logptr(contextptr) << cl2 << gettext(" end relations ") << cl2-cl << '\n';
1112     }
1113     return nrelations;
1114   }
1115 
1116   // #define MP_MODINV_1
1117 #ifdef MP_MODINV_1
mp_modinv_1(unsigned a,unsigned p)1118   static inline unsigned mp_modinv_1(unsigned a, unsigned p) {
1119 
1120     unsigned ps1, ps2, dividend, divisor, rem, q, t;
1121     unsigned parity;
1122 
1123     q = 1; rem = a; dividend = p; divisor = a;
1124     ps1 = 1; ps2 = 0; parity = 0;
1125 
1126     while (divisor > 1) {
1127       rem = dividend - divisor;
1128       t = rem - divisor;
1129       if (rem >= divisor) { q += ps1; rem = t; t -= divisor;
1130 	if (rem >= divisor) { q += ps1; rem = t; t -= divisor;
1131 	  if (rem >= divisor) { q += ps1; rem = t; t -= divisor;
1132 	    if (rem >= divisor) { q += ps1; rem = t; t -= divisor;
1133 	      if (rem >= divisor) { q += ps1; rem = t; t -= divisor;
1134 		if (rem >= divisor) { q += ps1; rem = t; t -= divisor;
1135 		  if (rem >= divisor) { q += ps1; rem = t; t -= divisor;
1136 		    if (rem >= divisor) { q += ps1; rem = t;
1137 		      if (rem >= divisor) {
1138 			q = dividend / divisor;
1139 			rem = dividend % divisor;
1140 			q *= ps1;
1141 		      }
1142 		    }
1143 		  }
1144 		}
1145 	      }
1146 	    }
1147 	  }
1148 	}
1149       }
1150 
1151       q += ps2;
1152       parity = ~parity;
1153       dividend = divisor;
1154       divisor = rem;
1155       ps2 = ps1;
1156       ps1 = q;
1157     }
1158 
1159     if (parity == 0)
1160       return ps1;
1161     else
1162       return p - ps1;
1163   }
1164 #endif
1165 
1166 #if (defined __i386__ || defined __x86_64__) && !defined PIC && !defined _I386_ && !defined __APPLE__ && !defined VISUALC && !defined(FIR_LINUX) && !defined(FIR_ANDROID)
1167   #define _I386_
1168 #endif
1169 
1170 #ifdef _I386_
1171   // a->a+b*c mod m
addmultmod(int & a,int b,int c,int m)1172   inline void addmultmod(int & a,int b,int c,int m){
1173     asm volatile("testl %%ebx,%%ebx\n\t" /* sign bit=1 if negative */
1174 		 "jns .Lok%=\n\t"
1175 		 "addl %%edi,%%ebx\n" /* a+=m*/
1176 		 ".Lok%=:\t"
1177 		 "imull %%ecx; \n\t" /* b*c in edx:eax */
1178 		 "addl %%ebx,%%eax; \n\t" /* b*c+a */
1179 		 "adcl $0x0,%%edx; \n\t" /* b*c+a carry */
1180 		 "idivl %%edi; \n\t"
1181 		 :"=d"(a)
1182 		 :"a"(b),"b"(a),"c"(c),"D"(m)
1183 		 );
1184   }
1185 #endif
1186 
1187   inline
modmult(int a,int b,unsigned p)1188   int modmult(int a,int b,unsigned p){
1189 #ifdef _I386_
1190     register int res;
1191     asm volatile("imull %%edx\n\t" /* a*b-> edx:eax */
1192 		 "idivl %%ecx\n\t" /* edx:eax div p -> quotient=eax, remainder=edx */
1193 		 :"=d"(res)
1194 		 :"a"(a),"d"(b),"c"(p)
1195 		 :
1196 		 );
1197     return res;
1198 #else
1199     return a*longlong(b) % p;
1200 #endif
1201   }
1202 
1203   // assumes b>0 and |a|<b
invmodnoerr(int a,int b)1204   int invmodnoerr(int a,int b){
1205     if (a==1 || a==-1 || a==0)
1206       return a;
1207     if (a<0) // insure a>0 so that all remainders below are >=0
1208       a+=b;
1209 #ifdef _I386_ // works only for ushort_t == unsigned short
1210     // int res=mp_modinv_1(a,b),p=b;
1211     /* GDB: si will step in assembly, info registers show register content, x/i $pc show next ins */
1212     asm volatile("movl $0,%%edi\n\t"
1213 		 "movl $1,%%ecx\n\t"
1214 		 "movl $0,%%edx\n\t"
1215 		 ".Lloop%=:\t"
1216 		 "movl %%esi,%%eax\n\t"
1217 		 "andl $0x80000000,%%esi\n\t"
1218 		 "xorl $0x80000000,%%esi\n\t" /* parity indicator for sign */
1219 		 "andl $0x7fffffff,%%eax\n\t" /* clear high bit of ax */
1220 		 "divl %%ebx\n\t" /* divide si by bx, ax=quotient, dx=rem */
1221 		 "orl %%ebx,%%esi\n\t"  /* copy bx in si but keep high bit of si */
1222 		 "movl %%edx,%%ebx\n\t" /* si now contains bx and bx the remainder */
1223 		 "mull %%ecx\n\t" /* quotient*cx is in ax (dx=0) */
1224 		 "addl %%eax,%%edi\n\t" /* di <- di+q*cx*/
1225 		 "xchgl %%edi,%%ecx\n\t" /* cx <- origi di+q*cx, di <- orig cx */
1226 		 "testl %%ebx,%%ebx\n\t"
1227 		 "jne .Lloop%=\n\t"
1228 		 :"=D"(a),"=S"(b)
1229 		 :"S"(b),"b"(a)
1230 		 :"%eax","%ecx","%edx"
1231 		 );
1232     if (b<0)
1233       b=b&0x7fffffff;
1234     else
1235       a=-a;
1236     a=(b==1)?a:0;
1237     // if ((a-res)%p)
1238     //  CERR << "error" << '\n';
1239     return a;
1240 #else // i386
1241 
1242 #ifdef MP_MODINV_1
1243     return mp_modinv_1(a,b);
1244 #endif
1245     // r0=b=ab*a+1*b
1246     // r1=a=aa*a+0*b
1247     int aa(1),ab(0),ar(0);
1248 #if 0 // def FXCG
1249     ushort_t q,r;
1250     while (a){
1251       q=b/a;
1252       ar=ab-q*aa;
1253       r=b-q*a;
1254       if (!r)
1255 	return a==1?aa:0;
1256       q=a/r;
1257       ab=aa-q*ar;
1258       b=a-q*r;
1259       if (!b)
1260 	return r==1?ar:0;
1261       q=r/b;
1262       aa=ar-q*ab;
1263       a=r-q*b;
1264     }
1265     return b==1?ab:0;
1266 #else
1267     div_t qr;
1268     while (a){
1269       qr=div(b,a);
1270       ar=ab-qr.quot*aa;
1271       b=a;
1272       a=qr.rem;
1273       ab=aa;
1274       aa=ar;
1275     }
1276     if (b==1)
1277       return ab;
1278     return 0;
1279 #endif
1280 #endif // i386
1281   }
1282 
1283 #if 0 // def PRIMES32
1284   // assumes |a|<b
1285   longlong invmodnoerr(longlong a,longlong b){
1286     if (a==1 || a==-1 || a==0)
1287       return a;
1288     if (a<0) // insure a>0 so that all remainders below are >=0
1289       a+=b;
1290     // r0=b=ab*a+1*b
1291     // r1=a=aa*a+0*b
1292     longlong aa(1),ab(0),ar(0);
1293     longlong q,r;
1294     lldiv_t qr;
1295     while (a){
1296       qr=lldiv(b,a);
1297       ar=ab-qr.quot*aa;
1298       b=a;
1299       a=qr.rem;
1300       ab=aa;
1301       aa=ar;
1302     }
1303     if (b==1)
1304       return ab;
1305     return 0;
1306   }
1307 #endif
1308 
find_multiplier(const gen & n,double & delta,GIAC_CONTEXT)1309   static int find_multiplier(const gen & n,double & delta,GIAC_CONTEXT){
1310     delta=0;
1311     if (n.type!=_ZINT)
1312       return 1;
1313     static const unsigned char mult[] =
1314       { 1, 3, 5, 7, 11, 13, 15, 17, 19,
1315 	21, 23, 29, 31, 33, 35, 37, 39, 41, 43, 47}; // only odd values for multiplier
1316     unsigned nmult=sizeof(mult)/sizeof(unsigned char);
1317     double scores[50];
1318     int nmodp=modulo(*n._ZINTptr,8),knmodp;
1319     // init scores and set value for 2
1320     double ln2=std::log(2.0);
1321     for (unsigned i=0;i<nmult;++i){
1322       knmodp=(mult[i]*nmodp)%8;
1323       scores[i]=0.5*std::log(double(mult[i]));
1324       switch(knmodp){
1325       case 1:
1326 	scores[i] -= 2*ln2;
1327 	break;
1328       case 5:
1329 	scores[i] -= ln2;
1330 	break;
1331       case 3: case 7:
1332 	scores[i] -= 0.5 * ln2;
1333 	break;
1334       }
1335     }
1336     // now compute contribution for giac_primes[1..300]
1337     for (unsigned i=1;i<=300;++i){
1338       int p=giac_primes[i];
1339       double contrib=std::log(double(p))/(p-1);
1340       nmodp=modulo(*n._ZINTptr,p);
1341       for (unsigned j=0;j<nmult;++j){
1342 	knmodp=(nmodp*mult[j])%p;
1343 	if (knmodp==0)
1344 	  scores[j] -= contrib;
1345 	else {
1346 	  if (!is_undef(sqrt_mod(knmodp,p,true,context0)))
1347 	    scores[j] -= 2*contrib;
1348 	}
1349       }
1350     }
1351     // select the smallest scores
1352     int pos=0;
1353     double minscore=scores[0]-0.1;
1354     for (unsigned i=1;i<nmult;++i){
1355       if (scores[i]<minscore){
1356 	minscore=scores[i];
1357 	pos=i;
1358       }
1359     }
1360     if (debug_infolevel>6){
1361       for (unsigned i=0;i<nmult;++i){
1362 	*logptr(contextptr) << gettext("multiplier ") << int(mult[i]) << " score " << scores[i] << '\n';
1363       }
1364     }
1365     if (pos){
1366       delta=minscore-scores[0];
1367       if (debug_infolevel)
1368 	*logptr(contextptr) << gettext("Using multiplier ") << int(mult[pos]) << " delta-score " << delta << '\n';
1369     }
1370     return mult[pos];
1371   }
1372 
add_relation(vector<line_t> relations,unsigned j,ushort_t * curpui,ushort_t * curpuiend,const vector<basis_t> & basis,const vector<additional_t> & additional_primes)1373   void add_relation(vector<line_t> relations,unsigned j,ushort_t * curpui,ushort_t * curpuiend,const vector<basis_t> & basis,const vector<additional_t> & additional_primes){
1374     unsigned curpuisize=unsigned(curpuiend-curpui);
1375     bool done=false;
1376     unsigned i=0; // position in basis
1377     unsigned k=0; // position in curpui
1378     additional_t p=0; // prime
1379     unsigned bs=unsigned(basis.size());
1380     for (;k<curpuisize;++k){
1381       p=curpui[k];
1382       if (p==0xffff){
1383 	relations[0].tab[j/32] ^= (1 << (j%32));
1384 	continue;
1385       }
1386       if (p==0){
1387 	done=true;
1388 	continue;
1389       }
1390       if (p==1){
1391 #ifndef ADDITIONAL_PRIMES_HASHMAP
1392 	p=curpui[k+1];
1393 #if GIAC_ADDITIONAL_PRIMES==32
1394 #ifndef PRIMES32
1395 	p <<= 16;
1396 	p += curpui[k+2];
1397 #endif
1398 #endif
1399 	// k must be == curpui.size()-1
1400 	// find p in additional_primes and position
1401 	int Ppos=_equalposcomp(additional_primes,p);
1402 	// *logptr(contextptr) << p << " " << Ppos+bs << " " << relations.size() << '\n';
1403 	relations[bs+Ppos].tab[j/32] |= (1 << (j %32));
1404 #endif
1405 	break;
1406       }
1407       if (!done){
1408 	if (p%2==0) // even exponent?
1409 	  continue;
1410 	p >>= 8;
1411       }
1412       else {
1413 	int c=1;
1414 	for (;k+1<curpuisize;c++){
1415 	  if (curpui[k+1]==unsigned(p))
1416 	    ++k;
1417 	  else
1418 	    break;
1419 	}
1420 	if (c%2==0)
1421 	  continue;
1422       }
1423       // advance to next i in basis
1424       for (;i<bs;++i){
1425 	if (basis[i].p==unsigned(p))
1426 	  break;
1427       }
1428       if (i<bs){
1429 	++i;
1430 	relations[i].tab[j/32] ^= (1 << (j %32));
1431       }
1432       else {
1433 	// ERROR
1434       }
1435     } // end loop on k in curpui
1436   }
1437 
update_xy(axbinv & A,mpz_t & zx,mpz_t & zy,vector<short_t> & p,vector<short_t> & add_p,const gen & N,const vector<basis_t> & basis,const vector<additional_t> & additional_primes,const vecteur & sqrtavals,const vecteur & bvals,ushort_t * puissancestab,mpz_t & zq,mpz_t & zr,mpz_t & alloc1,mpz_t & alloc2,mpz_t & alloc3,mpz_t & alloc4,mpz_t & alloc5)1438   void update_xy(axbinv & A,mpz_t & zx,mpz_t & zy,vector<short_t> & p,vector<short_t> & add_p,const gen & N,const vector<basis_t> & basis,const vector<additional_t> & additional_primes,const vecteur & sqrtavals,const vecteur & bvals,ushort_t * puissancestab,mpz_t & zq,mpz_t & zr,mpz_t & alloc1, mpz_t & alloc2,mpz_t & alloc3,mpz_t & alloc4, mpz_t & alloc5){
1439     // x=x*(a*shiftpos+b), y =y*sqrta;
1440     mpz_set_si(alloc2,A.shiftpos);
1441     if (sqrtavals[A.aindex].type==_INT_){
1442       mpz_mul_ui(alloc1,alloc2,sqrtavals[A.aindex].val);
1443       mpz_mul_ui(alloc2,alloc1,sqrtavals[A.aindex].val);
1444       mpz_mul_ui(zy,zy,sqrtavals[A.aindex].val);
1445     }
1446     else {
1447       mpz_mul(alloc1,alloc2,*sqrtavals[A.aindex]._ZINTptr);
1448       mpz_mul(alloc2,alloc1,*sqrtavals[A.aindex]._ZINTptr);
1449       mpz_mul(zy,zy,*sqrtavals[A.aindex]._ZINTptr);
1450     }
1451     mpz_add(alloc1,alloc2,*bvals[A.bindex]._ZINTptr);
1452     // mpz_mul(alloc2,alloc1,*invsqrtamodnvals[A.aindex]._ZINTptr);
1453     mpz_mul(zr,zx,alloc1);
1454 #ifdef USE_GMP_REPLACEMENTS
1455     mp_grow(&alloc1,zr.used+2);
1456     mpz_set_ui(alloc1,0);
1457     alloc1.used = zr.used +2 ;
1458     mpz_set(alloc2,zr);
1459     mpz_set(alloc3,*N._ZINTptr);
1460     // mpz_set_si(alloc4,0);
1461     // mpz_set_si(alloc5,0);
1462     alloc_mp_div(&zr,N._ZINTptr,&zq,&zx,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
1463     mp_grow(&alloc1,zy.used+2);
1464     mpz_set_ui(alloc1,0);
1465     alloc1.used = zy.used +2 ;
1466     mpz_set(alloc2,zy);
1467     mpz_set(alloc3,*N._ZINTptr);
1468     // mpz_set_si(alloc4,0);
1469     // mpz_set_si(alloc5,0);
1470     alloc_mp_div(&zy,N._ZINTptr,&zq,&zy,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
1471 #else
1472     mpz_tdiv_r(zx,zr,*N._ZINTptr);
1473     mpz_tdiv_r(zy,zy,*N._ZINTptr);
1474 #endif
1475     bool done=false;
1476     unsigned bi=0;
1477     ushort_t * it=puissancestab+A.first,* itend=puissancestab+A.second;
1478     for (;it!=itend;++it){
1479       if (*it==0xffff)
1480 	continue;
1481       if (*it==1){
1482 	++it;
1483 	additional_t p=*it;
1484 #if GIAC_ADDITIONAL_PRIMES==32
1485 #ifndef PRIMES32
1486 	p <<= 16;
1487 	++it;
1488 	p += *it;
1489 #endif
1490 #endif
1491 	int pos=_equalposcomp(additional_primes,p);
1492 	if (pos)
1493 	  ++add_p[pos-1];
1494 	else {
1495 	  // otherwise ERROR!!!
1496 	}
1497 	break;
1498       }
1499       if (!*it){
1500 	done=true;
1501 	continue;
1502       }
1503       if (done){
1504 	while (bi<basis.size() && basis[bi].p!=*it)
1505 	  ++bi;
1506 	if (bi<basis.size())
1507 	  p[bi]++;
1508 	else {
1509 	  // ERROR
1510 	}
1511       }
1512       else {
1513 	while (basis[bi].p!=(*it>>8))
1514 	  ++bi;
1515 	p[bi]+=(*it&0xff);
1516       }
1517     }
1518   }
1519 
find_bv_be(int tmp,int & bv,int & be)1520   void find_bv_be(int tmp,int & bv,int &be){
1521     bv=1; be=-1;
1522     while (tmp%2==0){
1523       ++bv;
1524       tmp /= 2;
1525     }
1526     tmp /= 2;
1527     if (tmp%2)
1528       be=1;
1529     else
1530       be=-1;
1531   }
1532 
1533 
1534 #ifdef PRIMES32
1535   // Change b coeff of polynomial: update roots for small primes
1536   // for large primes do it depending on LP_TAB_TOGETHER
1537 #ifdef LP_SMALL_PRIMES
copy(vector<basis_t> & basis,vector<small_basis_t> & small_basis)1538   void copy(vector<basis_t> & basis,vector<small_basis_t> & small_basis){
1539     small_basis_t * small_basisptr=&small_basis[0], * small_basisend=small_basisptr+small_basis.size();
1540     basis_t * basisptr=&basis[0];
1541     unsigned next=2,logp=1;
1542     if (small_basis[0].p==0){
1543       for (;small_basisptr<small_basisend;++basisptr,++small_basisptr){
1544 	small_basisptr->root1=basisptr->root1;
1545 	small_basisptr->root2=basisptr->root2;
1546 	register unsigned short p =basisptr->p;
1547 	small_basisptr->p = p;
1548 	small_basisptr->logp=logp;
1549 	if (p>next){
1550 	  ++logp;
1551 	  next *= 2;
1552 	}
1553       }
1554     }
1555     else {
1556       for (;small_basisptr<small_basisend;++basisptr,++small_basisptr){
1557 	small_basisptr->root1=basisptr->root1;
1558 	small_basisptr->root2=basisptr->root2;
1559       }
1560     }
1561   }
1562 
switch_roots(const vector<int> & bainv2,vector<basis_t> & basis,vector<small_basis_t> & small_basis,unsigned lp_basis_pos,unsigned nslices,unsigned slicesize,unsigned bv,int be,int afact,const vector<ushort_t> & pos,gen b,mpz_t & zq,int M)1563   void switch_roots(const vector<int> & bainv2,vector<basis_t> & basis,vector<small_basis_t> & small_basis,unsigned lp_basis_pos,unsigned nslices,unsigned slicesize,unsigned bv,int be,int afact,const vector<ushort_t> & pos,gen b,mpz_t & zq,int M){
1564     unsigned bs=basis.size();
1565     const int * bvpos=&bainv2[(bv-1)*bs];
1566 #ifdef LP_TAB_TOGETHER
1567     const int * bvposend=bvpos+lp_basis_pos;
1568 #else
1569     const int * bvposend=bvpos+bs;
1570 #endif
1571     basis_t * basisptr=&basis[0];
1572     if (be>0){
1573       for (;bvpos<bvposend;++basisptr,++bvpos){
1574 	// PREFETCH(basisptr+4);
1575 	// PREFETCH(bvpos+4);
1576 	register unsigned p=basisptr->p;
1577 	register int r=basisptr->root1-(*bvpos);
1578 	if (r<0)
1579 	  r+=p;
1580 	basisptr->root1=r;
1581 	r=basisptr->root2-(*bvpos);
1582 	if (r<0)
1583 	  r+=p;
1584 	basisptr->root2=r;
1585       }
1586     }
1587     else {
1588       for (;bvpos<bvposend;++basisptr,++bvpos){
1589 	// PREFETCH(basisptr+4);
1590 	// PREFETCH(bvpos+4);
1591 	register unsigned p=basisptr->p;
1592 	register int r=basisptr->root1+(*bvpos);
1593 	if (r>p)
1594 	  r-=p;
1595 	basisptr->root1=r;
1596 	r=basisptr->root2+(*bvpos);
1597 	if (r>p)
1598 	  r-=p;
1599 	basisptr->root2=r;
1600       }
1601     }
1602     // adjust sieve position for prime factors of a,
1603     for (int j=0;j<afact;++j){
1604       int pj=pos[j];
1605       ushort_t p=basis[pj].p;
1606       int q,bmodp=p-modulo(*b._ZINTptr,p);
1607       int cmodp=modulo(zq,p);
1608       q=(M+longlong(cmodp)*invmodnoerr((2*bmodp)%p,p))%p;
1609       if (q<0)
1610 	q+=p;
1611       basis[pj].root1=q;
1612       basis[pj].root2=q;
1613     }
1614     // set small primes position for sieving
1615     copy(basis,small_basis);
1616   }
1617 
1618 #else // LP_SMALL_PRIMES
1619 
switch_roots(const vector<int> & bainv2,vector<basis_t> & basis,unsigned lp_basis_pos,unsigned nslices,unsigned slicesize,unsigned bv,int be,int afact,const vector<ushort_t> & pos,gen b,mpz_t & zq,int M)1620   void switch_roots(const vector<int> & bainv2,vector<basis_t> & basis,unsigned lp_basis_pos,unsigned nslices,unsigned slicesize,unsigned bv,int be,int afact,const vector<ushort_t> & pos,gen b,mpz_t & zq,int M){
1621     unsigned bs=basis.size();
1622 #ifdef LP_TAB_SIZE
1623     const int * bvpos=&bainv2[(bv-1)*bs],* bvposend=bvpos+lp_basis_pos;
1624 #else
1625     const int * bvpos=&bainv2[(bv-1)*bs],* bvposend=bvpos+bs;
1626 #endif
1627     basis_t * basisptr=&basis[0];
1628     unsigned decal0=nslices*slicesize;
1629     if (decal0>=basis.back().p){
1630       if (be<0){
1631 	for (;bvpos<bvposend;++basisptr,++bvpos){
1632 	  register unsigned p=basisptr->p;
1633 	  register unsigned decal = (decal0+(*bvpos))% p;
1634 	  register unsigned r=basisptr->root1+decal;
1635 	  if (r>p)
1636 	    r -= p;
1637 	  basisptr->root1 = r;
1638 	  r = basisptr->root2+decal;
1639 	  if (r>p)
1640 	    r -= p;
1641 	  basisptr->root2 = r;
1642 	}
1643       }
1644       else {
1645 	for (;bvpos<bvposend;++basisptr,++bvpos){
1646 	  register unsigned p=basisptr->p;
1647 	  register unsigned decal = (decal0-(*bvpos))% p;
1648 	  register unsigned r=basisptr->root1+decal;
1649 	  if (r>p)
1650 	    r -= p;
1651 	  basisptr->root1 = r;
1652 	  r = basisptr->root2+decal;
1653 	  if (r>p)
1654 	    r -= p;
1655 	  basisptr->root2 = r;
1656 	}
1657       }
1658     }
1659     else
1660       { // should not be reached since Mtarget is about basis.back()
1661 	for (;bvpos<bvposend;++basisptr,++bvpos){
1662 	  register unsigned p=basisptr->p;
1663 	  register unsigned decal = (decal0+p-be*(*bvpos))% p;
1664 	  register unsigned r=basisptr->root1+decal;
1665 	  if (r>p)
1666 	    r -= p;
1667 	  basisptr->root1 = r;
1668 	  r = basisptr->root2+decal;
1669 	  if (r>p)
1670 	    r -= p;
1671 	  basisptr->root2 = r;
1672 	}
1673       }
1674     // adjust sieve position for prime factors of a,
1675     for (int j=0;j<afact;++j){
1676       int pj=pos[j];
1677       ushort_t p=basis[pj].p;
1678       int q,bmodp=p-modulo(*b._ZINTptr,p);
1679       int cmodp=modulo(zq,p);
1680       q=(M+longlong(cmodp)*invmodnoerr((2*bmodp)%p,p))%p;
1681       if (q<0)
1682 	q+=p;
1683       basis[pj].root1=q;
1684       basis[pj].root2=q;
1685     }
1686 #if defined(LP_TAB_SIZE) && !defined(LP_TAB_TOGETHER)
1687     bvposend += bs-lp_basis_pos;
1688     if (be>0){
1689       for (;bvpos<bvposend;++basisptr,++bvpos){
1690 	// PREFETCH(basisptr+4);
1691 	// PREFETCH(bvpos+4);
1692 	register unsigned p=basisptr->p;
1693 	register int r=basisptr->root1-(*bvpos);
1694 	if (r<0)
1695 	  r+=p;
1696 	basisptr->root1=r;
1697 	r=basisptr->root2-(*bvpos);
1698 	if (r<0)
1699 	  r+=p;
1700 	basisptr->root2=r;
1701       }
1702     }
1703     else {
1704       for (;bvpos<bvposend;++basisptr,++bvpos){
1705 	// PREFETCH(basisptr+4);
1706 	// PREFETCH(bvpos+4);
1707 	register unsigned p=basisptr->p;
1708 	register int r=basisptr->root1+(*bvpos);
1709 	if (r>int(p))
1710 	  r-=p;
1711 	basisptr->root1=r;
1712 	r=basisptr->root2+(*bvpos);
1713 	if (r>int(p))
1714 	  r-=p;
1715 	basisptr->root2=r;
1716       }
1717     }
1718 #endif
1719   }
1720 #endif // LP_SMALL_PRIMES
1721 #endif // PRIMES32
1722 
1723   // Change a, the leading coeff of polynomial: initialize all roots (small and large primes)
init_roots(vector<basis_t> & basis,vector<small_basis_t> & small_basis,vector<ushort_t> & Inva,const vector<ushort_t> & sqrtmod,vector<int> & bainv2,int afact,int afact0,const gen & a,const gen & b,const vecteur & bvalues,mpz_t & zq,unsigned M)1724   void init_roots(vector<basis_t> & basis,
1725 #ifdef LP_SMALL_PRIMES
1726 		  vector<small_basis_t> & small_basis,
1727 #endif
1728 #ifdef WITH_INVA
1729 		  vector<ushort_t> & Inva,
1730 #endif
1731 #ifdef SQRTMOD_OUTSIDE
1732 		  const vector<ushort_t> & sqrtmod,
1733 #endif
1734 #ifdef PRIMES32
1735 		  vector<int> & bainv2,int afact,int afact0,
1736 #else
1737 		  ulonglong usqrta,
1738 #endif
1739 		  const gen & a,const gen & b,const vecteur & bvalues,mpz_t & zq,unsigned M){
1740     unsigned bs=unsigned(basis.size());
1741     basis_t * basisptr=&basis.front(),*basisend=basisptr+bs;
1742 #ifdef SQRTMOD_OUTSIDE
1743     vector<ushort_t>::const_iterator sqrtmodit=sqrtmod.begin();
1744 #endif
1745     for (int i=0;basisptr!=basisend;++i,++basisptr){
1746       ushort_t p=basisptr->p;
1747       // find inverse of a mod p
1748 #ifdef PRIMES32
1749       int j=invmodnoerr(modulo(*a._ZINTptr,p),p);
1750       // deltar[i]=((2*ulonglong(basis[i].sqrtmod))*j)%p;
1751 #else // PRIMES32
1752       unsigned modu=usqrta%p;
1753       modu=(modu*modu)%p;
1754       int j=invmodnoerr(modu,p);
1755 #endif // PRIMES32
1756       if (j<0)
1757 	j += p;
1758       unsigned inva=j;
1759 #ifdef WITH_INVA
1760       Inva[i]=inva;
1761 #else
1762 #ifdef PRIMES32
1763       // set roots change values for all b coeffs for this a
1764       if (afact>afact0){
1765 	int * ptr=&bainv2[i];
1766 	for (int j=1;j<afact;ptr+=bs,++j){
1767 	  // PREFETCH(ptr+bs);
1768 	  *ptr=modmult(modulo(*bvalues[j]._ZINTptr,p),2*inva,p);
1769 	}
1770       }
1771 #endif // PRIMES32
1772 #endif // WITH_INVA
1773       // compute roots mod p
1774 #ifdef SQRTMOD_OUTSIDE
1775       ushort_t sqrtm=*sqrtmodit;
1776       ++sqrtmodit;
1777 #else
1778       ushort_t sqrtm=basisptr->sqrtmod;
1779 #endif
1780       int bmodp=p-modulo(*b._ZINTptr,p);
1781       if (inva){
1782 	if (p<=37000){
1783 	  // sqrtm<=p/2, bmodp<p, inva<p hence (bmodp+sqrtm)*inva<=(3p/2-1)*(p-1)
1784 	  // this leaves M up to about 203 millions
1785 	  basisptr->root1=(M+(bmodp+sqrtm)*inva) % p;
1786 	  basisptr->root2=(M+(bmodp+p-sqrtm)*inva) % p;
1787 	  continue;
1788 	}
1789 #ifdef _I386_
1790 	register int q=M;
1791 	addmultmod(q,bmodp+sqrtm,inva,p);
1792 	basisptr->root1=q;
1793 	q=M;
1794 	addmultmod(q,bmodp+p-sqrtm,inva,p);
1795 	basisptr->root2=q;
1796 #else
1797 	basisptr->root1=(M+longlong(bmodp+sqrtm)*inva) % p;
1798 	basisptr->root2=(M+longlong(bmodp+p-sqrtm)*inva) % p;
1799 #endif
1800 	continue;
1801       }
1802       int cmodp=modulo(zq,p);
1803       int q=(M+longlong(cmodp)*invmodnoerr((2*bmodp)%p,p))%p;
1804       if (q<0)
1805 	q+=p;
1806       basisptr->root2=q;
1807       basisptr->root1=q;
1808     }
1809 #ifdef WITH_INVA
1810 #ifdef PRIMES32
1811     if (afact>afact0){
1812       int * bainv2ptr=&bainv2.front();
1813       basis_t * basisptr,*basisend=&basis.front()+bs;
1814       for (int j=1;j<afact;++j){
1815 	if (bvalues[j].type==_INT_){
1816 	  int bjj=bvalues[j].val;
1817 	  vector<ushort_t>::const_iterator invait=Inva.begin();
1818 	  for (basisptr=&basis.front();basisptr<basisend;++invait,++bainv2ptr,++basisptr){
1819 	    register int r=(bjj*longlong(2*(*invait))) % basisptr->p;
1820 	    if (r<0)
1821 	      r += basisptr->p;
1822 	    *bainv2ptr=r;
1823 	  }
1824 	}
1825 	else {
1826 	    // longlong up1=up1tmp[2*j];
1827 	    // longlong tmp=up1tmp[2*j+1];
1828 	    // tmp is <= P^2 where P is the largest factor of a
1829 	  mpz_t & bz=*bvalues[j]._ZINTptr;
1830 	  vector<ushort_t>::const_iterator invait=Inva.begin();
1831 	  for (basisptr=&basis.front();basisptr<basisend;++invait,++bainv2ptr,++basisptr){
1832 	    register int p=basisptr->p;
1833 	    *bainv2ptr=((modulo(bz,p))*longlong(2*(*invait))) % p;
1834 	  }
1835 	}
1836       }
1837     }
1838 #endif // PRIMES32
1839 #endif // WITH_INVA
1840 
1841 #ifdef LP_SMALL_PRIMES // copy primes<2^16 into small_basis
1842     copy(basis,small_basis);
1843 #endif
1844   }
1845 
1846   // find relations using (a*x+b)^2=a*(a*x^2+b*x+c) mod n where
1847   // we sieve on [-M,M] for as many polynomials as required
1848   // a is a square, approx sqrt(2*n)/M, and n is a square modulo all primes dividing a
1849   // b satisifies b^2=n mod a (b in [0,a[)
1850   // c=(n-b^2)/a
msieve(const gen & n_orig,gen & pn,GIAC_CONTEXT)1851   bool msieve(const gen & n_orig,gen & pn,GIAC_CONTEXT){
1852     if (n_orig.type!=_ZINT)
1853       return false;
1854     // find multiplier
1855     double delta;
1856     int multiplier=find_multiplier(n_orig,delta,contextptr);
1857     gen N(multiplier*n_orig);
1858     double Nd=evalf_double(N,1,contextptr)._DOUBLE_val;
1859 #if defined RTOS_THREADX || defined NSPIRE
1860     if (Nd>1e40) return false;
1861 #endif
1862 #ifdef BESTA_OS
1863     if (Nd>1e40) return false;
1864 #endif
1865 #ifdef PRIMES32
1866     if (Nd>1e76) return false;
1867 #else
1868     if (Nd>1e63) return false;
1869 #endif
1870     int Ndl=int(std::log10(Nd)-std::log10(double(multiplier))+.5); // +2*delta);
1871 #ifdef LP_TAB_SIZE
1872     int slicesize=(1 << LP_TAB_SIZE);
1873 #else
1874     int slicesize=(QS_SIZE>=65536 && Ndl<61)?32768:QS_SIZE;
1875 #endif
1876     double B=std::exp(std::sqrt(2.0)/4*std::sqrt(std::log(Nd)*std::log(std::log(Nd))))*0.45;
1877     if (B<200) B=200;
1878     int pos1=70,pos0=23,afact=2,afixed=0; // pos position in the basis, afact number of factors
1879     // FIXME Will always include the 3 first primes of the basis
1880     // set a larger Mtarget gives less polynomials but also use less memory
1881 #if defined(RTOS_THREADX) || defined(RTOS_THREADX) || defined NSPIRE
1882     double Mtarget=0.95e5;
1883     if (Nd>1e36)
1884       Mtarget=1.2e5;
1885 #else
1886     double Mtarget=0.55e5;
1887 #ifndef USE_MORE_PRIMES // FIXME improve! in fact use more primes on Core, less on Opteron
1888     if (Ndl>=50){
1889       Ndl-=50;
1890       short int Btab[]={
1891 	// 50
1892 	1900,2100,2300,2500,2700,2900,3100,3400,3700,4000,
1893 	// 60
1894 	4300,4600,4900,5300,5700,6200,6800,7500,8300,9200,
1895 	// 70
1896 	10000,11000,12000,13000,14000,15000,16000
1897       };
1898       if (Ndl<sizeof(Btab)/sizeof(short int))
1899 	B=Btab[Ndl];
1900       Mtarget=0.66e5;
1901       if (Ndl>7)
1902 	Mtarget=0.95e5;
1903       if (Ndl>11)
1904 	Mtarget=1.3e5;
1905       if (Ndl>15)
1906 	Mtarget=1.6e5;
1907       if (Ndl>19)
1908 	Mtarget=1.92e5;
1909     }
1910 #else
1911     if (Ndl>=50)
1912       Mtarget=0.85e5;
1913     if (Ndl>65)
1914       Mtarget=1.3e5;
1915 #endif
1916 #endif
1917     if (debug_infolevel)
1918       *logptr(contextptr) << "" << CLOCK() << gettext(" sieve on ") << N << '\n' << gettext("Number of primes ") << B << '\n';
1919     // first compute the prime basis and sqrt(N) mod p, p in basis
1920     vector<basis_t> basis;
1921     basis.reserve(unsigned(B));
1922 #ifdef SQRTMOD_OUTSIDE
1923     vector<ushort_t> sqrtmod;
1924     sqrtmod.reserve(basis.capacity());
1925     basis.push_back(2);
1926     sqrtmod.push_back(1);
1927 #else
1928     basis.push_back(basis_t(2,1)); // I assume that N is odd... hence has sqrt 1 mod 2
1929 #endif
1930     N.uncoerce();
1931     // vector<ushort_t> N256;
1932     int i;
1933     mpz_t zx,zy,zq,zr;
1934     mpz_init(zx); mpz_init(zy); mpz_init(zq); mpz_init(zr);
1935     // fastsmod_prepare(N,zx,zy,zr,N256);
1936     for (i=1;i<int(sizeof(giac_primes)/sizeof(short));++i){
1937 #ifdef TIMEOUT
1938       control_c();
1939 #endif
1940       if (ctrl_c || interrupted)
1941 	break;
1942       ushort_t j=giac_primes[i];
1943       if (debug_infolevel>6 && (i%500==99))
1944 	*logptr(contextptr) << CLOCK() << gettext(" sieve current basis size ") << basis.size() << '\n';
1945 #if 1 // def USE_GMP_REPLACEMENTS
1946       // int n=fastsmod_compute(N256,j);
1947       int n=modulo(*N._ZINTptr,j),s;
1948 #else
1949       int n=smod(N,j).val,s;
1950 #endif
1951       if (n<0)
1952 	n+=j;
1953       if (n==0){
1954 #ifdef SQRTMOD_OUTSIDE
1955 	basis.push_back(j);
1956 	sqrtmod.push_back(0);
1957 #else
1958 	basis.push_back(basis_t(j,0));
1959 #endif
1960       }
1961       else {
1962 	if (powmod(n,(unsigned long)((j-1)/2),(int)j)==1){
1963 	  s=sqrt_mod(n,int(j),true,contextptr).val;
1964 	  if (s<0)
1965 	    s+=j;
1966 #ifdef SQRTMOD_OUTSIDE
1967 	  basis.push_back(j);
1968 	  sqrtmod.push_back(s);
1969 #else
1970 	  basis.push_back(basis_t(j,s));
1971 #endif
1972 	}
1973       }
1974       if (basis.size()>=B)
1975 	break;
1976     }
1977     vector<unsigned> crible;
1978     int jp=0;
1979     if (basis.size()<B){
1980 #ifdef PRIME_SIEVE
1981       fill_crible(crible,int(2.5*B*std::log(B)));
1982       jp=nextprime(crible,basis.back().p+1);
1983 #else
1984       jp=nextprime(int(basis.back().p+1)).val;
1985 #endif
1986     }
1987     unsigned lp_basis_pos=0; // position of first prime > 2^16 in the basis
1988     for (;basis.size()<B;++i){
1989 #ifdef TIMEOUT
1990       control_c();
1991 #endif
1992       if (ctrl_c || interrupted)
1993 	break;
1994 #ifndef PRIMES32
1995       if (jp>65535){
1996 	break;
1997       }
1998 #endif
1999       if (debug_infolevel>6 && (i%500==99))
2000 	*logptr(contextptr) << CLOCK() << gettext(" sieve current basis size ") << basis.size() << '\n';
2001 #if 1 // def USE_GMP_REPLACEMENTS
2002       // int n=fastsmod_compute(N256,jp);
2003       int n=modulo(*N._ZINTptr,jp),s;
2004 #else
2005       int n=smod(N,jp).val,s;
2006 #endif
2007       if (n<0)
2008 	n+=jp;
2009       if (powmod(n,(unsigned long)((jp-1)/2),jp)==1){
2010 	s=sqrt_mod(n,jp,true,contextptr).val;
2011 	if (s<0)
2012 	  s += jp;
2013 #ifdef LP_TAB_SIZE
2014 	if (!lp_basis_pos && jp> (1<<LP_BIT_LIMIT))
2015 	  lp_basis_pos=basis.size();
2016 #endif
2017 #ifdef SQRTMOD_OUTSIDE
2018 	basis.push_back(jp);
2019 	sqrtmod.push_back(s);
2020 #else
2021 	basis.push_back(basis_t(jp,s));
2022 #endif
2023       }
2024 #ifdef PRIME_SIEVE
2025       jp=nextprime(crible,jp+1);
2026 #else
2027       jp=nextprime(int(jp+1)).val;
2028 #endif
2029     }
2030     if (!lp_basis_pos)
2031       lp_basis_pos=unsigned(basis.size());
2032 #ifdef LP_SMALL_PRIMES
2033     vector<small_basis_t> small_basis(lp_basis_pos); // will be filled by primes<2^16
2034 #endif
2035 #ifdef TIMEOUT
2036     control_c();
2037 #endif
2038     if (ctrl_c || interrupted){
2039       mpz_clear(zx); mpz_clear(zy); mpz_clear(zq);  mpz_clear(zr);
2040       return false;
2041     }
2042     double dtarget=1.1;
2043     if (Mtarget<basis.back().p*dtarget){
2044       Mtarget=basis.back().p*dtarget; // (int(basis.back().p*1.1)/slicesize)*slicesize;
2045     }
2046     unsigned ps=sizeinbase2(basis.back().p);
2047 #if !defined(RTOS_THREADX) && !defined(BESTA_OS) && !defined NSPIRE // def USE_MORE_PRIMES
2048     unsigned maxadditional=(2+(basis.back().p>>16))*basis.back().p*ps;
2049 #else
2050     unsigned maxadditional=3*basis.back().p*ps;
2051 #endif
2052     if (debug_infolevel)
2053       *logptr(contextptr) << CLOCK() << gettext(" sieve basis OK, size ") << basis.size() << " largest prime in basis " << basis.back().p << " large prime " << maxadditional << " Mtarget " << Mtarget << '\n' ;
2054     int bs=int(basis.size());
2055     gen isqrtN=isqrt(N);
2056     isqrtN.uncoerce();
2057     // now compare isqrtN to a^2 for a in the basis
2058     double seuil=1.414*evalf_double(isqrtN,1,contextptr)._DOUBLE_val/Mtarget; // should be a
2059     seuil=std::sqrt(seuil); // should be product of primes of the basis
2060 #ifdef OLD_AFACT
2061     double dfactors=std::log10(seuil)/3;
2062     // fixed primes are choosen at basis[pos0], variables are choosen around 2000
2063     afact=int(dfactors+.5);
2064     if (afact<=1){
2065       afact=1;
2066       int i=20;
2067       for (;i<3*bs/4;++i){
2068 	if (seuil<basis[i].p){
2069 	  pos1=i;
2070 	  break;
2071 	}
2072       }
2073       if (i>=3*bs/4){
2074 	afact=2;
2075 	for (;i<3*bs/4;++i){
2076 	  if (seuil<basis[i].p){
2077 	    pos1=i;
2078 	    break;
2079 	  }
2080 	}
2081       }
2082     }
2083     else {
2084       if (afact==2){
2085 	seuil=std::sqrt(seuil);
2086 	for (int i=20;i<3*bs/4;++i){
2087 	  if (seuil<basis[i].p){
2088 	    pos1=i;
2089 	    break;
2090 	  }
2091 	}
2092       }
2093       else { // afact>=3,
2094 	if (dfactors>5.4){
2095 	  dfactors -= 3; // 3 large primes
2096 	  afixed = dfactors/.8; // at least 3 fixed
2097 	  afact = 3 + afixed;
2098 	}
2099 	else {
2100 	  dfactors -= 2; // 2 large primes
2101 	  afixed = dfactors/.8;
2102 	  if (afixed==0)
2103 	    afixed=1;
2104 	  afact = 2 +afixed;
2105 	}
2106 	for (int i=0;i<afixed;++i){
2107 	  seuil=seuil/basis[pos0+i].p;
2108 	}
2109 	seuil=std::pow(seuil,1./(afact-afixed));
2110 	for (int i=pos0+afixed+10;i<3*bs/4;++i){
2111 	  if (seuil<basis[i].p){
2112 	    pos1=i;
2113 	    break;
2114 	  }
2115 	}
2116       }
2117     }
2118 #else // OLD_AFACT
2119     double logprod=std::log10(seuil);
2120     if (logprod<9){
2121       afixed=0;
2122       afact=int(std::ceil(logprod/3));
2123       if (logprod-3*afact<-1)
2124 	afixed=1;
2125     }
2126     else {
2127       double logfixed=std::log10(double(basis[pos0].p));
2128       int maxfixed=int(logprod/logfixed)-2;
2129       if (maxfixed==0) maxfixed=1;
2130       double curseuil=1e10;
2131       afact=0;
2132       for (int i=1;i<=maxfixed;++i){
2133 	double variable=(logprod-i*logfixed)/3; // we want variable primes to be around 1000
2134 	int ivariable=int(variable);
2135 	double seuiltest=variable/ivariable;
2136 	if (i+ivariable>afact){
2137 	  afixed=i;
2138 	  afact=i+ivariable;
2139 	  curseuil=seuiltest;
2140 	}
2141       }
2142     }
2143     for (int i=0;i<afixed;++i)
2144       seuil=seuil/basis[pos0+i].p;
2145     seuil=std::pow(seuil,1./(afact-afixed));
2146     for (int i=pos0+afixed+10;i<3*bs/4;++i){
2147       if (seuil<basis[i].p){
2148 	pos1=i-1; // -afact/2;
2149 	break;
2150       }
2151     }
2152 #endif // OLD_AFACT
2153     if (debug_infolevel){
2154       *logptr(contextptr) << gettext("Using ") << afact << " square factors per a coefficient in polynomials" << '\n';
2155       *logptr(contextptr) << afixed << gettext(" fixed begin at ") << basis[pos0].p << " and " << afact-afixed << " variables at " << basis[pos1].p << '\n';
2156     }
2157     vector<ushort_t> isqrtN256;
2158     // fastsmod_prepare(isqrtN,zx,zy,zr,isqrtN256);
2159     vector<short_t> isqrtNmodp(bs);
2160     for (int i=0;i<bs;++i){
2161 #if 1
2162       // isqrtNmodp[i]=fastsmod_compute(isqrtN256,basis[i].p);
2163       isqrtNmodp[i]=modulo(*isqrtN._ZINTptr,basis[i].p);
2164 #else
2165       isqrtNmodp[i]=smod(isqrtN,basis[i].p).val;
2166 #endif
2167     }
2168 #if defined(RTOS_THREADX) || defined(BESTA_OS) || defined NSPIRE
2169     unsigned puissancestablength=10000;
2170 #else
2171 #if 1 // def USE_MORE_PRIMES
2172     unsigned puissancestablength=bs*(80+bs/500);
2173 #else
2174     unsigned puissancestablength=bs*80;
2175 #endif
2176 #endif
2177     ushort_t * puissancestab=new ushort_t[puissancestablength];
2178     ushort_t * puissancesptr=puissancestab;
2179     ushort_t * puissancesend=puissancestab+puissancestablength;
2180     slicetype * slice=0;
2181     if (puissancestab)
2182       slice=new slicetype[QS_SIZE];
2183     if (!slice){
2184       mpz_clear(zx); mpz_clear(zy); mpz_clear(zq);  mpz_clear(zr);
2185       return false;
2186     }
2187     // relations will be written in column
2188     vector<axbinv> axbmodn; // contains (sqrta,b,x)
2189     vector<additional_t> additional_primes;
2190 #ifndef ADDITIONAL_PRIMES_HASHMAP
2191     vector<bool> additional_primes_twice;
2192 #endif
2193 #ifdef LP_TAB_SIZE
2194     vector<lp_tab_t> lp_map(128); // at most 128 slices in a sieve
2195 #endif
2196     vecteur sqrtavals,bvals;
2197 #ifdef GIAC_ADDITIONAL_PRIMES
2198 #ifdef ADDITIONAL_PRIMES_HASHMAP
2199 #ifdef EMCC
2200     additional_map_t additional_primes_map;
2201 #else
2202     additional_map_t additional_primes_map(8*bs);
2203 #endif
2204     axbmodn.reserve(bs);
2205 #else
2206 #if defined(RTOS_THREADX) || defined(BESTA_OS) || defined NSPIRE
2207     additional_primes.reserve(bs);
2208     additional_primes_twice.reserve(bs);
2209     axbmodn.reserve(2*bs);
2210 #else
2211     additional_primes.reserve(4*bs);
2212     additional_primes_twice.reserve(4*bs);
2213     axbmodn.reserve(5*bs);
2214 #endif
2215     sqrtavals.reserve(bs/7);
2216     bvals.reserve(2*bs/7);
2217 #endif // ADDITIONAL_PRIMES_HASHMAP
2218 #else // GIAC_ADDITIONAL_PRIMES
2219     axbmodn.reserve(bs+1);
2220 #endif
2221     // now sieve
2222     unsigned todo_rel;
2223     unsigned marge=bs/100;
2224     if (marge<15)
2225       marge=15;
2226     mpz_t alloc1,alloc2,alloc3,alloc4,alloc5;
2227     mpz_init(alloc1); mpz_init(alloc2); mpz_init(alloc3); mpz_init(alloc4); mpz_init(alloc5);
2228     // vector<ushort_t> a256,b256,tmpv;
2229     vector<ushort_t> curpuissances,recheck,pos(afact);
2230 #ifdef WITH_INVA
2231     vector<ushort_t> Inva(bs);
2232 #endif
2233     vecteur bvalues; // will contain values of b if afact<=afact0 or components of b if afact>afact0
2234     // array for efficient polynomial switch (same a change b) when at least afact0 factors/a
2235 #ifdef PRIMES32
2236     const int afact0=3;
2237     vector<int> bainv2((afact-1)*bs);
2238     vector<longlong> up1tmp;
2239 #endif
2240     for (int i=0;i<afixed;++i)
2241       pos[i]=pos0+i;
2242     for (int i=afixed;i<afact;++i)
2243       pos[i]=pos1+i-afixed; // FIXME should be -afixed
2244     double Mval=1;
2245     for (int i=0;i<afact;++i)
2246       Mval=Mval*basis[pos[i]].p;
2247     Mval=std::sqrt(2*Nd)/(Mval*Mval);
2248     if (debug_infolevel)
2249       *logptr(contextptr) << gettext("First M ") << Mval << '\n';
2250     Mtarget=Mval;
2251     int avar=afact-afixed;
2252     int end_pos1=2*pos1;
2253     if (avar>1)
2254       end_pos1=pos1+100;
2255     if (avar>2)
2256       end_pos1=pos1+30;
2257     if (int(lp_basis_pos)<end_pos1)
2258       end_pos1=lp_basis_pos;
2259     for (;puissancesptr<puissancesend;++pos.back()){
2260       double bpos2=1;
2261       if (int(pos.back())>=end_pos1 || basis[pos.back()].p>=45000){
2262 	int i=afact-2;
2263 	for (;i>afixed;--i){
2264 	  if (int(pos[i])<end_pos1-(afact-i)){
2265 	    ++pos[i];
2266 	    for (int j=i+1;j<afact;++j)
2267 	      pos[j]=pos[i]+(j-i);
2268 	    break;
2269 	  }
2270 	}
2271 	if (i<=afixed){
2272 	  --pos1;
2273 	  if (pos1<=5){
2274 	    mpz_clear(zx); mpz_clear(zy); mpz_clear(zq);  mpz_clear(zr);
2275 	    mpz_clear(alloc1); mpz_clear(alloc2); mpz_clear(alloc3); mpz_clear(alloc4); mpz_clear(alloc5);
2276 	    delete [] puissancestab;
2277 	    return false;
2278 	  }
2279 	  // reset fixed factors
2280 	  for (i=0;i<afixed;++i)
2281 	    pos[i]=pos0+i;
2282 	  for (i=afixed;i<afact;++i)
2283 	    pos[i]=pos1+i-afixed;
2284 	}
2285       }
2286       for (int i=0;i<afact;++i)
2287 	bpos2=bpos2*basis[pos[i]].p;
2288       Mval=std::sqrt(2*Nd)/(bpos2*bpos2);
2289       if (afixed){
2290 	// move "fixed" factors so that Mval becomes closer to Mtarget
2291 	// NB: for later threads, afixed should be >=3, so that we can move pos[1] by thread
2292 	while (Mval>1.1*Mtarget && int(pos[afixed-1])<int(pos1)-10){
2293 	  // Mval is too large, hence one factor of a is too small, increase it
2294 	  if (int(pos[0])<pos0){
2295 	    ++pos[0];
2296 	    double coeff=basis[pos[0]].p/double(basis[pos[0]-1].p);
2297 	    Mval=Mval/(coeff*coeff);
2298 	  }
2299 	  else {
2300 	    ++pos[afixed-1];
2301 	    double coeff=basis[pos[afixed-1]].p/double(basis[pos[afixed-1]-1].p);
2302 	    Mval=Mval/(coeff*coeff);
2303 	  }
2304 	}
2305 	while (Mval<0.9*Mtarget && pos[0]>10){
2306 	  // Mval is too small, decrease one factor of a
2307 	  --pos[0];
2308 	  if (pos[0]<=10){
2309 	    Mval=0;
2310 	    break;
2311 	  }
2312 	  double coeff=basis[pos[0]].p/double(basis[pos[0]+1].p);
2313 	  Mval=Mval/(coeff*coeff);
2314 	}
2315       }
2316       if ( Mval <0.7*Mtarget ){
2317 	if (pos1>pos0+afixed+5 || Mval<32768){
2318 	  // CERR << pos ;
2319 	  int i=afact-1;
2320 	  for (;i>afixed+1;--i){
2321 	    if (pos[i]>pos[i-1]+5)
2322 	      break;
2323 	  }
2324 	  if (i<=afixed+1){
2325 	    --pos1;
2326 	    for (i=0;i<afixed;++i)
2327 	      pos[i]=pos0+i;
2328 	    for (i=afixed;i<afact;++i)
2329 	      pos[i]=pos1+i-afixed;
2330 	  }
2331 	  else {
2332 	    ++pos[i-1];
2333 	    for (;i<afact;++i)
2334 	      pos[i]=pos[i-1]+1;
2335 	  }
2336 	  // CERR << pos << '\n';
2337 	}
2338       }
2339       // finished?
2340 #ifdef TIMEOUT
2341       control_c();
2342 #endif
2343       if (ctrl_c || interrupted)
2344 	break;
2345 #ifdef ADDITIONAL_PRIMES_HASHMAP
2346       todo_rel=bs+marge;
2347 #else
2348       todo_rel=bs+marge+unsigned(additional_primes.size());
2349 #endif
2350       if (axbmodn.size()>=todo_rel)
2351 	break;
2352       int nrelationsa=0;
2353       // Not finished yet, construct a new value of a around ad=sqrt(2*n)/M
2354       // using a product of afact square of primes that are in the basis
2355       // and construct a vector of 2^(afact-1) corresponding values of b
2356       // and compute the values of inverses of a mod p
2357       ulonglong usqrta(basis[pos[0]].p);
2358       for (int i=1;i<afact;++i)
2359 	usqrta=basis[pos[i]].p*usqrta; // works up to about N=1e86
2360       gen sqrta((int) basis[pos[0]].p);
2361       for (int i=1;i<afact;++i)
2362 	sqrta=gen(int(basis[pos[i]].p))*sqrta;
2363       sqrtavals.push_back(sqrta);
2364       gen a=sqrta*sqrta; // a should be about sqrt(Nd/2)/M
2365       a.uncoerce();
2366       int M=int(std::floor(std::sqrt(Nd*2)/evalf_double(a,1,contextptr)._DOUBLE_val));
2367       if (debug_infolevel>6)
2368 	*logptr(contextptr) << CLOCK() << gettext(" initial value for M= ") << M << '\n';
2369       int nslices=int(std::ceil((2.*M)/slicesize));
2370       M=(nslices*slicesize)/2;
2371       bvalues.clear();
2372       gen curprod=1;
2373       for (int i=0;;){
2374 #ifdef SQRTMOD_OUTSIDE
2375 	int s=sqrtmod[pos[i]];
2376 #else
2377 	int s=basis[pos[i]].sqrtmod;
2378 #endif
2379 	int p=basis[pos[i]].p;
2380 	longlong p2=p*longlong(p);
2381 	// Hensel lift s to be a sqrt of n mod p^2: (s+p*r)^2=s^2+2p*r*s=n => r=(n-s^2)/p*inv(2*s mod p)
2382 	int r=p<37000?int((modulo(*N._ZINTptr,p2)-s*s)/p):((smod(N,p2)-s*s)/p).val;
2383 	r=(r*invmod(2*s,p))%p;
2384 	// overflow should not happen because p is a factor of a hence choosen
2385 	// in the 1000 range (perhaps up to 10 000, but not much larger)
2386 	// if ((longlong(r)*p)!=r*p) CERR << "overflow" << '\n';
2387 	s += p*r;
2388 #ifdef PRIMES32
2389 	if (afact>afact0){
2390 	  // store s*(inv( product(basis[pos[j]]^2,j!=i) mod p2)) in bvalues[i]
2391 	  longlong up1=(usqrta/p);
2392 	  longlong up=up1%p2;
2393 	  up=(up*up)%p2;
2394 	  //longlong tmp=(s*invmodnoerr(up,p2))%p2;
2395 	  //up1tmp.push_back(up1);
2396 	  //up1tmp.push_back(tmp);
2397 	  gen tmp=smod(s*invmod(gen(up),gen(p2)),p2);
2398 	  if (is_greater(0,tmp,contextptr)) tmp=-tmp;
2399 	  gen gup1(up1);
2400 	  bvalues.push_back(gup1*gup1*tmp);
2401 	  bvalues.back().uncoerce();
2402 	}
2403 	else
2404 #endif
2405 	  {
2406 	    if (bvalues.empty())
2407 	      bvalues.push_back(s);
2408 	    else {
2409 	      int js=int(bvalues.size());
2410 	      for (int j=0;j<js;++j){
2411 		bvalues.push_back(ichinrem(bvalues[j],-s,curprod,p2));
2412 		bvalues[j]=ichinrem(bvalues[j],s,curprod,p2);
2413 	      }
2414 	    }
2415 	  }
2416 	++i;
2417 	if (i==afact)
2418 	  break;
2419 	curprod = p*(p*curprod);
2420       } // end for
2421       // compute inverse of a modulo p (will set to 0 if not invertible)
2422       if (debug_infolevel>6)
2423 	*logptr(contextptr) << CLOCK() << gettext(" Computing inverses mod p of the basis ") << '\n';
2424       // fastsmod_prepare(a,zx,zy,zr,a256);
2425       gen b;
2426       for (int i=0;i< (1<<(afact-1));++i){
2427 #ifdef TIMEOUT
2428 	control_c();
2429 #endif
2430 	if (ctrl_c || interrupted)
2431 	  break;
2432 #ifdef ADDITIONAL_PRIMES_HASHMAP
2433 	todo_rel=bs+marge;
2434 #else
2435 	todo_rel=bs+marge+unsigned(additional_primes.size());
2436 #endif
2437 	if (axbmodn.size()>=todo_rel)
2438 	  break;
2439 	if (debug_infolevel>6)
2440 	  *logptr(contextptr) << CLOCK() << gettext(" Computing c ") << '\n';
2441 #ifdef PRIMES32
2442 	int bv=1,be=-1;
2443 	if (afact>afact0){
2444 	  if (i==0){
2445 	    b=0;
2446 	    for (unsigned j=0;j<bvalues.size();j++)
2447 	      b += bvalues[j];
2448 	  }
2449 	  else {
2450 	    find_bv_be(i,bv,be);
2451 	    b += (2*be)*bvalues[bv];
2452 	  }
2453 	}
2454 	else
2455 	  b=bvalues[i];
2456 #else
2457 	b=bvalues[i];
2458 #endif
2459 	b.uncoerce();
2460 	mpz_mul(zx,*b._ZINTptr,*b._ZINTptr);
2461 	mpz_sub(zy,zx,*N._ZINTptr);
2462 #ifdef USE_GMP_REPLACEMENTS
2463 	mp_grow(&alloc1,zy.used+2);
2464 	mpz_set_ui(alloc1,0);
2465 	alloc1.used = zy.used +2 ;
2466 	mpz_set(alloc2,zy);
2467 	mpz_set(alloc3,*a._ZINTptr);
2468 	alloc_mp_div(&zy,a._ZINTptr,&zq,&zr,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
2469 #else
2470 	mpz_divexact(zq,zy,*a._ZINTptr);
2471 #endif
2472 	// gen c=zq; // gen c=(b*b-N)/a;
2473 	// c.uncoerce();
2474 #ifdef PRIMES32
2475 	if (afact<=afact0)
2476 #endif
2477 	  {
2478 	    bool bneg=mpz_cmp_ui(*b._ZINTptr,0)<0;
2479 	    if (bneg)
2480 	      mpz_neg(*b._ZINTptr,*b._ZINTptr);
2481 	  }
2482 	bvals.push_back(b);
2483 	if (debug_infolevel>6)
2484 	  *logptr(contextptr) << CLOCK() << gettext(" Computing roots mod the basis ") << '\n';
2485 	// fastsmod_prepare(b,zx,zy,zr,b256);
2486 #ifdef PRIMES32
2487 	if (i && afact>afact0)
2488 	  switch_roots(bainv2,basis,
2489 #ifdef LP_SMALL_PRIMES
2490 		       small_basis,
2491 #endif
2492 		       lp_basis_pos,nslices,slicesize,bv,be,afact,pos,b,zq,M);
2493 	else {
2494 	  init_roots(basis,
2495 #ifdef LP_SMALL_PRIMES
2496 		     small_basis,
2497 #endif
2498 #ifdef WITH_INVA
2499 		     Inva,
2500 #endif
2501 #ifdef SQRTMOD_OUTSIDE
2502 		     sqrtmod,
2503 #endif
2504 		     bainv2,afact,afact0,
2505 		     a,b,bvalues,zq,M);
2506 #ifdef LP_TAB_TOGETHER
2507 	  // init all hashtable for large primes at once
2508 	  unsigned cl;
2509 	  if (debug_infolevel>3){
2510 	    cl=CLOCK();
2511 	    *logptr(contextptr) << cl << gettext(" Init large prime hashtables ") << '\n';
2512 	  }
2513 	  int total=(nslices << (afact-1));
2514 	  if (int(lp_map.size()) < total)
2515 	    lp_map.resize(total);
2516 	  for (int k=0;k< total;++k)
2517 	    lp_map[k].clear();
2518 	  if (lp_basis_pos){
2519 	    for (int k=0;;){
2520 	      basis_t * bit=&basis[0]+lp_basis_pos, * bitend=&basis[0]+bs;
2521 	      unsigned endpos=nslices*slicesize;
2522 	      lp_tab_t * ptr=&lp_map[0]+k*nslices;
2523 	      for (;bit!=bitend;++bit){
2524 		register ushort_t p=bit->p;
2525 		register unsigned pos=bit->root1;
2526 		for (;pos<endpos; pos += p){
2527 		  (ptr+(pos >> LP_TAB_SIZE))->push_back(lp_entry_t((pos & LP_MASK),p));
2528 		}
2529 		pos=bit->root2;
2530 		for (;pos<endpos; pos += p){
2531 		  (ptr+(pos >> LP_TAB_SIZE))->push_back(lp_entry_t((pos & LP_MASK),p));
2532 		}
2533 	      }
2534 	      ++k;
2535 	      if (k== (1 << (afact-1))){
2536 		if (debug_infolevel>3){
2537 		  unsigned cl2=CLOCK();
2538 		  *logptr(contextptr) << cl2 << gettext(" End large prime hashtables ") << cl2-cl << '\n';
2539 		}
2540 		break;
2541 	      }
2542 	      find_bv_be(k,bv,be);
2543 	      // switch roots to next polynomial
2544 	      int * bvpos=&bainv2[(bv-1)*bs],* bvposend=bvpos+bs;
2545 	      bvpos += lp_basis_pos;
2546 	      basis_t * basisptr=&basis[0]+lp_basis_pos;
2547 	      if (be>0){
2548 		for (;bvpos<bvposend;++basisptr,++bvpos){
2549 		  register unsigned p=basisptr->p;
2550 		  register int r=basisptr->root1-(*bvpos);
2551 		  if (r<0)
2552 		    r+=p;
2553 		  basisptr->root1=r;
2554 		  r=basisptr->root2-(*bvpos);
2555 		  if (r<0)
2556 		    r+=p;
2557 		  basisptr->root2=r;
2558 		}
2559 	      }
2560 	      else {
2561 		for (;bvpos<bvposend;++basisptr,++bvpos){
2562 		  register unsigned p=basisptr->p;
2563 		  register int r=basisptr->root1+(*bvpos);
2564 		  if (r>int(p))
2565 		    r-=p;
2566 		  basisptr->root1=r;
2567 		  r=basisptr->root2+(*bvpos);
2568 		  if (r>int(p))
2569 		    r-=p;
2570 		  basisptr->root2=r;
2571 		}
2572 	      }
2573 	    }
2574 	  }
2575 #endif // LP_TAB_TOGETHER
2576 	} // end else of if i==0
2577 #if defined(LP_TAB_SIZE) && !defined(LP_TAB_TOGETHER)
2578 	if (int(lp_map.size()) < nslices)
2579 	  lp_map.resize(nslices);
2580 	for (int k=0;k< nslices;++k)
2581 	  lp_map[k].clear();
2582 	if (lp_basis_pos){
2583 	  basis_t * bit=&basis[0]+lp_basis_pos, * bitend=&basis[0]+bs;
2584 	  unsigned endpos=nslices*slicesize;
2585 	  for (;bit!=bitend;++bit){
2586 	    register ushort_t p=bit->p;
2587 	    register unsigned pos=bit->root1;
2588 	    for (;pos<endpos; pos += p){
2589 	      lp_map[pos >> LP_TAB_SIZE].push_back(lp_entry_t((pos & LP_MASK),p));
2590 	    }
2591 	    pos=bit->root2;
2592 	    for (;pos<endpos; pos += p){
2593 	      lp_map[pos >> LP_TAB_SIZE].push_back(lp_entry_t((pos & LP_MASK),p));
2594 	    }
2595 	  }
2596 	}
2597 #endif // LP_TAB_SIZE && !LP_TAB_TOGETHER
2598 #else // PRIMES32
2599 	init_roots(basis,
2600 #ifdef WITH_INVA
2601 		     Inva,
2602 #endif
2603 #ifdef SQRTMOD_OUTSIDE
2604 		   sqrtmod,
2605 #endif
2606 		   usqrta,a,b,bvalues,zq,M);
2607 #endif // PRIMES32
2608 	// we can now sieve in [-M,M[ by slice of size slicesize
2609 #ifndef GIAC_HAS_STO_38
2610 	if (debug_infolevel>5){
2611 	  *logptr(contextptr) << CLOCK();
2612 	  *logptr(contextptr) << gettext(" Polynomial a,b,M=") << a << "," << b << "," << M << " (" << pos << ")" ;
2613 	  *logptr(contextptr) << CLOCK() << '\n';
2614 	}
2615 #endif
2616 	int nrelationsb=0;
2617 #ifdef LP_TAB_SIZE
2618 #endif
2619 	for (int l=0;l<nslices;l++){
2620 #ifdef TIMEOUT
2621 	  control_c();
2622 #endif
2623 	  if (ctrl_c || interrupted)
2624 	    break;
2625 #ifdef ADDITIONAL_PRIMES_HASHMAP
2626 	  todo_rel=bs+marge;
2627 #else
2628 	  todo_rel=bs+marge+unsigned(additional_primes.size());
2629 #endif
2630 	  if (axbmodn.size()>=todo_rel)
2631 	    break;
2632 	  int shift=-M+l*slicesize;
2633 	  int slicerelations=msieve(a,sqrtavals,
2634 				    bvals,zq,basis,lp_basis_pos,
2635 #ifdef LP_SMALL_PRIMES
2636 				    small_basis,
2637 #endif
2638 				    maxadditional,
2639 #ifdef ADDITIONAL_PRIMES_HASHMAP
2640 				    additional_primes_map,
2641 #else
2642 				    additional_primes,additional_primes_twice,
2643 #endif
2644 				    N,isqrtN,
2645 				    slice,slicesize,shift,puissancestab,puissancesptr,puissancesend,curpuissances,recheck,
2646 				    axbmodn,
2647 				    zx,zy,zr,alloc1,alloc2,alloc3,alloc4,alloc5,
2648 #ifdef LP_TAB_SIZE
2649 #ifdef LP_TAB_TOGETHER
2650 				    lp_map[l+nslices*i],
2651 #else
2652 				    lp_map[l],
2653 #endif
2654 #endif
2655 				    contextptr);
2656 	  if (slicerelations==-1){
2657 	    *logptr(contextptr) << gettext("Sieve error: Not enough memory ") << '\n';
2658 	    break;
2659 	  }
2660 	  nrelationsb += slicerelations;
2661 #ifdef ADDITIONAL_PRIMES_HASHMAP
2662 	  todo_rel=bs+marge;
2663 #else
2664 	  todo_rel=bs+marge+unsigned(additional_primes.size());
2665 #endif
2666 	}
2667 	if (nrelationsb==0)
2668 	  bvals.pop_back();
2669 	else
2670 	  nrelationsa += nrelationsb;
2671       }
2672 #if defined( RTOS_THREADX) || defined(BESTA_OS) || defined NSPIRE
2673       if (debug_infolevel){
2674 #ifdef NSPIRE
2675 	static int count_print=0;
2676 	++count_print;
2677 	if (count_print%4==0)
2678 #endif
2679 	  *logptr(contextptr) << axbmodn.size() << " of " << todo_rel << " (" << 100-100*(todo_rel-axbmodn.size())/double(bs+marge) << "%)" << '\n';
2680       }
2681 #endif
2682       if (nrelationsa==0){
2683 	sqrtavals.pop_back();
2684       }
2685 #if !defined(RTOS_THREADX) && !defined(BESTA_OS) && !defined NSPIRE
2686       if (debug_infolevel>1)
2687 	*logptr(contextptr) << CLOCK()<< gettext(" sieved : ") << axbmodn.size() << " of " << todo_rel << " (" << 100-100*(todo_rel-axbmodn.size())/double(bs+marge) << "%), M=" << M << '\n';
2688 #endif
2689     } // end sieve loop
2690     if (debug_infolevel)
2691       *logptr(contextptr) << gettext("Polynomials a,b in use: #a ") << sqrtavals.size() << " and #b " << bvals.size() << '\n';
2692     delete [] slice;
2693 #ifdef TIMEOUT
2694     control_c();
2695 #endif
2696     if (ctrl_c || interrupted || puissancesptr==puissancesend){
2697       mpz_clear(zx); mpz_clear(zy); mpz_clear(zq);  mpz_clear(zr);
2698       mpz_clear(alloc1); mpz_clear(alloc2); mpz_clear(alloc3); mpz_clear(alloc4); mpz_clear(alloc5);
2699       delete [] puissancestab;
2700       return false;
2701     }
2702     // We have enough relations, make matrix, reduce it then find x^2=y^2 mod n congruences
2703     if (debug_infolevel)
2704       *logptr(contextptr) << CLOCK() << gettext(" sieve done: used ") << (puissancesptr-puissancestab)*0.002 << " K for storing relations (of " << puissancestablength*0.002 << ")" << '\n';
2705     release_memory(isqrtNmodp);
2706 #ifdef GIAC_ADDITIONAL_PRIMES
2707 #ifdef ADDITIONAL_PRIMES_HASHMAP
2708     additional_primes.reserve(axbmodn.size());
2709     vector<axbinv>::const_iterator it=axbmodn.begin(),itend=axbmodn.end();
2710     for (;it!=itend;++it) {
2711       unsigned u=largep(*it,puissancestab);
2712       if (u)
2713 	additional_primes.push_back(u);
2714     }
2715     sort(additional_primes.begin(),additional_primes.end()); // for binary search later
2716 #else
2717     if (debug_infolevel)
2718       *logptr(contextptr) << CLOCK() << gettext(" removing additional primes") << '\n';
2719     // remove relations with additional primes which are used only once
2720     int lastp=int(axbmodn.size())-1,lasta=int(additional_primes.size())-1;
2721     for (int i=0;i<=lastp;++i){
2722       ushort_t * curbeg=puissancestab+axbmodn[i].first, * curend=puissancestab+axbmodn[i].second;
2723       bool done=false;
2724       for (;curbeg!=curend;++curbeg){
2725 	if (*curbeg==1)
2726 	  break;
2727       }
2728       if (curbeg==curend)
2729 	continue;
2730       ++curbeg;
2731       additional_t u=*curbeg;
2732 #if GIAC_ADDITIONAL_PRIMES==32 && !defined(PRIMES32)
2733       u <<=16 ;
2734       ++curbeg;
2735       u += *curbeg;
2736 #endif
2737       int pos=_equalposcomp(additional_primes,u);
2738       if (!pos)
2739 	continue;
2740       if (pos>lasta){
2741 	// *logptr(contextptr) << cur << '\n';
2742 	continue;
2743       }
2744       --pos;
2745       if (additional_primes_twice[pos])
2746 	continue;
2747       axbmodn[i]=axbmodn[lastp];
2748       --lastp;
2749       additional_primes[pos]=additional_primes[lasta];
2750       additional_primes_twice[pos]=additional_primes_twice[lasta];
2751       --lasta;
2752       --i; // recheck at current index
2753     }
2754     axbmodn.resize(lastp+1);
2755     additional_primes.resize(lasta+1);
2756     if (debug_infolevel)
2757       *logptr(contextptr) << CLOCK() << gettext(" end removing additional primes") << '\n';
2758 #endif // ADDTIONAL_PRIMES_HASHMAP
2759 #endif // GIAC_ADDITIONAL_PRIMES
2760     // Make relations matrix (currently dense, FIXME improve to sparse and Lanczos algorithm)
2761     int C32=int(std::ceil(axbmodn.size()/32./GIAC_RREF_UNROLL))*GIAC_RREF_UNROLL;
2762     unsigned * tab=new unsigned[axbmodn.size()*C32],*tabend=tab+axbmodn.size()*C32;
2763     if (!tab){
2764       mpz_clear(zx); mpz_clear(zy); mpz_clear(zq); mpz_clear(zr);
2765       mpz_clear(alloc1); mpz_clear(alloc2); mpz_clear(alloc3); mpz_clear(alloc4); mpz_clear(alloc5);
2766       delete [] puissancestab;
2767       return false;
2768     }
2769     // init tab
2770     for (unsigned * ptr=tab;ptr!=tabend;++ptr)
2771       *ptr=0;
2772     int l32=C32*32;
2773     vector< line_t > relations(axbmodn.size());
2774     for (unsigned i=0;i<axbmodn.size();++i){
2775       relations[i].tab=tab+i*C32;
2776     }
2777     for (unsigned j=0;j<axbmodn.size();j++){
2778       ushort_t * curpui=puissancestab+axbmodn[j].first, * curpuiend=puissancestab+axbmodn[j].second;
2779       add_relation(relations,j,curpui,curpuiend,basis,additional_primes);
2780 #ifdef ADDITIONAL_PRIMES_HASHMAP
2781       unsigned u=largep(axbmodn[j],puissancestab);
2782       if (u){
2783 	axbinv & A=additional_primes_map[u];
2784 	curpui=puissancestab+A.first; curpuiend=puissancestab+A.second;
2785 	add_relation(relations,j,curpui,curpuiend,basis,additional_primes);
2786       }
2787 #endif
2788     } // end loop on j in puissances
2789 #ifdef RREF_SORT // seems slower
2790     unsigned count0=0,count1=0;
2791     for (int i=0;i<relations.size();++i){
2792       int c=relations[i].count=count_ones(relations[i].tab,C32);
2793       if (c==0)
2794 	++count0;
2795       if (c==1)
2796 	++count1;
2797       if (debug_infolevel>2){
2798 	cout << i << ", p=";
2799 	if (i==0)
2800 	  cout << "-1";
2801 	else {
2802 	  if (i<=bs)
2803 	    cout << basis[i-1].p << " " << relations[i].count << '\n';
2804 	  else
2805 	    cout << '\n';
2806 	}
2807       }
2808     }
2809     if (debug_infolevel)
2810       *logptr(contextptr) << CLOCK() << " begin rref size " << relations.size() << "x" << l32 << " K " << 0.004*relations.size()*C32 << ", " << count0 << " null lines, " << count1 << " 1-line" << '\n';
2811 #if 0 // debug only
2812     for (int i=0;i<relations.size();++i){
2813       cout << i << ", p=";
2814       if (i==0)
2815 	cout << "-1";
2816       else {
2817 	if (i<=bs)
2818 	  cout << basis[i-1].p << " " << relations[i].count << '\n';
2819 	else
2820 	  cout << '\n';
2821       }
2822     }
2823 #endif
2824     sort(relations.begin(),relations.end()); // put 0 lines at end, otherwise asc. sort
2825 #else // RREF_SORT
2826     if (debug_infolevel)
2827       *logptr(contextptr) << CLOCK() << " begin rref size " << relations.size() << "x" << l32 << " K " << 0.004*relations.size()*C32 << '\n';
2828     reverse(relations.begin(),relations.end());
2829 #endif // RREF_SORT
2830     // rref(relations,relations.size(),C32,0);
2831     rref(relations,int(relations.size()),C32,1);
2832     rref(relations,int(relations.size()),C32,2);
2833     if (debug_infolevel)
2834       *logptr(contextptr) << CLOCK() << " end rref" << '\n';
2835     // printbool(*logptr(contextptr),relations);
2836     // move pivots on the diagonal by inserting 0 lines
2837     vector< unsigned * > relations2(l32);
2838     i=0;
2839     int j=0,rs=int(relations.size());
2840     for (;i<rs && j<l32;++j){
2841       if (relations[i].tab[j/32] & (1 << j%32)){
2842 	swap(relations2[j],relations[i].tab);
2843 	++i;
2844       }
2845     }
2846     // printbool(*logptr(contextptr),relations2);
2847     // for each element of the kernel compute x and y / x^2=y^2[N]
2848     // then gcd(x-y,n_orig)
2849     for (i=0;i<l32;++i){
2850       if (relations2[i] && (relations2[i][i/32] & (1<<i%32)))
2851 	continue;
2852       // using column i of relations2 which is in the kernel, build x and y
2853       // for x, we can compute the product of the axbmodn mod N
2854       // for y, compute the product of sqrta mod N and multiply later by ax^2+bx+c factored part
2855       // since (a*x+b)^2=a*(a*x^2+2*b*x+c) mod N
2856       gen x=1,y=1,cur;
2857       mpz_set_ui(zx,1);
2858       mpz_set_ui(zy,1);
2859       vector<short_t> p(bs), add_p(additional_primes.size());
2860       for (int j=0;j<l32;++j){
2861 	if (j<int(axbmodn.size()) && (i==j || (relations2[j] && (relations2[j][i/32] & (1<<(i%32)))))){
2862 	  if (axbmodn[j].aindex>=sqrtavals.size() || axbmodn[j].bindex>=bvals.size())
2863 	    return false; // check added because ifactor(nextprime(alog10(17))*nextprime(alog10(19))); fails on Prime (and unable to do parallel debug in giac)
2864 	  update_xy(axbmodn[j],zx,zy,p,add_p,N,basis,additional_primes,sqrtavals,bvals,puissancestab,zq,zr,alloc1,alloc2,alloc3,alloc4,alloc5);
2865 #ifdef ADDITIONAL_PRIMES_HASHMAP
2866 	  unsigned u=largep(axbmodn[j],puissancestab);
2867 	  if (u)
2868 	    update_xy(additional_primes_map[u],zx,zy,p,add_p,N,basis,additional_primes,sqrtavals,bvals,puissancestab,zq,zr,alloc1,alloc2,alloc3,alloc4,alloc5);
2869 #endif
2870 	} // end if (j<axbmodn.size() ...)
2871       } // end for unsigned j=0; j<l32
2872       for (int i=0;i<bs;++i){
2873 	if (p[i] % 2)
2874 	  *logptr(contextptr) << gettext("error, odd exponent for prime ") << basis[i].p << '\n';
2875 	if (p[i]){
2876 #if 1
2877 	  mpz_set_ui(alloc1,basis[i].p);
2878 	  for (int j=0;j<p[i]/2;++j)
2879 	    mpz_mul(zy,zy,alloc1);
2880 #ifdef USE_GMP_REPLACEMENTS
2881 	  mp_grow(&alloc1,zy.used+2);
2882 	  mpz_set_ui(alloc1,0);
2883 	  alloc1.used = zy.used +2 ;
2884 	  mpz_set(alloc2,zy);
2885 	  mpz_set(alloc3,*N._ZINTptr);
2886 	  // mpz_set_si(alloc4,0);
2887 	  // mpz_set_si(alloc5,0);
2888 	  alloc_mp_div(&zy,N._ZINTptr,&zq,&zr,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
2889 #else
2890 	  mpz_tdiv_r(zr,zy,*N._ZINTptr);
2891 #endif
2892 	  mpz_set(zy,zr);
2893 #else
2894 	  y=y*pow(gen(basis[i].p),int(p[i]/2));
2895 	  y=smod(y,N);
2896 #endif
2897 	}
2898       }
2899       for (unsigned i=0;i<additional_primes.size();++i){
2900 	if (add_p[i] % 2)
2901 	  *logptr(contextptr) << gettext("error") << i << '\n';
2902 	if (add_p[i]){
2903 #if 1
2904 	  mpz_set_ui(alloc1,additional_primes[i]);
2905 	  for (int j=0;j<add_p[i]/2;++j)
2906 	    mpz_mul(zy,zy,alloc1);
2907 #ifdef USE_GMP_REPLACEMENTS
2908 	  mp_grow(&alloc1,zy.used+2);
2909 	  mpz_set_ui(alloc1,0);
2910 	  alloc1.used = zy.used +2 ;
2911 	  mpz_set(alloc2,zy);
2912 	  mpz_set(alloc3,*N._ZINTptr);
2913 	  // mpz_set_si(alloc4,0);
2914 	  // mpz_set_si(alloc5,0);
2915 	  alloc_mp_div(&zy,N._ZINTptr,&zq,&zr,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
2916 #else
2917 	  mpz_tdiv_r(zr,zy,*N._ZINTptr);
2918 #endif
2919 	  mpz_set(zy,zr);
2920 #else
2921 	  y=y*pow(gen(additional_primes[i]),int(add_p[i]/2));
2922 	  y=smod(y,N);
2923 #endif
2924 	}
2925       }
2926 #if 1
2927       y=zy;
2928       x=zx;
2929 #endif
2930       cur=gcd(x-y,n_orig);
2931       if (debug_infolevel>6)
2932 	*logptr(contextptr) << CLOCK() << gettext("checking gcd") << cur << " " << N << '\n';
2933       if ( (cur.type==_INT_ && cur.val>7) ||
2934 	   (cur.type==_ZINT && is_strictly_greater(n_orig,cur,contextptr))){
2935 	pn=cur;
2936 	mpz_clear(zx); mpz_clear(zy); mpz_clear(zq); mpz_clear(zr);
2937 	mpz_clear(alloc1); mpz_clear(alloc2); mpz_clear(alloc3); mpz_clear(alloc4); mpz_clear(alloc5);
2938 	delete [] puissancestab;
2939 	delete [] tab;
2940 	return true;
2941       }
2942     }
2943     mpz_clear(zx); mpz_clear(zy); mpz_clear(zq); mpz_clear(zr);
2944     mpz_clear(alloc1); mpz_clear(alloc2); mpz_clear(alloc3); mpz_clear(alloc4); mpz_clear(alloc5);
2945     delete [] puissancestab;
2946     delete [] tab;
2947     return false;
2948   }
2949 
2950   // elliptic curve method,
2951   // http://math.univ-lyon1.fr/~roblot/resources/factorisation.pdf
2952   // This is a very naive implementation
2953   // It does not use Montgomery representation and only phase 1
2954   // For professional implementations, cf.
2955   // https://members.loria.fr/PZimmermann/papers/ecm-submitted.pdf
2956   // https://pdfs.semanticscholar.org/e8eb/13b75292b15dd63c3e7e4b1c8dc334d278ba.pdf
2957   // ecm will be used if available
2958 #define ECM_MAXITER 1000
L(double alpha,double beta,double N)2959   static gen L(double alpha,double beta,double N){
2960     double lnN=std::log(N);
2961     return std::exp(beta*std::pow(lnN,alpha)*std::pow(std::log(lnN),1-alpha));
2962   }
2963 
2964 
2965 #ifndef USE_GMP_REPLACEMENTS
2966   // addition in elliptic curve, returns 1 on success or 0 and m=a divisor of n
ecm_add(const mpz_t & x1,const mpz_t & y1,const mpz_t & x2,const mpz_t & y2,const mpz_t & a,const mpz_t & n,mpz_t & m,mpz_t & x,mpz_t & y)2967   int ecm_add(const mpz_t &x1,const mpz_t &y1,const mpz_t & x2,const mpz_t &y2,const mpz_t & a,const mpz_t & n,mpz_t & m,mpz_t & x,mpz_t &y){
2968     if (mpz_cmp(x1,x2)){
2969       mpz_sub(x,x2,x1); // x=x2-x1
2970       int res=mpz_invert(m,x,n); // m=inv(x2-x1) mod n
2971       if (res==0){ // not invertible
2972 	mpz_gcd(m,x,n);
2973 	return 0; // m has non trivial gcd with n
2974       }
2975       mpz_sub(y,y2,y1);
2976       mpz_mul(m,m,y); // m=(y2-y1)*invmod(x2-x1,n);
2977     }
2978     else {
2979       mpz_mul_ui(y,y1,2);
2980       int res=mpz_invert(m,y,n); // m=inv(2*y) mod n
2981       if (res==0){ // not invertible
2982 	mpz_gcd(m,y,n);
2983 	return 0; // m has non trivial gcd with n
2984       }
2985       mpz_mul(x,x1,x1);
2986       mpz_mul_ui(x,x,3);
2987       mpz_add(x,x,a);
2988       mpz_mul(m,m,x); // m=(3*x1*x1+a)*invmod(2*y1,n);
2989     }
2990     mpz_fdiv_r(m,m,n); // m=mod(m,n);
2991     mpz_mul(x,m,m);
2992     mpz_sub(x,x,x1);
2993     mpz_sub(x,x,x2);
2994     mpz_fdiv_r(x,x,n); // x=mod(m*m-x1-x2,n);
2995     mpz_sub(y,x1,x);
2996     mpz_mul(y,m,y);
2997     mpz_sub(y,y,y1);
2998     mpz_fdiv_r(y,y,n); // y=mod(m*(x1-x)-y1,n);
2999     // smod x and y
3000     mpz_add(m,x,x);
3001     if (mpz_cmp(m,n)>0)
3002       mpz_sub(x,x,n);
3003     mpz_add(m,y,y);
3004     if (mpz_cmp(m,n)>0)
3005       mpz_sub(y,y,n);
3006     return 1;
3007   }
3008 #endif
3009 
ecm_add(const gen & x1,const gen & y1,const gen & x2,const gen & y2,const gen & a,const gen & n,gen & m,gen & x,gen & y)3010   gen ecm_add(const gen &x1,const gen &y1,const gen & x2,const gen &y2,const gen & a,const gen & n,gen & m,gen & x,gen &y){
3011     if (is_inf(x1)){
3012       x=x2; y=y2; return 1;
3013     }
3014     if (is_inf(x2)){
3015       x=x1; y=y1; return 1;
3016     }
3017     if (y1+y2==0){
3018       y=x=unsigned_inf; return 1;
3019     }
3020 #ifndef USE_GMP_REPLACEMENTS
3021     if (x1.type==_ZINT && y1.type==_ZINT && x2.type==_ZINT && y2.type==_ZINT && a.type==_ZINT && n.type==_ZINT ){
3022       m=gen(1LL<<33);
3023       x=gen(1LL<<33);
3024       y=gen(1LL<<33);
3025       if (!ecm_add(*x1._ZINTptr,*y1._ZINTptr,*x2._ZINTptr,*y2._ZINTptr,*a._ZINTptr,*n._ZINTptr,*m._ZINTptr,*x._ZINTptr,*y._ZINTptr)){
3026 	return gen(*m._ZINTptr);
3027       }
3028       return 1;
3029     }
3030 #endif
3031     if (x1!=x2){
3032       m=gcd(x2-x1,n);
3033       if (m!=1)
3034 	return m;
3035       m=(y2-y1)*invmod(x2-x1,n);
3036     }
3037     else {
3038       m=gcd(y1,n);
3039       if (m!=1)
3040 	return m;
3041       m=(3*x1*x1+a)*invmod(2*y1,n);
3042     }
3043     m=smod(m,n);
3044     x=smod(m*m-x1-x2,n);
3045     y=smod(m*(x1-x)-y1,n);
3046     return 1;
3047   }
3048   // multiplication in elliptic curve,
ecm_mult(const gen & x1,const gen & y1,ulonglong m,const gen & a,const gen & n,gen & x,gen & y)3049   gen ecm_mult(const gen &x1,const gen &y1,ulonglong m,const gen & a,const gen & n,gen & x,gen &y){
3050     gen x2(x1),y2(y1),xtmp,ytmp,g,M;
3051     y=x=plus_inf;
3052     while (m){
3053       if (m%2){
3054 	g=ecm_add(x,y,x2,y2,a,n,M,xtmp,ytmp);
3055 	if (g!=1)
3056 	  return g;
3057 	swapgen(x,xtmp); swapgen(y,ytmp);// x=xtmp; y=ytmp;
3058       }
3059       m/=2;
3060       g=ecm_add(x2,y2,x2,y2,a,n,M,xtmp,ytmp); // improve: ecmdup
3061       if (g!=1)
3062 	return g;
3063       swapgen(x2,xtmp);swapgen(y2,ytmp);// x2=xtmp; y2=ytmp;
3064     }
3065     return 1;
3066   }
_ecm_factor(const gen & n_,GIAC_CONTEXT)3067   gen _ecm_factor(const gen &n_,GIAC_CONTEXT){
3068     gen B,n(n_);
3069     int maxiter(ECM_MAXITER);
3070     if (n.type==_VECT && n._VECTptr->size()>=2){
3071       const vecteur & v=*n._VECTptr;
3072       B=v[1];
3073       if (v.size()>=3 && v[2].type==_INT_)
3074 	maxiter=giacmax(1,v[2].val);
3075       n=v.front();
3076     }
3077     if (!is_integer(n) || is_positive(-n,contextptr))
3078       return gensizeerr(contextptr);
3079     if (_isprime(n,contextptr)!=0)
3080       return n;
3081     double logp=.5*std::log(evalf_double(n,1,contextptr)._DOUBLE_val);
3082 #ifdef HAVE_LIBECM
3083     double epsilon=.02; // to be adjusted
3084 #else
3085     double epsilon=.45; // to be adjusted
3086 #endif
3087     if (logp>80) // research factors of size not exceeding 35 digits
3088       logp=80;
3089     if (B==0)
3090       B=L(.5,0.707+epsilon,std::exp(logp));
3091     // B=1000;
3092     B=_ceil(B,contextptr);
3093 #ifdef HAVE_LIBECM
3094     *logptr(contextptr) << "ECM-GMP factor n="<< n << " , B=" << B << ", #curves <=" << maxiter << '\n';
3095     n.uncoerce();
3096     double B1=evalf_double(B,1,contextptr)._DOUBLE_val;
3097     /* From ECM README, table of optimal values of B1
3098        digits D  optimal B1   default B2           expected curves
3099                                                        N(B1,B2,D)
3100                                               -power 1         default poly
3101           20       11e3         1.9e6             74               74 [x^1]
3102           25        5e4         1.3e7            221              214 [x^2]
3103           30       25e4         1.3e8            453              430 [D(3)]
3104           35        1e6         1.0e9            984              904 [D(6)]
3105           40        3e6         5.7e9           2541             2350 [D(6)]
3106           45       11e6        3.5e10           4949             4480 [D(12)]
3107           50       43e6        2.4e11           8266             7553 [D(12)]
3108           55       11e7        7.8e11          20158            17769 [D(30)]
3109           60       26e7        3.2e12          47173            42017 [D(30)]
3110           65       85e7        1.6e13          77666            69408 [D(30)]
3111 
3112      */
3113     int res;
3114     gen F(1LL<<33);
3115     for (int i=0;i<maxiter;++i){
3116       res=ecm_factor(*F._ZINTptr, *n._ZINTptr, B1, 0);
3117       if (res!=0) break;
3118     }
3119     if (res==0) return undef;
3120     return F;
3121 #else
3122     *logptr(contextptr) << "ECM naive factor n="<< n << " , B=" << B << ", #curves <=" << maxiter << '\n';
3123     for (int i=0;i<maxiter;++i){
3124       gen a,x,y,b,d,g;
3125       a= rand_interval(makevecteur(0,n-1),true,contextptr);// a=1078104638;
3126       x= smod(rand_interval(makevecteur(0,n-1),true,contextptr),n);// 317359960;
3127       y= smod(rand_interval(makevecteur(0,n-1),true,contextptr),n);// 983830906;
3128       b=smod(y*y-x*x*x-a*x,n);
3129       if (debug_infolevel)
3130 	COUT << CLOCK()*1e-6 << " Factor "<< n << " ECM curve " << i << ", B="<<B << ", a=" << a << ", x=" << x << ", y=" << y << '\n';
3131       d=4*a*a*a-27*b*b;
3132       g=gcd(d,n);
3133       if (g==n)
3134 	continue;
3135       if (g!=1)
3136 	return g;
3137       gen p(2),pe,tmp,xm,ym;
3138       for (;is_greater(B,pe=p*p,contextptr);p=nextprime(p+1)){
3139 	int e=2;
3140 	while (is_greater(B,tmp=pe*p,contextptr)){
3141 	  ++e;
3142 	  pe=tmp;
3143 	}
3144 	tmp=evalf_double(pe,1,contextptr);
3145 	if (pe==tmp){
3146 	  g=ecm_mult(x,y,ulonglong(tmp._DOUBLE_val),a,n,xm,ym);
3147 	  if (g!=1){
3148 	    if (debug_infolevel)
3149 	      COUT << CLOCK()*1e-6 << " ECM success p=" << p << ", p^e=" << pe << '\n';
3150 	    return g;
3151 	  }
3152 	  swapgen(x,xm); swapgen(y,ym); // x=xm;y=ym;
3153 	}
3154       }
3155       B=_floor(1.001*B,contextptr)+1; // to be adjusted
3156     } // end maxiter loop
3157     return undef;
3158 #endif
3159   }
3160   static const char _ecm_factor_s []="ecm_factor";
3161   static define_unary_function_eval (__ecm_factor,&_ecm_factor,_ecm_factor_s);
3162   define_unary_function_ptr5( at_ecm_factor ,alias_at_ecm_factor,&__ecm_factor,0,true);
3163 
3164   // Pollard-rho algorithm
3165   const int POLLARD_GCD=64;
3166 #ifdef GIAC_MPQS
3167 #if defined(RTOS_THREADX) // !defined(BESTA_OS)
3168   const int POLLARD_MAXITER=3000;
3169 #else
3170   const int POLLARD_MAXITER=15000;
3171 #endif
3172 #else
3173   const int POLLARD_MAXITER=15000;
3174 #endif
3175 
pollard(gen n,gen k,GIAC_CONTEXT)3176   static gen pollard(gen n, gen k,GIAC_CONTEXT){
3177     k.uncoerce();
3178     n.uncoerce();
3179     int maxiter=POLLARD_MAXITER;
3180     double nd=evalf_double(n,1,contextptr)._DOUBLE_val;
3181 #if defined(RTOS_THREADX) || defined(BESTA_OS) || defined NSPIRE
3182     int nd1=int(2000*(std::log10(nd)-34));
3183 #else
3184     int nd1=int(1500*std::pow(16.,(std::log10(nd)-40)/10));
3185 #endif
3186     if (nd1>maxiter)
3187       maxiter=nd1;
3188     int m,m1,a,a1,j;
3189     m1=m=2;
3190     a1=a=1;
3191     int c=0;
3192     mpz_t g,x,x1,x2,x2k,y,y1,p,q,tmpq,alloc1,alloc2,alloc3,alloc4,alloc5;
3193     mpz_init_set_si(g,1); // ? mp_init_size to specify size
3194     mpz_init_set_si(x,2);
3195     mpz_init_set_si(x1,2);
3196     mpz_init_set_si(y,2);
3197     mpz_init(y1);
3198     mpz_init(x2);
3199     mpz_init(x2k);
3200     mpz_init_set_si(p,1);
3201     mpz_init(q);
3202     mpz_init(tmpq);
3203     mpz_init(alloc1);
3204     mpz_init(alloc2);
3205     mpz_init(alloc3);
3206     mpz_init(alloc4);
3207     mpz_init(alloc5);
3208     while (!ctrl_c && !interrupted && mpz_cmp_si(g,1)==0) {
3209 #ifdef TIMEOUT
3210       control_c();
3211 #endif
3212       a=2*a+1;//a=2^(e+1)-1=2*l(m)-1
3213       while (!ctrl_c && !interrupted && mpz_cmp_si(g,1)==0 && a>m) { // ok
3214 #ifdef TIMEOUT
3215 	control_c();
3216 #endif
3217 	// x=f(x,k,n,q);
3218 #ifdef USE_GMP_REPLACEMENTS
3219 	mp_sqr(&x,&x2);
3220 	mpz_add(x2k,x2,*k._ZINTptr);
3221 	if (mpz_cmp(x2k,*n._ZINTptr)>0){
3222 	  mp_grow(&alloc1,x2k.used+2);
3223 	  mpz_set_ui(alloc1,0);
3224 	  alloc1.used = x2k.used +2 ;
3225 	  mpz_set(alloc2,x2k);
3226 	  mpz_set(alloc3,*n._ZINTptr);
3227 	  // mpz_set_si(alloc4,0);
3228 	  // mpz_set_si(alloc5,0);
3229 	  alloc_mp_div(&x2k,n._ZINTptr,&tmpq,&x,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
3230 	}
3231 	else
3232 	  mpz_set(x,x2k);
3233 #else
3234 	mpz_mul(x2,x,x);
3235 	mpz_add(x2k,x2,*k._ZINTptr);
3236 	mpz_tdiv_r(x,x2k,*n._ZINTptr);
3237 #endif
3238 	m += 1;
3239 	if (debug_infolevel && ((m %
3240 #if defined(RTOS_THREADX) || defined(BESTA_OS) || defined NSPIRE
3241 				 (1<<10)
3242 #else
3243 				 (1<<18)
3244 #endif
3245 				 )==0))
3246 	  *logptr(contextptr) << CLOCK() << gettext(" Pollard-rho try ") << m << '\n';
3247 	if (m > maxiter ){
3248 	  if (debug_infolevel)
3249 	    *logptr(contextptr) << CLOCK() << gettext(" Pollard-rho failure, ntries ") << m << '\n';
3250 	  mpz_clear(alloc5);
3251 	  mpz_clear(alloc4);
3252 	  mpz_clear(alloc3);
3253 	  mpz_clear(alloc2);
3254 	  mpz_clear(alloc1);
3255 	  mpz_clear(tmpq);
3256 	  mpz_clear(x);
3257 	  mpz_clear(x1);
3258 	  mpz_clear(x2);
3259 	  mpz_clear(x2k);
3260 	  mpz_clear(y);
3261 	  mpz_clear(y1);
3262 	  mpz_clear(p);
3263 	  mpz_clear(q);
3264 	  return -1;
3265 	}
3266 	// p=irem(p*(x1-x),n,q);
3267 	mpz_sub(q,x1,x);
3268 	mpz_mul(x2,p,q);
3269 #if 0 // def USE_GMP_REPLACEMENTS
3270 	if (mpz_cmp(x2,*n._ZINTptr)>0){
3271 	  mp_grow(&alloc1,x2.used+2);
3272 	  mpz_set_ui(alloc1,0);
3273 	  alloc1.used = x2.used +2 ;
3274 	  mpz_set(alloc2,x2);
3275 	  mpz_set(alloc3,*n._ZINTptr);
3276 	  // mpz_set_si(alloc4,0);
3277 	  // mpz_set_si(alloc5,0);
3278 	  alloc_mp_div(&x2,n._ZINTptr,&tmpq,&p,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
3279 	}
3280 	else
3281 	  mpz_set(p,x2);
3282 #else
3283 	mpz_tdiv_r(p,x2,*n._ZINTptr);
3284 #endif
3285 	c += 1;
3286 	if (c==POLLARD_GCD) {
3287 	  // g=gcd(abs(p,context0),n);
3288 	  mpz_abs(q,p);
3289 	  my_mpz_gcd(g,q,*n._ZINTptr);
3290 	  if (mpz_cmp_si(g,1)==0) {
3291 	    mpz_set(y,x); // y=x;
3292 	    mpz_set(y1,x1); // y1=x1;
3293 	    mpz_set_si(p,1); // p=1;
3294 	    a1=a;
3295 	    m1=m;
3296 	    c=0;
3297 	  }
3298 	}
3299       }//m=a=2^e-1=l(m)
3300       if (mpz_cmp_si(g,1)==0) {
3301 	mpz_set(x1,x); // x1=x;//x1=x_m=x_l(m)-1
3302 	j=3*(a+1)/2; // j=3*iquo(a+1,2);
3303 	for (long i=m+1;i<=j;i++){
3304 	  // x=f(x,k,n,q);
3305 	  mpz_mul(x2,x,x);
3306 	  mpz_add(x2k,x2,*k._ZINTptr);
3307 #if 0 // def USE_GMP_REPLACEMENTS
3308 	  if (mpz_cmp(x2k,*n._ZINTptr)>0){
3309 	    mp_grow(&alloc1,x2k.used+2);
3310 	    mpz_set_ui(alloc1,0);
3311 	    alloc1.used = x2k.used +2 ;
3312 	    mpz_set(alloc2,x2k);
3313 	    mpz_set(alloc3,*n._ZINTptr);
3314 	    // mpz_set_si(alloc4,0);
3315 	    // mpz_set_si(alloc5,0);
3316 	    alloc_mp_div(&x2k,n._ZINTptr,&tmpq,&x,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
3317 	  }
3318 	  else
3319 	    mpz_set(x,x2);
3320 #else
3321 	  mpz_tdiv_r(x,x2k,*n._ZINTptr);
3322 #endif
3323 	}
3324 	m=j;
3325       }
3326     }
3327     //g<>1 ds le paquet de POLLARD_GCD
3328     if (debug_infolevel>5)
3329       CERR << CLOCK() << " Pollard-rho nloops " << m << '\n';
3330     mpz_set(x,y); // x=y;
3331     mpz_set(x1,y1); // x1=y1;
3332     mpz_set_si(g,1); // g=1;
3333     a=(a1-1)/2; // a=iquo(a1-1,2);
3334     m=m1;
3335     while (!ctrl_c && !interrupted && mpz_cmp_si(g,1)==0) {
3336 #ifdef TIMEOUT
3337       control_c();
3338 #endif
3339       a=2*a+1;
3340       while (!ctrl_c && !interrupted && mpz_cmp_si(g,1)==0 && a>m) { // ok
3341 #ifdef TIMEOUT
3342 	control_c();
3343 #endif
3344 	// x=f(x,k,n,q);
3345 	mpz_mul(x2,x,x);
3346 	mpz_add(x2k,x2,*k._ZINTptr);
3347 #if 0 // def USE_GMP_REPLACEMENTS
3348 	if (mpz_cmp(x2k,*n._ZINTptr)>0){
3349 	  mp_grow(&alloc1,x2k.used+2);
3350 	  mpz_set_ui(alloc1,0);
3351 	  alloc1.used = x2k.used +2 ;
3352 	  mpz_set(alloc2,x2k);
3353 	  mpz_set(alloc3,*n._ZINTptr);
3354 	  alloc_mp_div(&x2k,n._ZINTptr,&tmpq,&x,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
3355 	}
3356 	else
3357 	  mpz_set(x,x2k);
3358 #else
3359 	mpz_tdiv_r(x,x2k,*n._ZINTptr);
3360 #endif
3361 	m += 1;
3362 	if (m > maxiter ){
3363 	  mpz_clear(alloc5);
3364 	  mpz_clear(alloc4);
3365 	  mpz_clear(alloc3);
3366 	  mpz_clear(alloc2);
3367 	  mpz_clear(alloc1);
3368 	  mpz_clear(tmpq);
3369 	  mpz_clear(x);
3370 	  mpz_clear(x1);
3371 	  mpz_clear(x2);
3372 	  mpz_clear(x2k);
3373 	  mpz_clear(y);
3374 	  mpz_clear(y1);
3375 	  mpz_clear(p);
3376 	  mpz_clear(q);
3377 	  return -1;
3378 	}
3379 	// p=irem(x1-x,n,q);
3380 	mpz_sub(q,x1,x);
3381 #if 0 // def USE_GMP_REPLACEMENTS
3382 	if (mpz_cmp(q,*n._ZINTptr)>0){
3383 	  mp_grow(&alloc1,q.used+2);
3384 	  mpz_set_ui(alloc1,0);
3385 	  alloc1.used = q.used +2 ;
3386 	  mpz_set(alloc2,q);
3387 	  mpz_set(alloc3,*n._ZINTptr);
3388 	  // mpz_set_si(alloc4,0);
3389 	  // mpz_set_si(alloc5,0);
3390 	  alloc_mp_div(&q,n._ZINTptr,&tmpq,&p,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
3391 	}
3392 	else
3393 	  mpz_set(p,q);
3394 #else
3395 	mpz_tdiv_r(p,q,*n._ZINTptr);
3396 #endif
3397 	// g=gcd(abs(p,context0),n);  // ok
3398 	mpz_abs(q,p);
3399 	my_mpz_gcd(g,q,*n._ZINTptr);
3400       }
3401       if (mpz_cmp_si(g,1)==0) {
3402 	mpz_set(x1,x); // x1=x;
3403 	j=3*(a+1)/2; // j=3*iquo(a+1,2);
3404 	for (long i=m+1;j>=i;i++){
3405 	  // x=f(x,k,n,q);
3406 	  mpz_mul(x2,x,x);
3407 	  mpz_add(x2k,x2,*k._ZINTptr);
3408 	  mpz_tdiv_qr(tmpq,x,x2k,*n._ZINTptr);
3409 	}
3410 	m=j;
3411       }
3412     }
3413     mpz_clear(alloc5);
3414     mpz_clear(alloc4);
3415     mpz_clear(alloc3);
3416     mpz_clear(alloc2);
3417     mpz_clear(alloc1);
3418     mpz_clear(tmpq);
3419     mpz_clear(x);
3420     mpz_clear(x1);
3421     mpz_clear(x2);
3422     mpz_clear(x2k);
3423     mpz_clear(y);
3424     mpz_clear(y1);
3425     mpz_clear(p);
3426     mpz_clear(q);
3427 #ifdef TIMEOUT
3428     control_c();
3429 #endif
3430     if (ctrl_c || interrupted){
3431       mpz_clear(g);
3432       return 0;
3433     }
3434     if (mpz_cmp(g,*n._ZINTptr)==0) {
3435       if (k==1) {
3436 	mpz_clear(g);
3437 	return(pollard(n,-1,contextptr));
3438       }
3439       else {
3440 	if (k*k==1){
3441 	  mpz_clear(g);
3442 	  return(pollard(n,3,contextptr));
3443 	}
3444 	else {
3445 	  if (is_greater(k,50,contextptr)){
3446 #if 1
3447 	    return -1;
3448 #else
3449 	    ref_mpz_t * ptr=new ref_mpz_t;
3450 	    mpz_init_set(ptr->z,g);
3451 	    mpz_clear(g);
3452 	    return ptr;
3453 #endif
3454 	  }
3455 	  else {
3456 	    mpz_clear(g);
3457 	    return(pollard(n,k+2,contextptr));
3458 	  }
3459 	}
3460       }
3461     }
3462     ref_mpz_t * ptr=new ref_mpz_t;
3463     mpz_init_set(ptr->z,g);
3464     mpz_clear(g);
3465     return ptr;
3466   }
3467 
3468   // const short int giac_primes[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997};
3469 
eratosthene(double n,vector<bool> * & v)3470   bool eratosthene(double n,vector<bool> * & v){
3471     static vector<bool> *ptr=0;
3472     if (!ptr)
3473       ptr=new vector<bool>;
3474     vector<bool> &erato=*ptr;
3475     v=ptr;
3476     if (n+1>erato.size()){
3477       unsigned N=int(n);
3478       ++N;
3479 #if defined BESTA_OS
3480       if (N>2e6)
3481 	return false;
3482 #else
3483       if (N>2e9)
3484 	return false;
3485 #endif
3486       N = (N*11)/10;
3487       erato=vector<bool>(N+1,true);
3488       // insure that we won't recompute all again from start for ithprime(i+1)
3489       for (unsigned p=2;;++p){
3490 	while (!erato[p]) // find next prime
3491 	  ++p;
3492 	if (p*p>N) // finished
3493 	  return true;
3494 	for (unsigned i=2*p;i<=N;i+=p)
3495 	  erato[i]=false; // remove p multiples
3496       }
3497     }
3498     return true;
3499   }
3500 
eratosthene2(double n,vector<bool> * & v)3501   bool eratosthene2(double n,vector<bool> * & v){
3502     static vector<bool> *ptr=0;
3503     if (!ptr)
3504       ptr=new vector<bool>;
3505     vector<bool> &erato=*ptr;
3506     v=ptr;
3507     if (n/2>=erato.size()){
3508       unsigned N=int(n);
3509       ++N;
3510 #if defined BESTA_OS
3511       if (N>4e6)
3512 	return false;
3513 #else
3514       if (N>2e9)
3515 	return false;
3516 #endif
3517       // 11/20 insures that we won't recompute all again from start for ithprime(i+1)
3518       N = (N*11)/20; // keep only odd numbers in sieve
3519       erato=vector<bool>(N+1,true); //erato[i] stands for 2*i+1 <-> n corresponds to erato[n/2]
3520       for (unsigned p=3;;p+=2){
3521 	while (!erato[p/2]) // find next prime (first one is p==3)
3522 	  p+=2;
3523 	if (p*p>2*N+1) // finished
3524 	  return true;
3525 	// p is prime, set p*p, (p+2)*p, etc. to be non prime
3526 	for (unsigned i=(p*p)/2;i<=N;i+=p)
3527 	  erato[i]=false; // remove p multiples
3528       }
3529     }
3530     return true;
3531   }
3532 
3533   // ithprime(n) is approx invli(n)+invli(sqrt(n))/4 where invli is reciproc.
3534   // of Li(x)=Ei(ln(x))
3535   // For fast code, cf. https://github.com/kimwalisch/primecount
3536   static const char _ithprime_s []="ithprime";
symb_ithprime(const gen & args)3537   static symbolic symb_ithprime(const gen & args){
3538     return symbolic(at_ithprime,args);
3539   }
ithprime(const gen & g_,GIAC_CONTEXT)3540   static gen ithprime(const gen & g_,GIAC_CONTEXT){
3541     gen g(g_);
3542     if (!is_integral(g))
3543       return gentypeerr(contextptr);
3544     if (g.type!=_INT_)
3545       return gensizeerr(contextptr); // symb_ithprime(g);
3546     int i=g.val;
3547     if (i<0)
3548       return gensizeerr(contextptr);
3549     if (i==0)
3550       return 1;
3551     if (i<=int(sizeof(giac_primes)/sizeof(short int)))
3552       return giac_primes[i-1];
3553     vector<bool> * vptr=0;
3554 #if 1
3555     if (!eratosthene2(i*std::log(double(i))*1.1,vptr))
3556       return gensizeerr(contextptr);
3557     unsigned count=2;
3558     unsigned s=unsigned(vptr->size());
3559     for (unsigned k=2;k<s;++k){
3560       if ((*vptr)[k]){
3561 	++count;
3562 	if (i==count)
3563 	  return int(2*k+1);
3564       }
3565     }
3566     return undef;
3567 #else
3568     if (!eratosthene(i*std::log(double(i))*1.1,vptr))
3569       return gensizeerr(contextptr);
3570     unsigned count=2;
3571     unsigned s=vptr->size();
3572     for (unsigned k=4;k<s;++k){
3573       if ((*vptr)[k]){
3574 	++count;
3575 	if (i==count)
3576 	  return int(k);
3577       }
3578     }
3579     return undef;
3580 #endif
3581   }
_ithprime(const gen & args,GIAC_CONTEXT)3582   gen _ithprime(const gen & args,GIAC_CONTEXT){
3583     if ( args.type==_STRNG && args.subtype==-1) return  args;
3584     if (args.type==_VECT)
3585       return apply(args,_ithprime,contextptr);
3586     return ithprime(args,contextptr);
3587   }
3588   static define_unary_function_eval (__ithprime,&_ithprime,_ithprime_s);
3589   define_unary_function_ptr5( at_ithprime ,alias_at_ithprime,&__ithprime,0,true);
3590 
3591   static const char _nprimes_s []="nprimes";
nprimes(const gen & g_,GIAC_CONTEXT)3592   static gen nprimes(const gen & g_,GIAC_CONTEXT){
3593     gen g(g_);
3594     if (!is_integral(g))
3595       return gentypeerr(contextptr);
3596     if (g.type!=_INT_)
3597       return gensizeerr(contextptr); // symb_ithprime(g);
3598     int i=g.val;
3599     if (i<0)
3600       return gensizeerr(contextptr);
3601     if (i<2)
3602       return 0;
3603     vector<bool> * vptr=0;
3604     if (!eratosthene2(i+2,vptr))
3605       return gensizeerr(contextptr);
3606     unsigned count=1; // 2 is prime, then count odd primes
3607     i=(i-1)/2;
3608     for (int k=1;k<=i;++k){
3609       if ((*vptr)[k])
3610 	++count;
3611     }
3612     return int(count);
3613   }
_nprimes(const gen & args,GIAC_CONTEXT)3614   gen _nprimes(const gen & args,GIAC_CONTEXT){
3615     if ( args.type==_STRNG && args.subtype==-1) return  args;
3616     if (args.type==_VECT)
3617       return apply(args,_nprimes,contextptr);
3618     return nprimes(args,contextptr);
3619   }
3620   static define_unary_function_eval (__nprimes,&_nprimes,_nprimes_s);
3621   define_unary_function_ptr5( at_nprimes ,alias_at_nprimes,&__nprimes,0,true);
3622 
is_divisible_by(const gen & n,unsigned long a)3623   bool is_divisible_by(const gen & n,unsigned long a){
3624     if (n.type==_ZINT){
3625 #ifdef USE_GMP_REPLACEMENTS
3626       mp_digit c;
3627       mp_mod_d(n._ZINTptr, a, &c);
3628       return c==0;
3629 #else
3630       return mpz_divisible_ui_p(*n._ZINTptr,a);
3631 #endif
3632     }
3633     return n.val%a==0;
3634   }
3635 
3636   // find trivial factors of n,
3637   // if add_last is true the remainder is put in the vecteur,
3638   // otherwise n contains the remainder
pfacprem(gen & n,bool add_last,GIAC_CONTEXT)3639   vecteur pfacprem(gen & n,bool add_last,GIAC_CONTEXT){
3640     gen a;
3641     gen q;
3642     int p,i,prime;
3643     vecteur v(2);
3644     vecteur u;
3645     if (is_zero(n))
3646       return u;
3647     if (n.type==_ZINT){
3648       ref_mpz_t * cur = new ref_mpz_t;
3649       mpz_t div,q,r,alloc1,alloc2,alloc3,alloc4,alloc5;
3650       mpz_set(cur->z,*n._ZINTptr);
3651       mpz_init_set(q,*n._ZINTptr);
3652       mpz_init(r);
3653       mpz_init(div);
3654       mpz_init(alloc1);
3655       mpz_init(alloc2);
3656       mpz_init(alloc3);
3657       mpz_init(alloc4);
3658       mpz_init(alloc5);
3659       for (i=0;i<int(sizeof(giac_primes)/sizeof(short int));++i){
3660 	if (mpz_cmp_si(cur->z,1)==0)
3661 	  break;
3662 	prime=giac_primes[i];
3663 	mpz_set_ui(div,prime);
3664 #ifdef USE_GMP_REPLACEMENTS
3665 	for (p=0;;p++){
3666 	  mp_grow(&alloc1,cur->z.used+2);
3667 	  mpz_set_ui(alloc1,0);
3668 	  alloc1.used = cur->z.used +2 ;
3669 	  mpz_set(alloc2,cur->z);
3670 	  mpz_set(alloc3,div);
3671 	  alloc_mp_div(&cur->z,&div,&q,&r,&alloc1,&alloc2,&alloc3,&alloc4,&alloc5);
3672 	  // mpz_tdiv_qr(q,r,cur->z,div);
3673 	  if (mpz_cmp_si(r,0))
3674 	    break;
3675 	  mp_exch(&cur->z,&q);
3676 	}
3677 	// *logptr(contextptr) << "Factor " << prime << " " << p << '\n';
3678 	if (p){
3679 	  u.push_back(prime);
3680 	  u.push_back(p);
3681 	}
3682 #else
3683 	if (mpz_divisible_ui_p(cur->z,prime)){
3684 	  mpz_set_ui(div,prime);
3685 	  for (p=0;;p++){
3686 	    mpz_tdiv_qr(q,r,cur->z,div);
3687 	    if (mpz_cmp_si(r,0))
3688 	      break;
3689 	    mpz_swap(cur->z,q);
3690 	  }
3691 	  // *logptr(contextptr) << "Factor " << prime << " " << p << '\n';
3692 	  u.push_back(prime);
3693 	  u.push_back(p);
3694 	}
3695 #endif
3696       } // end for on smal primes
3697       mpz_clear(alloc5);
3698       mpz_clear(alloc4);
3699       mpz_clear(alloc3);
3700       mpz_clear(alloc2);
3701       mpz_clear(alloc1);
3702       mpz_clear(div); mpz_clear(r); mpz_clear(q);
3703       n=cur;
3704     }
3705     else {
3706       for (i=0;i<int(sizeof(giac_primes)/sizeof(short int));++i){
3707 	if (n==1)
3708 	  break;
3709 	a.val=giac_primes[i];
3710 	p=0;
3711 	while (is_divisible_by(n,a.val)){ // while (irem(n,a,q)==0){
3712 	  n=iquo(n,a);
3713 	  p=p+1;
3714 	}
3715 	if (p!=0){
3716 	  // *logptr(contextptr) << "Factor " << a << " " << p << '\n';
3717 	  u.push_back(a);
3718 	  u.push_back(p);
3719 	}
3720       }
3721     }
3722     if (add_last && i==1229 && !is_one(n)){
3723       // hack: check if n is a perfect square
3724       double nf=evalf_double(n,1,contextptr)._DOUBLE_val;
3725       nf=std::sqrt(nf);
3726       gen n2=_round(nf,contextptr);
3727       if (n2*n2==n){
3728 	u.push_back(n2);
3729 	u.push_back(2);
3730       }
3731       else {
3732 	u.push_back(n);
3733 	u.push_back(1);
3734       }
3735       n=1;
3736     }
3737     //v[0]=n;
3738     //v[1]=u;
3739 
3740     return(u);
3741   }
3742 
3743 #ifdef USE_GMP_REPLACEMENTS
inpollardsieve(const gen & a,gen k,bool & do_pollard,GIAC_CONTEXT)3744   static gen inpollardsieve(const gen &a,gen k,bool & do_pollard,GIAC_CONTEXT){
3745     gen b=do_pollard?pollard(a,k,contextptr):-1;
3746 #ifdef TIMEOUT
3747     control_c();
3748 #endif
3749 #ifdef GIAC_MPQS
3750     if (b==-1 && !ctrl_c && !interrupted){
3751       do_pollard=false;
3752       if (msieve(a,b,contextptr)) return b; else return -1; }
3753 #endif
3754     return b;
3755   }
pollardsieve(const gen & a,gen k,bool & do_pollard,GIAC_CONTEXT)3756   static gen pollardsieve(const gen &a,gen k,bool & do_pollard,GIAC_CONTEXT){
3757 #if defined( GIAC_HAS_STO_38) || defined(EMCC) || defined NSPIRE
3758     int debug_infolevel_=debug_infolevel;
3759 #if defined RTOS_THREADX || defined NSPIRE
3760     debug_infolevel=2;
3761     if (do_pollard)
3762       *logptr(contextptr) << gettext("Pollard-rho on ") << a << '\n';
3763 #else
3764     debug_infolevel=0;
3765 #endif
3766 #endif
3767     gen res=inpollardsieve(a,k,do_pollard,contextptr);
3768 #if defined( GIAC_HAS_STO_38) || defined(EMCC) || defined NSPIRE
3769     debug_infolevel=debug_infolevel_;
3770 #ifdef GIAC_HAS_STO_38
3771     Calc->Terminal.MakeUnvisible();
3772 #endif
3773 #endif
3774     return res;
3775   }
3776 #else // USE_GMP_REPLACEMENTS
pollardsieve(const gen & a,gen k,bool & do_pollard,GIAC_CONTEXT)3777   static gen pollardsieve(const gen &a,gen k,bool & do_pollard,GIAC_CONTEXT){
3778     gen b=do_pollard?pollard(a,k,contextptr):-1;
3779 #ifdef TIMEOUT
3780     control_c();
3781 #endif
3782 #ifdef HAVE_LIBECM
3783     if (is_greater(a,1e60,context0) && b==-1  && !ctrl_c && !interrupted && _isprime(a,contextptr)==0){
3784       int res;
3785       gen F(1LL<<33);
3786       for (int i=0;i<200;++i){ // searching factors of size about 20 digits
3787 	res=ecm_factor(*F._ZINTptr, *a._ZINTptr, 11e3, 0);
3788 	if (res!=0) break;
3789       }
3790       if (res!=0)
3791 	b=F;
3792     }
3793 #endif
3794 #ifdef GIAC_MPQS
3795     if (b==-1 && !ctrl_c && !interrupted){
3796       do_pollard=false;
3797       if (msieve(a,b,contextptr)) return b; else return -1; }
3798 #else
3799     if (b==-1)
3800       *logptr(contextptr) << "Integer too large for factorization algorithm\n";
3801 #endif
3802     if (b==-1)
3803       b=a;
3804     return b;
3805   }
3806 #endif // USE_GMP_REPLACEMENTS
3807 
ifactor2(const gen & n,vecteur & v,bool & do_pollard,GIAC_CONTEXT)3808   static gen ifactor2(const gen & n,vecteur & v,bool & do_pollard,GIAC_CONTEXT){
3809     if (is_greater(giac_last_prime*giac_last_prime,n,contextptr) || is_probab_prime_p(n) ){
3810       v.push_back(n);
3811       return 1;
3812     }
3813     // Check for power of integer: arg must be > 1e4, n*ln(arg)=d => n<d/ln(1e4)
3814     double d=evalf_double(n,1,contextptr)._DOUBLE_val;
3815     int maxpow=int(std::ceil(std::log(d)/std::log(1e4)));
3816     for (int i=2;i<=maxpow;++i){
3817       if ( (i>2 && i%2==0) ||
3818 	   (i>3 && i%3==0) ||
3819 	   (i>5 && i%5==0) ||
3820 	   (i>7 && i%7==0) )
3821 	continue;
3822       gen u;
3823       if (i==2)
3824 	u=isqrt(n);
3825       else {
3826 	double x=std::pow(d,1./i);
3827 	u=longlong(x);
3828       }
3829       if (pow(u,i,contextptr)==n){
3830 	vecteur w;
3831 	do_pollard=true;
3832 	ifactor2(u,w,do_pollard,contextptr);
3833 	for (int j=0;j<i;j++)
3834 	  v=mergevecteur(v,w);
3835 	return v;
3836       }
3837     }
3838     gen a=pollardsieve(n,1,do_pollard,contextptr);
3839     if (a==-1)
3840       return a;
3841 #ifdef TIMEOUT
3842     control_c();
3843 #endif
3844     if (ctrl_c || interrupted)
3845       return gensizeerr("Interrupted");
3846     gen ba=n/a;
3847     if (a!=n)
3848       a=ifactor2(a,v,do_pollard,contextptr);
3849     else {
3850       a=1;
3851       v.push_back(n);
3852     }
3853     if (is_strictly_greater(ba,1,contextptr))
3854       a=ifactor2(ba,v,do_pollard,contextptr);
3855     return a;
3856   }
3857 
facprem(gen & n,GIAC_CONTEXT)3858   static vecteur facprem(gen & n,GIAC_CONTEXT){
3859     vecteur v;
3860     if (n==1) { return v; }
3861     if ( (n.type==_INT_ && n.val<giac_last_prime*giac_last_prime) || is_probab_prime_p(n)) {
3862       v.push_back(n);
3863       n=1;
3864       return v;
3865     }
3866     if (debug_infolevel>5)
3867       CERR << "Pollard begin " << CLOCK() << '\n';
3868     bool do_pollard=true;
3869     gen a=ifactor2(n,v,do_pollard,contextptr);
3870     if (a==-1)
3871       return makevecteur(gensizeerr(gettext("Quadratic sieve failure, perhaps number too large")));
3872     if (is_zero(a))
3873       return makevecteur(gensizeerr(gettext("Stopped by user interruption")));
3874     n=1;
3875     return v;
3876   }
3877 
mergeifactors(const vecteur & f,const vecteur & g,vecteur & h)3878   void mergeifactors(const vecteur & f,const vecteur &g,vecteur & h){
3879     h=f;
3880     for (unsigned i=0;i<g.size();i+=2){
3881       unsigned j=0;
3882       for (;j<f.size();j+=2){
3883 	if (f[j]==g[i])
3884 	  break;
3885       }
3886       if (j<f.size())
3887 	h[j+1] += g[i+1];
3888       else {
3889 	h.push_back(g[i]);
3890 	h.push_back(g[i+1]);
3891       }
3892     }
3893   }
3894 
giac_ifactors(const gen & n0,GIAC_CONTEXT)3895   static vecteur giac_ifactors(const gen & n0,GIAC_CONTEXT){
3896     if (!is_integer(n0) || is_zero(n0))
3897       return vecteur(1,gensizeerr(gettext("ifactors")));
3898     if (is_one(n0))
3899       return vecteur(0);
3900     gen n(n0);
3901     vecteur f;
3902     vecteur g;
3903     vecteur u;
3904     // First find if |n-k^d|<=1 for d = 2, 3, 5 or 7
3905     double nd=evalf_double(n,1,contextptr)._DOUBLE_val;
3906     double nd2=std::floor(std::sqrt(nd)+.5);
3907     if (absdouble(1-nd2*nd2/nd)<1e-10){
3908       gen n2=isqrt(n+1);
3909       if (n==n2*n2){
3910 	f=ifactors(n2,contextptr);
3911 	iterateur it=f.begin(),itend=f.end();
3912 	for (;it!=itend;++it){
3913 	  ++it;
3914 	  *it = 2 * *it;
3915 	}
3916 	return f;
3917       }
3918       if (n==n2*n2-1){
3919 	f=ifactors(n2-1,contextptr);
3920 	g=ifactors(n2+1,contextptr);
3921 	mergeifactors(f,g,u);
3922 	return u;
3923       }
3924     }
3925     for (int k=3;;){
3926       nd2=std::floor(std::pow(nd,1./k)+.5);
3927       if (absdouble(1-std::pow(nd2,k)/nd)<1e-10){
3928 	gen n2=_floor(nd2,contextptr),nf=n2*n2;
3929 	for (int j=2;j<k;j++)
3930 	  nf=nf*n2;
3931 	if (n==nf){
3932 	  f=ifactors(n2,contextptr);
3933 	  iterateur it=f.begin(),itend=f.end();
3934 	  for (;it!=itend;++it){
3935 	    ++it;
3936 	    *it = k * *it;
3937 	  }
3938 	  return f;
3939 	}
3940 	if (n==nf-1){ // n2^k-1
3941 	  f=ifactors(n2-1,contextptr);
3942 	  g=ifactors(n/(n2-1),contextptr);
3943 	  mergeifactors(f,g,u);
3944 	  return u;
3945 	}
3946 	if (n==nf+1){ // n2^k+1
3947 	  f=ifactors(n2+1,contextptr);
3948 	  g=ifactors(n/(n2+1),contextptr);
3949 	  mergeifactors(f,g,u);
3950 	  return u;
3951 	}
3952       }
3953       if (k==11) break;
3954       if (k==7) break; // k=11;
3955       if (k==5) k=7;
3956       if (k==3) k=5;
3957     }
3958     //f=pfacprem(n,false,contextptr);
3959     //cout<<n<<" "<<f<<'\n';
3960     while (n!=1) {
3961       g=facprem(n,contextptr);
3962       if (is_undef(g))
3963 	return g;
3964       islesscomplexthanf_sort(g.begin(),g.end());
3965       gen last=0; int p=0;
3966       for (unsigned i=0;i<g.size();++i){
3967 	if (g[i]==last)
3968 	  ++p;
3969 	else {
3970 	  if (last!=0){
3971 	    u.push_back(last);
3972 	    u.push_back(p);
3973 	  }
3974 	  last=g[i];
3975 	  p=1;
3976 	}
3977       }
3978       u.push_back(last);
3979       u.push_back(p);
3980     }
3981     g=mergevecteur(f,u);
3982     return g;
3983   }
3984 
ifactors1(const gen & n0,GIAC_CONTEXT)3985   static vecteur ifactors1(const gen & n0,GIAC_CONTEXT){
3986     if (is_greater(1e71,n0,contextptr))
3987       return giac_ifactors(n0,contextptr);
3988     if (n0.type==_VECT && !n0._VECTptr->empty())
3989       return giac_ifactors(n0._VECTptr->front(),contextptr);
3990     if (!is_integer(n0) || is_zero(n0))
3991       return vecteur(1,gensizeerr(gettext("ifactors")));
3992     if (is_one(n0))
3993       return vecteur(0);
3994     if (_isprime(n0,contextptr)!=0)
3995       return makevecteur(n0,1);
3996 #ifdef HAVE_LIBECM
3997     int res;
3998     gen F(1LL<<33);
3999     double B1=1e6;
4000     for (int i=0;i<ECM_MAXITER;++i){
4001       res=ecm_factor(*F._ZINTptr, *n0._ZINTptr, B1, 0);
4002       if (res!=0) break;
4003     }
4004     if (res!=0){
4005       vecteur tmp=ifactors1(n0/F,contextptr);
4006       tmp.push_back(F);
4007       tmp.push_back(1);
4008       return tmp;
4009     }
4010 #endif
4011 #ifdef HAVE_LIBPARI
4012 #ifdef __APPLE__
4013     return vecteur(1,gensizeerr(gettext("(Mac OS) Large number, you can try pari(); pari_factor(")+n0.print(contextptr)+")"));
4014 #endif
4015     gen g(pari_ifactor(n0),contextptr);
4016     if (g.type==_VECT){
4017       matrice m(mtran(*g._VECTptr));
4018       vecteur res;
4019       const_iterateur it=m.begin(),itend=m.end();
4020       for (;it!=itend;++it){
4021 	if (it->type!=_VECT) return vecteur(1,gensizeerr(gettext("ifactor.cc/ifactors")));
4022 	res.push_back(it->_VECTptr->front());
4023 	res.push_back(it->_VECTptr->back());
4024       }
4025       return res;
4026     }
4027 #endif // LIBPARI
4028     return giac_ifactors(n0,contextptr);
4029   }
4030 
ifactors(const gen & n0,GIAC_CONTEXT)4031   vecteur ifactors(const gen & n0,GIAC_CONTEXT){
4032     gen n(n0);
4033     vecteur f=pfacprem(n,false,contextptr);
4034     if (is_undef(f))
4035       return f;
4036     vecteur g=ifactors1(n,contextptr);
4037     if (is_undef(g))
4038       return g;
4039     return mergevecteur(f,g);
4040   }
4041 
ifactors(const gen & r,const gen & i,const gen & ri,GIAC_CONTEXT)4042   vecteur ifactors(const gen & r,const gen & i,const gen & ri,GIAC_CONTEXT){
4043     gen norm=r*r+i*i;
4044     gen reste(ri);
4045     const vecteur & facto = ifactors(norm,contextptr);
4046     if (is_undef(facto))
4047       return facto;
4048     int l=int(facto.size())/2;
4049     vecteur res;
4050     for (int i=0;i<l;++i){
4051       gen prime=facto[2*i];
4052       int mult=facto[2*i+1].val,multp=0;
4053       int n=smod(prime,4).val;
4054       if (n==2){
4055 	res.push_back(1+cst_i);
4056 	res.push_back(mult);
4057 	reste=reste/pow(1+cst_i,mult,contextptr);
4058 	continue;
4059       }
4060       if (n==-1){
4061 	res.push_back(prime);
4062 	res.push_back(mult/2);
4063 	reste=reste/pow(prime,mult/2,contextptr);
4064 	continue;
4065       }
4066       prime=pa2b2(prime,contextptr);
4067       prime=gen(prime[0],prime[1]);
4068       for (;mult>0;--mult,++multp){
4069 	if (!is_zero(reste % prime))
4070 	  break;
4071 	reste=reste/prime;
4072       }
4073       if (multp){
4074 	res.push_back(prime);
4075 	res.push_back(multp);
4076       }
4077       if (mult){
4078 	prime=conj(prime,contextptr);
4079 	res.push_back(prime);
4080 	res.push_back(mult);
4081 	reste=reste/pow(prime,mult,contextptr);
4082       }
4083     }
4084     if (!is_one(reste)){
4085       res.insert(res.begin(),1);
4086       res.insert(res.begin(),reste);
4087     }
4088     return res;
4089   }
4090 
ifactors(const gen & args,int maplemode,GIAC_CONTEXT)4091   gen ifactors(const gen & args,int maplemode,GIAC_CONTEXT){
4092     if ( (args.type==_INT_) || (args.type==_ZINT)){
4093       if (is_zero(args)){
4094 	if (maplemode==1)
4095 	  return makevecteur(args,vecteur(0));
4096 	else
4097 	  return makevecteur(args);
4098       }
4099       vecteur v(ifactors(abs(args,contextptr),contextptr)); // ok
4100       if (!v.empty() && is_undef(v.front()))
4101 	return v.front();
4102       if (maplemode!=1){
4103 	if (is_positive(args,context0))
4104 	  return v;
4105 	return mergevecteur(makevecteur(minus_one,plus_one),v);
4106       }
4107       vecteur res;
4108       const_iterateur it=v.begin(),itend=v.end();
4109       for (;it!=itend;it+=2){
4110 	res.push_back(makevecteur(*it,*(it+1)));
4111       }
4112       if (is_positive(args,context0))
4113 	return makevecteur(plus_one,res);
4114       else
4115 	return makevecteur(minus_one,res);
4116     }
4117     if (args.type==_CPLX && is_integer(*args._CPLXptr) && is_integer(*(args._CPLXptr+1)))
4118       return ifactors(*args._CPLXptr,*(args._CPLXptr+1),args,contextptr);
4119     return gentypeerr(gettext("ifactors"));
4120   }
4121 
_ifactors(const gen & args,GIAC_CONTEXT)4122   gen _ifactors(const gen & args,GIAC_CONTEXT){
4123     if ( args.type==_STRNG && args.subtype==-1) return  args;
4124     if (args.type==_VECT && args.subtype==_SEQ__VECT && args._VECTptr->size()==2 && args._VECTptr->back()==at_matrix){
4125       gen g=args._VECTptr->front();
4126       g=_ifactors(g,contextptr);
4127       if (g.type!=_VECT || g._VECTptr->size()%2)
4128 	return g;
4129       return _matrix(makesequence(g._VECTptr->size()/2,2,g),contextptr);
4130     }
4131     if (args.type==_VECT)
4132       return apply(args,_ifactors,contextptr);
4133     gen g(args);
4134     if (!is_integral(g))
4135       return gensizeerr(contextptr);
4136     if (calc_mode(contextptr)==1){ // ggb returns factors repeted instead of multiplicites
4137       vecteur res;
4138       gen in=ifactors(g,0,contextptr);
4139       if (in.type==_VECT){
4140 	for (unsigned i=0;i<in._VECTptr->size();i+=2){
4141 	  gen f=in[i],m=in[i+1];
4142 	  if (m.type==_INT_){
4143 	    for (int j=0;j<m.val;++j)
4144 	      res.push_back(f);
4145 	  }
4146 	}
4147 	return res;
4148       }
4149     }
4150     return ifactors(g,0,contextptr);
4151   }
4152   static const char _ifactors_s []="ifactors";
4153   static define_unary_function_eval (__ifactors,&_ifactors,_ifactors_s);
4154   define_unary_function_ptr5( at_ifactors ,alias_at_ifactors,&__ifactors,0,true);
4155 
4156   static const char _facteurs_premiers_s []="facteurs_premiers";
4157   static define_unary_function_eval (__facteurs_premiers,&_ifactors,_facteurs_premiers_s);
4158   define_unary_function_ptr5( at_facteurs_premiers ,alias_at_facteurs_premiers,&__facteurs_premiers,0,true);
4159 
4160   static const char _maple_ifactors_s []="maple_ifactors";
_maple_ifactors(const gen & args,GIAC_CONTEXT)4161   gen _maple_ifactors(const gen & args,GIAC_CONTEXT){
4162     if ( args.type==_STRNG && args.subtype==-1) return  args;
4163     if (args.type==_VECT)
4164       return apply(args,_maple_ifactors,contextptr);
4165     return ifactors(args,1,contextptr);
4166   }
4167   static define_unary_function_eval (__maple_ifactors,&_maple_ifactors,_maple_ifactors_s);
4168   define_unary_function_ptr5( at_maple_ifactors ,alias_at_maple_ifactors,&__maple_ifactors,0,true);
4169 
in_factors(const gen & gf,GIAC_CONTEXT)4170   static vecteur in_factors(const gen & gf,GIAC_CONTEXT){
4171     if (gf.type!=_SYMB)
4172       return makevecteur(gf,plus_one);
4173     unary_function_ptr & u=gf._SYMBptr->sommet;
4174     if (u==at_inv){
4175       vecteur v=in_factors(gf._SYMBptr->feuille,contextptr);
4176       iterateur it=v.begin(),itend=v.end();
4177       for (;it!=itend;it+=2)
4178 	*(it+1)=-*(it+1);
4179       return v;
4180     }
4181     if (u==at_neg){
4182       vecteur v=in_factors(gf._SYMBptr->feuille,contextptr);
4183       v.push_back(minus_one);
4184       v.push_back(plus_one);
4185       return v;
4186     }
4187     if ( (u==at_pow) && (gf._SYMBptr->feuille._VECTptr->back().type==_INT_) ){
4188       vecteur v=in_factors(gf._SYMBptr->feuille._VECTptr->front(),contextptr);
4189       gen k=gf._SYMBptr->feuille._VECTptr->back();
4190       iterateur it=v.begin(),itend=v.end();
4191       for (;it!=itend;it+=2)
4192 	*(it+1)=k* *(it+1);
4193       return v;
4194     }
4195     if (u!=at_prod)
4196       return makevecteur(gf,plus_one);
4197     vecteur res;
4198     const_iterateur it=gf._SYMBptr->feuille._VECTptr->begin(),itend=gf._SYMBptr->feuille._VECTptr->end();
4199     for (;it!=itend;++it){
4200       res=mergevecteur(res,in_factors(*it,contextptr));
4201     }
4202     return res;
4203   }
in_factors1(const vecteur & res,GIAC_CONTEXT)4204   static vecteur in_factors1(const vecteur & res,GIAC_CONTEXT){
4205     gen coeff(1);
4206     vecteur v;
4207     const_iterateur it=res.begin(),itend=res.end();
4208     for (;it!=itend;it+=2){
4209       if (lidnt(*it).empty())
4210 	coeff=coeff*(pow(*it,*(it+1),contextptr));
4211       else
4212 	v.push_back(makevecteur(*it,*(it+1)));
4213     }
4214     return makevecteur(coeff,v);
4215   }
factors(const gen & g,const gen & x,GIAC_CONTEXT)4216   vecteur factors(const gen & g,const gen & x,GIAC_CONTEXT){
4217     gen gf=factor(g,x,false,contextptr);
4218     vecteur res=in_factors(gf,contextptr);
4219     if (xcas_mode(contextptr)!=1)
4220       return res;
4221     return in_factors1(res,contextptr);
4222   }
sqff_factors(const gen & g,GIAC_CONTEXT)4223   vecteur sqff_factors(const gen & g,GIAC_CONTEXT){
4224     gen gf=_sqrfree(g,contextptr);
4225     return in_factors(gf,contextptr);
4226   }
4227   static const char _factors_s []="factors";
_factors(const gen & args,GIAC_CONTEXT)4228   gen _factors(const gen & args,GIAC_CONTEXT){
4229     if ( args.type==_STRNG && args.subtype==-1) return  args;
4230     if (args.type==_VECT && args.subtype==_SEQ__VECT && args._VECTptr->size()>=2 && args._VECTptr->back()==at_matrix){
4231       gen g;
4232       if (args._VECTptr->size()==2)
4233 	g=args._VECTptr->front();
4234       else
4235 	g=gen(vecteur(args._VECTptr->begin(),args._VECTptr->end()-1),_SEQ__VECT);
4236       g=_factors(g,contextptr);
4237       if (g.type!=_VECT || g._VECTptr->size()%2)
4238 	return g;
4239       return _matrix(makesequence(g._VECTptr->size()/2,2,g),contextptr);
4240     }
4241     if (args.type==_VECT && args.subtype==_POLY1__VECT){
4242       gen x(identificateur("xfactors"));
4243       gen res=_poly2symb(makesequence(args,x),contextptr);
4244       res=_factors(res,contextptr);
4245       if (res.type==_VECT && res._VECTptr->size()==2){
4246 	vecteur v(*res._VECTptr);
4247 	for (size_t i=0;i<v.size();i+=2){
4248 	  v[i]=_symb2poly(makesequence(v[i],x),contextptr);
4249 	}
4250 	return v;
4251       }
4252       return res;
4253     }
4254     if (args.type==_VECT && args.subtype==_SEQ__VECT && args._VECTptr->size()==2){
4255       gen j=args._VECTptr->back();
4256       gen res=_factors(args._VECTptr->front()*j,contextptr);
4257       if (res.type==_VECT && xcas_mode(contextptr)!=1)
4258 	res=in_factors1(*res._VECTptr,contextptr);
4259       if (res.type==_VECT && res._VECTptr->size()==2){
4260 	res._VECTptr->front()=recursive_normal(res._VECTptr->front()/j,contextptr);
4261 	if (xcas_mode(contextptr)!=1){
4262 	  if (is_one(res._VECTptr->front()))
4263 	    res=res._VECTptr->back();
4264 	  else {
4265 	    j=res._VECTptr->front();
4266 	    res=res._VECTptr->back();
4267 	    if (res.type==_VECT)
4268 	      res=mergevecteur(makevecteur(j,1),*res._VECTptr);
4269 	  }
4270 	  vecteur v;
4271 	  aplatir(*res._VECTptr,v,contextptr);
4272 	  res=v;
4273 	}
4274       }
4275       return res;
4276     }
4277     if (args.type==_VECT)
4278       return apply(args,_factors,contextptr);
4279     return factors(args,vx_var,contextptr);
4280   }
4281   static define_unary_function_eval (__factors,&_factors,_factors_s);
4282   define_unary_function_ptr5( at_factors ,alias_at_factors,&__factors,0,true);
4283 
ifactors2ifactor(const vecteur & l,bool quote)4284   static gen ifactors2ifactor(const vecteur & l,bool quote){
4285     int s;
4286     s=int(l.size());
4287     gen r;
4288     vecteur v(s/2);
4289     for (int j=0;j<s;j=j+2){
4290       if (!is_one(l[j+1]))
4291 	v[j/2]=symbolic(at_pow,gen(makevecteur(l[j],l[j+1]),_SEQ__VECT));
4292       else
4293 	v[j/2]=l[j];
4294     }
4295     if (v.size()==1){
4296 #if defined(GIAC_HAS_STO_38) && defined(CAS38_DISABLED)
4297       return symb_quote(v.front());
4298 #else
4299       if (quote)
4300 	return symb_quote(v.front());
4301       return v.front();
4302 #endif
4303     }
4304     r=symbolic(at_prod,gen(v,_SEQ__VECT));
4305 #if defined(GIAC_HAS_STO_38) && defined(CAS38_DISABLED)
4306     r=symb_quote(r);
4307 #endif
4308     if (quote)
4309       return symb_quote(r);
4310     return r;
4311   }
ifactor(const gen & n,GIAC_CONTEXT)4312   gen ifactor(const gen & n,GIAC_CONTEXT){
4313     vecteur l;
4314     l=ifactors(n,contextptr);
4315     if (!l.empty() && is_undef(l.front())) return l.front();
4316     return ifactors2ifactor(l,calc_mode(contextptr)==1);
4317   }
_ifactor(const gen & args,GIAC_CONTEXT)4318   gen _ifactor(const gen & args,GIAC_CONTEXT){
4319     if ( args.type==_STRNG && args.subtype==-1) return  args;
4320     if (args.type==_CPLX && is_integer(*args._CPLXptr) && is_integer(*(args._CPLXptr+1))){
4321       const vecteur & v=ifactors(*args._CPLXptr,*(args._CPLXptr+1),args,contextptr);
4322       return ifactors2ifactor(v,calc_mode(contextptr)==1);
4323     }
4324     gen n=args;
4325     if (n.type==_VECT && n._VECTptr->size()==1 && is_integer(n._VECTptr->front()))
4326       return ifactor(n,contextptr);
4327     if (n.type==_VECT)
4328       return apply(n,_ifactor,contextptr);
4329     if (!is_integral(n))
4330       return gensizeerr(contextptr);
4331     if (is_strictly_positive(-n,0))
4332       return -_ifactor(-n,contextptr);
4333     if (n.type==_INT_ && n.val<=3)
4334       return n;
4335     return ifactor(n,contextptr);
4336   }
4337   static const char _ifactor_s []="ifactor";
4338   static define_unary_function_eval (__ifactor,&_ifactor,_ifactor_s);
4339   define_unary_function_ptr5( at_ifactor ,alias_at_ifactor,&__ifactor,0,true);
4340 
4341   static const char _factoriser_entier_s []="factoriser_entier";
4342   static define_unary_function_eval (__factoriser_entier,&_ifactor,_factoriser_entier_s);
4343   define_unary_function_ptr5( at_factoriser_entier ,alias_at_factoriser_entier,&__factoriser_entier,0,true);
4344 
divis(const vecteur & l3,GIAC_CONTEXT)4345   static vecteur divis(const vecteur & l3,GIAC_CONTEXT){
4346     vecteur l1(1);
4347     gen d,e;
4348     int s=int(l3.size());
4349     gen taille=1;
4350     for (int k=0;k<s;k+=2){
4351       taille=taille*(l3[k+1]+1);
4352     }
4353     if (taille.type!=_INT_ || taille.val>LIST_SIZE_LIMIT)
4354       return vecteur(1,gendimerr(contextptr));
4355     l1.reserve(taille.val);
4356     l1[0]=1;//l3.push_back(..);
4357     for (int k=0;k<s;k=k+2) {
4358       vecteur l2;
4359       l2.reserve(taille.val);
4360       int s1;
4361       s1=int(l1.size());
4362       vecteur l4(s1);
4363       d=l3[k];
4364       e=l3[k+1];
4365       int ei;
4366       if (e.type==_INT_){
4367 	ei=e.val;
4368       }
4369       else
4370 	return vecteur(1,gensizeerr(gettext("Integer too large")));
4371       for (int j=1;j<=ei;j++){
4372 	gen dj=pow(d,j);
4373 	for (int l=0;l<s1;l++){
4374 	  l4[l]=l1[l]*dj;
4375 	}
4376 	// l2=mergevecteur(l2,l4);
4377 	iterateur it=l4.begin(),itend=l4.end();
4378 	for (;it!=itend;++it)
4379 	  l2.push_back(*it);
4380       }
4381       // l1=mergevecteur(l1,l2);
4382       iterateur it=l2.begin(),itend=l2.end();
4383       for (;it!=itend;++it)
4384 	l1.push_back(*it);
4385     }
4386     return(l1);
4387   }
idivis(const gen & n,GIAC_CONTEXT)4388   gen idivis(const gen & n,GIAC_CONTEXT){
4389     vecteur l3(ifactors(n,contextptr));
4390     if (!l3.empty() && is_undef(l3.front())) return l3.front();
4391     return divis(l3,contextptr);
4392   }
_idivis(const gen & args,GIAC_CONTEXT)4393   gen _idivis(const gen & args,GIAC_CONTEXT){
4394     if ( args.type==_STRNG && args.subtype==-1) return  args;
4395     if (args.type==_VECT)
4396       return apply(args,_idivis,contextptr);
4397     gen n=args;
4398     if (is_zero(n) || (!is_integral(n) && !is_integer(n)) || n.type==_CPLX)
4399       return gentypeerr(contextptr);
4400     return _sort(idivis(abs(n,contextptr),contextptr),contextptr);
4401   }
4402   static const char _idivis_s []="idivis";
4403   static define_unary_function_eval (__idivis,&_idivis,_idivis_s);
4404   define_unary_function_ptr5( at_idivis ,alias_at_idivis,&__idivis,0,true);
4405 
_divis(const gen & args,GIAC_CONTEXT)4406   gen _divis(const gen & args,GIAC_CONTEXT){
4407     if ( args.type==_STRNG && args.subtype==-1) return  args;
4408     if (args.type==_VECT)
4409       return apply(args,_divis,contextptr);
4410     return divis(factors(args,vx_var,contextptr),contextptr);
4411   }
4412   static const char _divis_s []="divis";
4413   static define_unary_function_eval (__divis,&_divis,_divis_s);
4414   define_unary_function_ptr5( at_divis ,alias_at_divis,&__divis,0,true);
4415 
4416   /*
4417   gen ichinreme(const vecteur & a,const vecteur & b){
4418     vecteur r(2);
4419     gen p=a[1],q=b[1],u,v,d;
4420     egcd(p,q,u,v,d);
4421     if (d!=1)  return gensizeerr(contextptr);
4422     r[0]=(u*p*b[0]+v*q*a[0]%p*q);
4423     r[1]=p*q;
4424     return(r);
4425   }
4426   gen _ichinreme(const gen & args){
4427   if ( args){
4428     if ( (args.type!=_VECT) || (args._VECTptr->size()!=4) )
4429       return gensizeerr(contextptr);
4430     vecteur a(2).type==_STRNG && args.subtype==-1{
4431     if ( (args.type!=_VECT) || (args._VECTptr->size()!=4) )
4432       return gensizeerr(contextptr);
4433     vecteur a(2))) return  args){
4434     if ( (args.type!=_VECT) || (args._VECTptr->size()!=4) )
4435       return gensizeerr(contextptr);
4436     vecteur a(2);
4437     if ( (args.type!=_VECT) || (args._VECTptr->size()!=4) )
4438       return gensizeerr(contextptr);
4439     vecteur a(2),b(2);
4440     a[0]=args[0];
4441     a[1]=args[1];
4442     b[0]=args[2];
4443     b[1]=args[3];
4444     //gen a=args[0],p=args[1], b=args[2],q=args[3];
4445     return ichinreme(a,b);
4446   }
4447   static const char _ichinreme_s []="ichinreme";
4448   static define_unary_function_eval (__ichinreme,&_ichinreme,_ichinreme_s);
4449   define_unary_function_ptr5( at_ichinreme ,alias_at_ichinreme,&__ichinreme,0,true);
4450   */
4451 
euler(const gen & e,GIAC_CONTEXT)4452   gen euler(const gen & e,GIAC_CONTEXT){
4453     if (e==0)
4454       return e;
4455     vecteur v(ifactors(e,contextptr));
4456     if (!v.empty() && is_undef(v.front())) return v.front();
4457     const_iterateur it=v.begin(),itend=v.end();
4458     for (gen res(plus_one);;){
4459       if (it==itend)
4460 	return res;
4461       gen p=*it;
4462       ++it;
4463       int n=it->val;
4464       res = res * (p-plus_one)*pow(p,n-1);
4465       ++it;
4466     }
4467   }
4468   static const char _euler_s []="euler";
_euler(const gen & args,GIAC_CONTEXT)4469   gen _euler(const gen & args,GIAC_CONTEXT){
4470     if ( args.type==_STRNG && args.subtype==-1) return  args;
4471     if (args.type==_VECT)
4472       return apply(args,_euler,contextptr);
4473     if ( is_integer(args) && is_positive(args,contextptr))
4474       return euler(args,contextptr);
4475     return gentypeerr(contextptr);
4476   }
4477   static define_unary_function_eval (__euler,&_euler,_euler_s);
4478   define_unary_function_ptr5( at_euler ,alias_at_euler,&__euler,0,true);
4479 
pa2b2(const gen & p,GIAC_CONTEXT)4480   gen pa2b2(const gen & p,GIAC_CONTEXT){
4481     if (p==2)
4482       return makevecteur(1,1);
4483     if (!is_integer(p) || (p%4)!=1 || is_greater(1,p,contextptr)) return gensizeerr(contextptr);// car p!=1 mod 4
4484     gen q=(p-1)/4;
4485     gen a=2;
4486     gen ra;
4487     ra=powmod(a,q,p);
4488     //on cherche ra^2=-1 mod p avec ra!=1 et ra !=p-1
4489     while ((a!=p-1) && ((ra==1)|| (ra==p-1))){
4490       a=a+1;
4491       ra=powmod(a,q,p);
4492     }
4493     if ((ra==1)||(ra==p-1))  return gensizeerr(contextptr);//car p n'est pas premier
4494     gen ux=1,uy=ra,vx=0,vy=p,wx,wy;
4495     gen m=1;
4496     while(m!=0){
4497       if (is_positive(vx*vx+vy*vy-ux*ux+uy*uy,0)){
4498 	//on echange u et v
4499 	wx=vx;
4500 	wy=vy;
4501 	vx=ux;
4502 	vy=uy;
4503 	ux=wx;
4504 	uy=wy;
4505       }
4506       gen alpha=inv(2,contextptr)-(ux*vx+uy*vy)*inv(vx*vx+vy*vy,contextptr);
4507       //m=partie entiere de alpha (-v.v/2<(u+mv).v<=v.v/2)
4508       m=_floor(alpha,contextptr);
4509       ux=ux+m*vx;
4510       uy=uy+m*vy;
4511     }
4512     vecteur v(2);
4513     //v repond a la question
4514     v[0]=abs(vx,contextptr); // ok
4515     v[1]=abs(vy,contextptr); // ok
4516     if (vx*vx+vy*vy!=p)
4517       return gensizeerr(contextptr);
4518     return v;
4519   }
_pa2b2(const gen & args,GIAC_CONTEXT)4520   gen _pa2b2(const gen & args,GIAC_CONTEXT){
4521     if ( args.type==_STRNG && args.subtype==-1) return  args;
4522     if (!is_integer(args))
4523       return gensizeerr(contextptr);
4524     gen n=args;
4525     return pa2b2(n,contextptr);
4526   }
4527   static const char _pa2b2_s []="pa2b2";
4528   static define_unary_function_eval (__pa2b2,&_pa2b2,_pa2b2_s);
4529   define_unary_function_ptr5( at_pa2b2 ,alias_at_pa2b2,&__pa2b2,0,true);
4530 
ipropfrac(const gen & a,const gen & b,GIAC_CONTEXT)4531   static gen ipropfrac(const gen & a,const gen & b,GIAC_CONTEXT){
4532     if (!is_integer(a) || !is_integer(b))
4533       return gensizeerr(contextptr);
4534     gen r=a%b;
4535     gen q=(a-r)/b;
4536     gen d=gcd(r,b);
4537     r=r/d;
4538     gen b1=b/d;
4539     if (r==0)
4540       return q;
4541     gen v;
4542     v=symbolic(at_division,gen(makevecteur(r,b1),_SEQ__VECT));
4543     gen w;
4544     w=symbolic(at_plus,gen(makevecteur(q,v),_SEQ__VECT));
4545     if (calc_mode(contextptr)==1)
4546       return symbolic(at_quote,w);
4547     return w;
4548   }
_propfrac(const gen & arg,GIAC_CONTEXT)4549   gen _propfrac(const gen & arg,GIAC_CONTEXT){
4550     if ( arg.type==_STRNG && arg.subtype==-1) return  arg;
4551     gen args(arg);
4552     vecteur v;
4553     if (arg.type==_VECT && arg._VECTptr->size()==2){
4554       v=vecteur(1,arg._VECTptr->back());
4555       args=arg._VECTptr->front();
4556       lvar(args,v);
4557     }
4558     else
4559       v=lvar(arg);
4560     gen g=e2r(args,v,contextptr);
4561     gen a,b;
4562     fxnd(g,a,b);
4563     if (v.empty())
4564       return ipropfrac(a,b,contextptr);
4565     else {
4566       gen d=r2e(b,v,contextptr);
4567       g=_quorem(makesequence(r2e(a,v,contextptr),d,v.front()),contextptr);
4568       if (is_undef(g)) return g;
4569       vecteur &v=*g._VECTptr;
4570       return v[0]+rdiv(v[1],d,contextptr);
4571     }
4572   }
4573   static const char _propfrac_s []="propfrac";
4574   static define_unary_function_eval (__propfrac,&_propfrac,_propfrac_s);
4575   define_unary_function_ptr5( at_propfrac ,alias_at_propfrac,&__propfrac,0,true);
4576 
step_egcd(int a,int b,GIAC_CONTEXT)4577   void step_egcd(int a,int b,GIAC_CONTEXT){
4578     gprintf("===============",vecteur(0),1,contextptr);
4579     gprintf("Extended Euclide algorithm for a=%gen and b=%gen",makevecteur(a,b),1,contextptr);
4580     gprintf("L%gen: 1*a+0*b=%gen",makevecteur(1,a),1,contextptr);
4581     gprintf("L%gen: 0*a+1*b=%gen",makevecteur(2,b),1,contextptr);
4582     int i=3;
4583     int u0=1,v0=0,u1=0,v1=1,u2,v2;
4584     for (;b;++i){
4585       int q=a/b;
4586       u2=u0-q*u1;
4587       v2=v0-q*v1;
4588       int r=a-q*b;
4589       gprintf("iquo(%gen,%gen)=%gen",makevecteur(a,b,q),1,contextptr);
4590       gprintf("L%gen=L%gen-%gen*L%gen: %gen*a+%gen*b=%gen",makevecteur(i,i-2,q,i-1,u2,v2,r),1,contextptr);
4591       u0=u1;
4592       u1=u2;
4593       v0=v1;
4594       v1=v2;
4595       a=b;
4596       b=r;
4597     }
4598     gprintf("Bezout identity %gen*a+%gen*b=%gen",makevecteur(u0,v0,a),1,contextptr);
4599   }
4600 
iabcuv(const gen & a,const gen & b,const gen & c,GIAC_CONTEXT)4601   gen iabcuv(const gen & a,const gen & b,const gen & c,GIAC_CONTEXT){
4602     gen d=gcd(a,b);
4603     if (c%d!=0)  return gensizeerr(gettext("No solution in ring"));
4604     gen a1=a/d,b1=b/d,c1=c/d;
4605     gen u,v,w;
4606     if (a1.type==_INT_ && b1.type==_INT_ && step_infolevel(contextptr))
4607       step_egcd(a1.val,b1.val,contextptr);
4608     egcd(a1,b1,u,v,w);
4609     vecteur r(2);
4610     r[0]=smod(u*c1,b);
4611     r[1]=iquo(c-r[0]*a,b);
4612     return r;
4613   }
_iabcuv(const gen & args,GIAC_CONTEXT)4614   gen _iabcuv(const gen & args,GIAC_CONTEXT){
4615     if ( args.type==_STRNG && args.subtype==-1) return  args;
4616     if ( (args.type!=_VECT) || (args._VECTptr->size()!=3) )
4617       return gensizeerr(contextptr);
4618     gen a=args[0],b=args[1],c=args[2];
4619     return iabcuv(a,b,c,contextptr);
4620   }
4621   static const char _iabcuv_s []="iabcuv";
4622   static define_unary_function_eval (__iabcuv,&_iabcuv,_iabcuv_s);
4623   define_unary_function_ptr5( at_iabcuv ,alias_at_iabcuv,&__iabcuv,0,true);
4624 
abcuv(const gen & a,const gen & b,const gen & c,const gen & x,GIAC_CONTEXT)4625   gen abcuv(const gen & a,const gen & b,const gen & c,const gen & x,GIAC_CONTEXT){
4626     gen g=_egcd(makesequence(a,b,x),contextptr);
4627     if (is_undef(g)) return g;
4628     vecteur & v=*g._VECTptr;
4629     gen h=_quorem(makesequence(c,v[2],x),contextptr);
4630     if (is_undef(h)) return h;
4631     vecteur & w=*h._VECTptr;
4632     if (!is_zero(w[1]))
4633       return gensizeerr(gettext("No solution in ring"));
4634     gen U=v[0]*w[0],V=v[1]*w[0];
4635     if (_degree(makesequence(c,x),contextptr).val<_degree(makesequence(a,x),contextptr).val+_degree(makesequence(b,x),contextptr).val ){
4636       U=_rem(makesequence(U,b,x),contextptr);
4637       V=_rem(makesequence(V,a,x),contextptr);
4638     }
4639     return makevecteur(U,V);
4640   }
_abcuv(const gen & args,GIAC_CONTEXT)4641   gen _abcuv(const gen & args,GIAC_CONTEXT){
4642     if ( args.type==_STRNG && args.subtype==-1) return  args;
4643     if ( (args.type!=_VECT) || (args._VECTptr->size()<3) )
4644       return gensizeerr(contextptr);
4645     vecteur & v =*args._VECTptr;
4646     if (v.size()>3)
4647       return abcuv(v[0],v[1],v[2],v[3],contextptr);
4648     return abcuv(v[0],v[1],v[2],vx_var,contextptr);
4649   }
4650   static const char _abcuv_s []="abcuv";
4651   static define_unary_function_eval (__abcuv,&_abcuv,_abcuv_s);
4652   define_unary_function_ptr5( at_abcuv ,alias_at_abcuv,&__abcuv,0,true);
4653 
simp2(const gen & a,const gen & b,GIAC_CONTEXT)4654   gen simp2(const gen & a,const gen & b,GIAC_CONTEXT){
4655     vecteur r(2);
4656     gen d=gcd(a,b);
4657     r[0]=normal(a/d,contextptr);
4658     r[1]=normal(b/d,contextptr);
4659     return r;
4660   }
_simp2(const gen & args,GIAC_CONTEXT)4661   gen _simp2(const gen & args,GIAC_CONTEXT){
4662     if ( args.type==_STRNG && args.subtype==-1) return  args;
4663     if ( (args.type!=_VECT) || (args._VECTptr->size()!=2) )
4664       return gensizeerr(contextptr);
4665     gen a=args[0],b=args[1];
4666     if ( (a.type==_VECT) || (b.type==_VECT) )
4667       return gensizeerr(contextptr);
4668     return simp2(a,b,contextptr);
4669   }
4670   static const char _simp2_s []="simp2";
4671   static define_unary_function_eval (__simp2,&_simp2,_simp2_s);
4672   define_unary_function_ptr5( at_simp2 ,alias_at_simp2,&__simp2,0,true);
4673 
fxnd(const gen & a)4674   gen fxnd(const gen & a){
4675     vecteur v(lvar(a));
4676     gen g=e2r(a,v,context0); // ok
4677     gen n,d;
4678     fxnd(g,n,d);
4679     return makevecteur(r2e(n,v,context0),r2e(d,v,context0)); // ok
4680   }
_fxnd(const gen & args,GIAC_CONTEXT)4681   gen _fxnd(const gen & args,GIAC_CONTEXT){
4682     if ( args.type==_STRNG && args.subtype==-1) return  args;
4683     if (args.type==_VECT)
4684       return apply(args,fxnd);
4685     return fxnd(args);
4686   }
4687   static const char _fxnd_s []="fxnd";
4688   static define_unary_function_eval (__fxnd,&_fxnd,_fxnd_s);
4689   define_unary_function_ptr5( at_fxnd ,alias_at_fxnd,&__fxnd,0,true);
4690 
4691 #ifndef NO_NAMESPACE_GIAC
4692 } // namespace giac
4693 #endif // ndef NO_NAMESPACE_GIAC
4694 
4695