Line data Source code
1 : /* Copyright (C) 2000 The PARI group.
2 :
3 : This file is part of the PARI/GP package.
4 :
5 : PARI/GP is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 2 of the License, or (at your option) any later
8 : version. It is distributed in the hope that it will be useful, but WITHOUT
9 : ANY WARRANTY WHATSOEVER.
10 :
11 : Check the License for details. You should have received a copy of it, along
12 : with the package; see the file 'COPYING'. If not, write to the Free Software
13 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
14 :
15 : /********************************************************************/
16 : /** **/
17 : /** GENERIC OPERATIONS **/
18 : /** (third part) **/
19 : /** **/
20 : /********************************************************************/
21 : #include "pari.h"
22 : #include "paripriv.h"
23 :
24 : /********************************************************************/
25 : /** **/
26 : /** PRINCIPAL VARIABLE NUMBER **/
27 : /** **/
28 : /********************************************************************/
29 : static void
30 26628 : recvar(hashtable *h, GEN x)
31 : {
32 26628 : long i = 1, lx = lg(x);
33 : void *v;
34 26628 : switch(typ(x))
35 : {
36 6090 : case t_POL: case t_SER:
37 6090 : v = (void*)varn(x);
38 6090 : if (!hash_search(h, v)) hash_insert(h, v, NULL);
39 6090 : i = 2; break;
40 1050 : case t_POLMOD: case t_RFRAC:
41 1050 : case t_VEC: case t_COL: case t_MAT: break;
42 14 : case t_LIST:
43 14 : x = list_data(x);
44 14 : lx = x? lg(x): 1; break;
45 19474 : default:
46 19474 : return;
47 : }
48 32718 : for (; i < lx; i++) recvar(h, gel(x,i));
49 : }
50 :
51 : GEN
52 1064 : variables_vecsmall(GEN x)
53 : {
54 1064 : hashtable *h = hash_create_ulong(100, 1);
55 1064 : recvar(h, x);
56 1064 : return vars_sort_inplace(hash_keys(h));
57 : }
58 :
59 : GEN
60 42 : variables_vec(GEN x)
61 42 : { return x? vars_to_RgXV(variables_vecsmall(x)): gpolvar(NULL); }
62 :
63 : long
64 130872540 : gvar(GEN x)
65 : {
66 : long i, v, w, lx;
67 130872540 : switch(typ(x))
68 : {
69 50884136 : case t_POL: case t_SER: return varn(x);
70 184627 : case t_POLMOD: return varn(gel(x,1));
71 14547208 : case t_RFRAC: return varn(gel(x,2));
72 3675816 : case t_VEC: case t_COL: case t_MAT:
73 3675816 : lx = lg(x); break;
74 14 : case t_LIST:
75 14 : x = list_data(x);
76 14 : lx = x? lg(x): 1; break;
77 61580739 : default:
78 61580739 : return NO_VARIABLE;
79 : }
80 3675830 : v = NO_VARIABLE;
81 32928004 : for (i=1; i < lx; i++) { w = gvar(gel(x,i)); if (varncmp(w,v) < 0) v = w; }
82 3675841 : return v;
83 : }
84 : /* T main polynomial in R[X], A auxiliary in R[X] (possibly degree 0).
85 : * Guess and return the main variable of R */
86 : static long
87 10493 : var2_aux(GEN T, GEN A)
88 : {
89 10493 : long a = gvar2(T);
90 10493 : long b = (typ(A) == t_POL && varn(A) == varn(T))? gvar2(A): gvar(A);
91 10493 : if (varncmp(a, b) > 0) a = b;
92 10493 : return a;
93 : }
94 : static long
95 7035 : var2_rfrac(GEN x) { return var2_aux(gel(x,2), gel(x,1)); }
96 : static long
97 3458 : var2_polmod(GEN x) { return var2_aux(gel(x,1), gel(x,2)); }
98 :
99 : /* main variable of x, with the convention that the "natural" main
100 : * variable of a POLMOD is mute, so we want the next one. */
101 : static long
102 57946 : gvar9(GEN x)
103 57946 : { return (typ(x) == t_POLMOD)? var2_polmod(x): gvar(x); }
104 :
105 : /* main variable of the ring over wich x is defined */
106 : long
107 20640473 : gvar2(GEN x)
108 : {
109 : long i, v, w;
110 20640473 : switch(typ(x))
111 : {
112 56 : case t_POLMOD:
113 56 : return var2_polmod(x);
114 18123 : case t_POL: case t_SER:
115 18123 : v = NO_VARIABLE;
116 75026 : for (i=2; i < lg(x); i++) {
117 56903 : w = gvar9(gel(x,i));
118 56903 : if (varncmp(w,v) < 0) v=w;
119 : }
120 18123 : return v;
121 7035 : case t_RFRAC:
122 7035 : return var2_rfrac(x);
123 49 : case t_VEC: case t_COL: case t_MAT:
124 49 : v = NO_VARIABLE;
125 147 : for (i=1; i < lg(x); i++) {
126 98 : w = gvar2(gel(x,i));
127 98 : if (varncmp(w,v)<0) v=w;
128 : }
129 49 : return v;
130 : }
131 20615210 : return NO_VARIABLE;
132 : }
133 :
134 : /*******************************************************************/
135 : /* */
136 : /* PRECISION OF SCALAR OBJECTS */
137 : /* */
138 : /*******************************************************************/
139 : static long
140 9527856 : prec0(long e) { return (e < 0)? nbits2prec(-e): LOWDEFAULTPREC; }
141 : static long
142 944559214 : precREAL(GEN x) { return signe(x) ? realprec(x): prec0(expo(x)); }
143 : /* x t_REAL, y an exact noncomplex type. Return precision(|x| + |y|) */
144 : static long
145 1321734 : precrealexact(GEN x, GEN y)
146 : {
147 1321734 : long lx, ey = gexpo(y), ex, e;
148 1321739 : if (ey == -(long)HIGHEXPOBIT) return precREAL(x);
149 618972 : ex = expo(x);
150 618972 : e = ey - ex;
151 618972 : if (!signe(x)) return prec0((e >= 0)? -e: ex);
152 618923 : lx = realprec(x);
153 618923 : return (e > 0)? lx + nbits2extraprec(e): lx;
154 : }
155 : static long
156 22903359 : precCOMPLEX(GEN z)
157 : { /* ~ precision(|x| + |y|) */
158 22903359 : GEN x = gel(z,1), y = gel(z,2);
159 : long e, ex, ey, lz, lx, ly;
160 22903359 : if (typ(x) != t_REAL) {
161 2240957 : if (typ(y) != t_REAL) return 0;
162 1309467 : return precrealexact(y, x);
163 : }
164 20662402 : if (typ(y) != t_REAL) return precrealexact(x, y);
165 : /* x, y are t_REALs, cf addrr_sign */
166 20650135 : ex = expo(x);
167 20650135 : ey = expo(y);
168 20650135 : e = ey - ex;
169 20650135 : if (!signe(x)) {
170 581743 : if (!signe(y)) return prec0( minss(ex,ey) );
171 581645 : if (e <= 0) return prec0(ex);
172 581567 : lz = nbits2prec(e);
173 581565 : ly = realprec(y); if (lz > ly) lz = ly;
174 581565 : return lz;
175 : }
176 20068392 : if (!signe(y)) {
177 75157 : if (e >= 0) return prec0(ey);
178 75150 : lz = nbits2prec(-e);
179 75149 : lx = realprec(x); if (lz > lx) lz = lx;
180 75149 : return lz;
181 : }
182 19993235 : if (e < 0) { swap(x, y); e = -e; }
183 19993235 : lx = realprec(x);
184 19993235 : ly = realprec(y);
185 19993235 : if (e) {
186 16996603 : long d = nbits2extraprec(e), l = ly-d;
187 16996586 : return (l > lx)? lx + d: ly;
188 : }
189 2996632 : return minss(lx, ly);
190 : }
191 : long
192 957126735 : precision(GEN z)
193 : {
194 957126735 : switch(typ(z))
195 : {
196 940126989 : case t_REAL: return precREAL(z);
197 16957257 : case t_COMPLEX: return precCOMPLEX(z);
198 : }
199 42489 : return 0;
200 : }
201 :
202 : long
203 14472809 : gprecision(GEN x)
204 : {
205 : long i, k, l;
206 :
207 14472809 : switch(typ(x))
208 : {
209 3729816 : case t_REAL: return precREAL(x);
210 5946104 : case t_COMPLEX: return precCOMPLEX(x);
211 896740 : case t_INT: case t_INTMOD: case t_FRAC: case t_FFELT:
212 : case t_PADIC: case t_QUAD: case t_POLMOD:
213 896740 : return 0;
214 :
215 602 : case t_POL: case t_SER:
216 602 : k = LONG_MAX;
217 2121 : for (i=lg(x)-1; i>1; i--)
218 : {
219 1519 : l = gprecision(gel(x,i));
220 1519 : if (l && l<k) k = l;
221 : }
222 602 : return (k==LONG_MAX)? 0: k;
223 3899593 : case t_VEC: case t_COL: case t_MAT:
224 3899593 : k = LONG_MAX;
225 14397794 : for (i=lg(x)-1; i>0; i--)
226 : {
227 10498138 : l = gprecision(gel(x,i));
228 10498201 : if (l && l<k) k = l;
229 : }
230 3899656 : return (k==LONG_MAX)? 0: k;
231 :
232 7 : case t_RFRAC:
233 : {
234 7 : k=gprecision(gel(x,1));
235 7 : l=gprecision(gel(x,2)); if (l && (!k || l<k)) k=l;
236 7 : return k;
237 : }
238 7 : case t_QFB:
239 7 : return gprecision(gel(x,4));
240 : }
241 48 : return 0;
242 : }
243 :
244 : static long
245 413 : vec_padicprec_relative(GEN x, long imin)
246 : {
247 : long s, t, i;
248 1288 : for (s=LONG_MAX, i=lg(x)-1; i>=imin; i--)
249 : {
250 875 : t = padicprec_relative(gel(x,i)); if (t<s) s = t;
251 : }
252 413 : return s;
253 : }
254 : /* RELATIVE padic precision. Only accept decent types: don't try to make sense
255 : * of everything like padicprec */
256 : long
257 2359 : padicprec_relative(GEN x)
258 : {
259 2359 : switch(typ(x))
260 : {
261 427 : case t_INT: case t_FRAC:
262 427 : return LONG_MAX;
263 1519 : case t_PADIC:
264 1519 : return signe(gel(x,4))? precp(x): 0;
265 238 : case t_POLMOD: case t_VEC: case t_COL: case t_MAT:
266 238 : return vec_padicprec_relative(x, 1);
267 175 : case t_POL: case t_SER:
268 175 : return vec_padicprec_relative(x, 2);
269 : }
270 0 : pari_err_TYPE("padicprec_relative",x);
271 : return 0; /* LCOV_EXCL_LINE */
272 : }
273 :
274 : static long
275 826 : vec_padicprec(GEN x, GEN p, long imin)
276 : {
277 : long s, t, i;
278 4760 : for (s=LONG_MAX, i=lg(x)-1; i>=imin; i--)
279 : {
280 3934 : t = padicprec(gel(x,i),p); if (t<s) s = t;
281 : }
282 826 : return s;
283 : }
284 : static long
285 14 : vec_serprec(GEN x, long v, long imin)
286 : {
287 : long s, t, i;
288 42 : for (s=LONG_MAX, i=lg(x)-1; i>=imin; i--)
289 : {
290 28 : t = serprec(gel(x,i),v); if (t<s) s = t;
291 : }
292 14 : return s;
293 : }
294 :
295 : /* ABSOLUTE padic precision */
296 : long
297 4172 : padicprec(GEN x, GEN p)
298 : {
299 4172 : if (typ(p) != t_INT) pari_err_TYPE("padicprec",p);
300 4165 : switch(typ(x))
301 : {
302 42 : case t_INT: case t_FRAC:
303 42 : return LONG_MAX;
304 :
305 7 : case t_INTMOD:
306 7 : return Z_pval(gel(x,1),p);
307 :
308 3290 : case t_PADIC:
309 3290 : if (!equalii(gel(x,2),p)) pari_err_MODULUS("padicprec", gel(x,2), p);
310 3283 : return precp(x)+valp(x);
311 :
312 14 : case t_POL: case t_SER:
313 14 : return vec_padicprec(x, p, 2);
314 812 : case t_COMPLEX: case t_QUAD: case t_POLMOD: case t_RFRAC:
315 : case t_VEC: case t_COL: case t_MAT:
316 812 : return vec_padicprec(x, p, 1);
317 : }
318 0 : pari_err_TYPE("padicprec",x);
319 : return 0; /* LCOV_EXCL_LINE */
320 : }
321 : GEN
322 105 : gppadicprec(GEN x, GEN p)
323 : {
324 105 : long v = padicprec(x,p);
325 91 : return v == LONG_MAX? mkoo(): stoi(v);
326 : }
327 :
328 : /* ABSOLUTE X-adic precision */
329 : long
330 70 : serprec(GEN x, long v)
331 : {
332 : long w;
333 70 : switch(typ(x))
334 : {
335 21 : case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FFELT:
336 : case t_COMPLEX: case t_PADIC: case t_QUAD: case t_QFB:
337 21 : return LONG_MAX;
338 :
339 7 : case t_POL:
340 7 : w = varn(x);
341 7 : if (varncmp(v,w) <= 0) return LONG_MAX;
342 7 : return vec_serprec(x, v, 2);
343 42 : case t_SER:
344 42 : w = varn(x);
345 42 : if (w == v)
346 : {
347 35 : long l = lg(x); /* Mod(0,2) + O(x) */
348 35 : if (l == 3 && !signe(x) && !isinexact(gel(x,2))) l--;
349 35 : return l - 2 + valser(x);
350 : }
351 7 : if (varncmp(v,w) < 0) return LONG_MAX;
352 7 : return vec_serprec(x, v, 2);
353 0 : case t_POLMOD: case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
354 0 : return vec_serprec(x, v, 1);
355 : }
356 0 : pari_err_TYPE("serprec",x);
357 : return 0; /* LCOV_EXCL_LINE */
358 : }
359 : GEN
360 42 : gpserprec(GEN x, long v)
361 : {
362 42 : long p = serprec(x,v);
363 42 : return p == LONG_MAX? mkoo(): stoi(p);
364 : }
365 :
366 : /* Degree of x (scalar, t_POL, t_RFRAC) wrt variable v if v >= 0,
367 : * wrt to main variable if v < 0. */
368 : long
369 107119 : poldegree(GEN x, long v)
370 : {
371 107119 : const long DEGREE0 = -LONG_MAX;
372 107119 : long tx = typ(x), lx,w,i,d;
373 :
374 107119 : if (is_scalar_t(tx)) return gequal0(x)? DEGREE0: 0;
375 106793 : switch(tx)
376 : {
377 106702 : case t_POL:
378 106702 : if (!signe(x)) return DEGREE0;
379 106695 : w = varn(x);
380 106695 : if (v < 0 || v == w) return degpol(x);
381 172 : if (varncmp(v, w) < 0) return 0;
382 144 : lx = lg(x); d = DEGREE0;
383 684 : for (i=2; i<lx; i++)
384 : {
385 540 : long e = poldegree(gel(x,i), v);
386 540 : if (e > d) d = e;
387 : }
388 144 : return d;
389 :
390 91 : case t_RFRAC:
391 : {
392 91 : GEN a = gel(x,1), b = gel(x,2);
393 91 : if (gequal0(a)) return DEGREE0;
394 84 : if (v < 0)
395 : {
396 84 : v = varn(b); d = -degpol(b);
397 84 : if (typ(a) == t_POL && varn(a) == v) d += degpol(a);
398 84 : return d;
399 : }
400 0 : return poldegree(a,v) - poldegree(b,v);
401 : }
402 : }
403 0 : pari_err_TYPE("degree",x);
404 : return 0; /* LCOV_EXCL_LINE */
405 : }
406 : GEN
407 31231 : gppoldegree(GEN x, long v)
408 : {
409 31231 : long d = poldegree(x,v);
410 31231 : return d == -LONG_MAX? mkmoo(): stoi(d);
411 : }
412 :
413 : /* assume v >= 0 and x is a POLYNOMIAL in v, return deg_v(x) */
414 : long
415 563002 : RgX_degree(GEN x, long v)
416 : {
417 563002 : long tx = typ(x), lx, w, i, d;
418 :
419 563002 : if (is_scalar_t(tx)) return gequal0(x)? -1: 0;
420 342474 : switch(tx)
421 : {
422 342474 : case t_POL:
423 342474 : if (!signe(x)) return -1;
424 342453 : w = varn(x);
425 342453 : if (v == w) return degpol(x);
426 126971 : if (varncmp(v, w) < 0) return 0;
427 126971 : lx = lg(x); d = -1;
428 544347 : for (i=2; i<lx; i++)
429 : {
430 417376 : long e = RgX_degree(gel(x,i), v);
431 417376 : if (e > d) d = e;
432 : }
433 126971 : return d;
434 :
435 0 : case t_RFRAC:
436 0 : w = varn(gel(x,2));
437 0 : if (varncmp(v, w) < 0) return 0;
438 0 : if (RgX_degree(gel(x,2),v)) pari_err_TYPE("RgX_degree", x);
439 0 : return RgX_degree(gel(x,1),v);
440 : }
441 0 : pari_err_TYPE("RgX_degree",x);
442 : return 0; /* LCOV_EXCL_LINE */
443 : }
444 :
445 : long
446 11223 : degree(GEN x)
447 : {
448 11223 : return poldegree(x,-1);
449 : }
450 :
451 : /* If v<0, leading coeff with respect to the main variable, otherwise wrt v. */
452 : GEN
453 1211 : pollead(GEN x, long v)
454 : {
455 1211 : long tx = typ(x), w;
456 : pari_sp av;
457 :
458 1211 : if (is_scalar_t(tx)) return gcopy(x);
459 1211 : w = varn(x);
460 1211 : switch(tx)
461 : {
462 1176 : case t_POL:
463 1176 : if (v < 0 || v == w)
464 : {
465 1141 : long l = lg(x);
466 1141 : return (l==2)? gen_0: gcopy(gel(x,l-1));
467 : }
468 35 : break;
469 :
470 35 : case t_SER:
471 35 : if (v < 0 || v == w) return signe(x)? gcopy(gel(x,2)): gen_0;
472 14 : if (varncmp(v, w) > 0) x = polcoef_i(x, valser(x), v);
473 14 : break;
474 :
475 0 : default:
476 0 : pari_err_TYPE("pollead",x);
477 : return NULL; /* LCOV_EXCL_LINE */
478 : }
479 49 : if (varncmp(v, w) < 0) return gcopy(x);
480 28 : av = avma; w = fetch_var_higher();
481 28 : x = gsubst(x, v, pol_x(w));
482 28 : x = pollead(x, w);
483 28 : delete_var(); return gerepileupto(av, x);
484 : }
485 :
486 : /* returns 1 if there's a real component in the structure, 0 otherwise */
487 : int
488 14357 : isinexactreal(GEN x)
489 : {
490 : long i;
491 14357 : switch(typ(x))
492 : {
493 1246 : case t_REAL: return 1;
494 2597 : case t_COMPLEX: return (typ(gel(x,1))==t_REAL || typ(gel(x,2))==t_REAL);
495 :
496 9926 : case t_INT: case t_INTMOD: case t_FRAC:
497 : case t_FFELT: case t_PADIC: case t_QUAD:
498 9926 : case t_QFB: return 0;
499 :
500 0 : case t_RFRAC: case t_POLMOD:
501 0 : return isinexactreal(gel(x,1)) || isinexactreal(gel(x,2));
502 :
503 588 : case t_POL: case t_SER:
504 5411 : for (i=lg(x)-1; i>1; i--)
505 4872 : if (isinexactreal(gel(x,i))) return 1;
506 539 : return 0;
507 :
508 0 : case t_VEC: case t_COL: case t_MAT:
509 0 : for (i=lg(x)-1; i>0; i--)
510 0 : if (isinexactreal(gel(x,i))) return 1;
511 0 : return 0;
512 0 : default: return 0;
513 : }
514 : }
515 : /* Check if x is approximately real with precision e */
516 : int
517 1867907 : isrealappr(GEN x, long e)
518 : {
519 : long i;
520 1867907 : switch(typ(x))
521 : {
522 696704 : case t_INT: case t_REAL: case t_FRAC:
523 696704 : return 1;
524 1171205 : case t_COMPLEX:
525 1171205 : return (gexpo(gel(x,2)) < e);
526 :
527 0 : case t_POL: case t_SER:
528 0 : for (i=lg(x)-1; i>1; i--)
529 0 : if (! isrealappr(gel(x,i),e)) return 0;
530 0 : return 1;
531 :
532 0 : case t_RFRAC: case t_POLMOD:
533 0 : return isrealappr(gel(x,1),e) && isrealappr(gel(x,2),e);
534 :
535 0 : case t_VEC: case t_COL: case t_MAT:
536 0 : for (i=lg(x)-1; i>0; i--)
537 0 : if (! isrealappr(gel(x,i),e)) return 0;
538 0 : return 1;
539 0 : default: pari_err_TYPE("isrealappr",x); return 0;
540 : }
541 : }
542 :
543 : /* returns 1 if there's an inexact component in the structure, and
544 : * 0 otherwise. */
545 : int
546 141362991 : isinexact(GEN x)
547 : {
548 : long lx, i;
549 :
550 141362991 : switch(typ(x))
551 : {
552 583124 : case t_REAL: case t_PADIC: case t_SER:
553 583124 : return 1;
554 95782096 : case t_INT: case t_INTMOD: case t_FFELT: case t_FRAC:
555 : case t_QFB:
556 95782096 : return 0;
557 2411652 : case t_COMPLEX: case t_QUAD: case t_RFRAC: case t_POLMOD:
558 2411652 : return isinexact(gel(x,1)) || isinexact(gel(x,2));
559 42567279 : case t_POL:
560 135504545 : for (i=lg(x)-1; i>1; i--)
561 93107419 : if (isinexact(gel(x,i))) return 1;
562 42397126 : return 0;
563 18841 : case t_VEC: case t_COL: case t_MAT:
564 22999 : for (i=lg(x)-1; i>0; i--)
565 22488 : if (isinexact(gel(x,i))) return 1;
566 511 : return 0;
567 0 : case t_LIST:
568 0 : x = list_data(x); lx = x? lg(x): 1;
569 0 : for (i=1; i<lx; i++)
570 0 : if (isinexact(gel(x,i))) return 1;
571 0 : return 0;
572 : }
573 0 : return 0;
574 : }
575 :
576 : int
577 0 : isrationalzeroscalar(GEN g)
578 : {
579 0 : switch (typ(g))
580 : {
581 0 : case t_INT: return !signe(g);
582 0 : case t_COMPLEX: return isintzero(gel(g,1)) && isintzero(gel(g,2));
583 0 : case t_QUAD: return isintzero(gel(g,2)) && isintzero(gel(g,3));
584 : }
585 0 : return 0;
586 : }
587 :
588 : int
589 0 : iscomplex(GEN x)
590 : {
591 0 : switch(typ(x))
592 : {
593 0 : case t_INT: case t_REAL: case t_FRAC:
594 0 : return 0;
595 0 : case t_COMPLEX:
596 0 : return !gequal0(gel(x,2));
597 0 : case t_QUAD:
598 0 : return signe(gmael(x,1,2)) > 0;
599 : }
600 0 : pari_err_TYPE("iscomplex",x);
601 : return 0; /* LCOV_EXCL_LINE */
602 : }
603 :
604 : /*******************************************************************/
605 : /* */
606 : /* GENERIC REMAINDER */
607 : /* */
608 : /*******************************************************************/
609 : static int
610 1099 : is_realquad(GEN x) { GEN Q = gel(x,1); return signe(gel(Q,2)) < 0; }
611 : static int
612 178167 : is_realext(GEN x)
613 178167 : { long t = typ(x);
614 178167 : return (t == t_QUAD)? is_realquad(x): is_real_t(t);
615 : }
616 : /* euclidean quotient for scalars of admissible types */
617 : static GEN
618 875 : _quot(GEN x, GEN y)
619 : {
620 875 : GEN q = gdiv(x,y), f = gfloor(q);
621 637 : if (gsigne(y) < 0 && !gequal(f,q)) f = addiu(f, 1);
622 637 : return f;
623 : }
624 : /* y t_REAL, x \ y */
625 : static GEN
626 70 : _quotsr(long x, GEN y)
627 : {
628 : GEN q, f;
629 70 : if (!x) return gen_0;
630 70 : q = divsr(x,y); f = floorr(q);
631 70 : if (signe(y) < 0 && signe(subir(f,q))) f = addiu(f, 1);
632 70 : return f;
633 : }
634 : /* x t_REAL, x \ y */
635 : static GEN
636 28 : _quotrs(GEN x, long y)
637 : {
638 28 : GEN q = divrs(x,y), f = floorr(q);
639 28 : if (y < 0 && signe(subir(f,q))) f = addiu(f, 1);
640 28 : return f;
641 : }
642 : static GEN
643 7 : _quotri(GEN x, GEN y)
644 : {
645 7 : GEN q = divri(x,y), f = floorr(q);
646 7 : if (signe(y) < 0 && signe(subir(f,q))) f = addiu(f, 1);
647 7 : return f;
648 : }
649 : static GEN
650 70 : _quotsq(long x, GEN y)
651 : {
652 70 : GEN f = gfloor(gdivsg(x,y));
653 70 : if (gsigne(y) < 0) f = gaddgs(f, 1);
654 70 : return f;
655 : }
656 : static GEN
657 28 : _quotqs(GEN x, long y)
658 : {
659 28 : GEN f = gfloor(gdivgs(x,y));
660 28 : if (y < 0) f = addiu(f, 1);
661 28 : return f;
662 : }
663 :
664 : /* y t_FRAC, x \ y */
665 : static GEN
666 35 : _quotsf(long x, GEN y)
667 35 : { return truedivii(mulis(gel(y,2),x), gel(y,1)); }
668 : /* x t_FRAC, x \ y */
669 : static GEN
670 301 : _quotfs(GEN x, long y)
671 301 : { return truedivii(gel(x,1),mulis(gel(x,2),y)); }
672 : /* x t_FRAC, y t_INT, x \ y */
673 : static GEN
674 7 : _quotfi(GEN x, GEN y)
675 7 : { return truedivii(gel(x,1),mulii(gel(x,2),y)); }
676 :
677 : static GEN
678 777 : quot(GEN x, GEN y)
679 777 : { pari_sp av = avma; return gerepileupto(av, _quot(x, y)); }
680 : static GEN
681 14 : quotrs(GEN x, long y)
682 14 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotrs(x,y)); }
683 : static GEN
684 301 : quotfs(GEN x, long s)
685 301 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotfs(x,s)); }
686 : static GEN
687 35 : quotsr(long x, GEN y)
688 35 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotsr(x, y)); }
689 : static GEN
690 35 : quotsf(long x, GEN y)
691 35 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotsf(x, y)); }
692 : static GEN
693 35 : quotsq(long x, GEN y)
694 35 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotsq(x, y)); }
695 : static GEN
696 14 : quotqs(GEN x, long y)
697 14 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotqs(x, y)); }
698 : static GEN
699 7 : quotfi(GEN x, GEN y)
700 7 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotfi(x, y)); }
701 : static GEN
702 7 : quotri(GEN x, GEN y)
703 7 : { pari_sp av = avma; return gerepileuptoleaf(av, _quotri(x, y)); }
704 :
705 : static GEN
706 14 : modrs(GEN x, long y)
707 : {
708 14 : pari_sp av = avma;
709 14 : GEN q = _quotrs(x,y);
710 14 : if (!signe(q)) { set_avma(av); return rcopy(x); }
711 7 : return gerepileuptoleaf(av, subri(x, mulis(q,y)));
712 : }
713 : static GEN
714 35 : modsr(long x, GEN y)
715 : {
716 35 : pari_sp av = avma;
717 35 : GEN q = _quotsr(x,y);
718 35 : if (!signe(q)) return gc_stoi(av, x);
719 7 : return gerepileuptoleaf(av, subsr(x, mulir(q,y)));
720 : }
721 : static GEN
722 35 : modsf(long x, GEN y)
723 : {
724 35 : pari_sp av = avma;
725 35 : return gerepileupto(av, Qdivii(modii(mulis(gel(y,2),x), gel(y,1)), gel(y,2)));
726 : }
727 :
728 : /* assume y a t_REAL, x a t_INT, t_FRAC or t_REAL.
729 : * Return x mod y or NULL if accuracy error */
730 : GEN
731 0 : modRr_safe(GEN x, GEN y)
732 : {
733 : GEN q, f;
734 : long e;
735 0 : if (isintzero(x)) return gen_0;
736 0 : q = gdiv(x,y); /* t_REAL */
737 :
738 0 : e = expo(q);
739 0 : if (e >= 0 && nbits2prec(e+1) > realprec(q)) return NULL;
740 0 : f = floorr(q);
741 0 : if (signe(y) < 0 && signe(subri(q,f))) f = addiu(f, 1);
742 0 : return signe(f)? gsub(x, mulir(f,y)): x;
743 : }
744 : GEN
745 4876826 : modRr_i(GEN x, GEN y, GEN iy)
746 : {
747 : GEN q, f;
748 : long e;
749 4876826 : if (isintzero(x)) return gen_0;
750 4876825 : q = gmul(x, iy); /* t_REAL */
751 :
752 4876823 : e = expo(q);
753 4876823 : if (e >= 0 && nbits2prec(e+1) > realprec(q)) return NULL;
754 4876822 : f = floorr(q);
755 4876698 : if (signe(y) < 0 && signe(subri(q,f))) f = addiu(f, 1);
756 4876798 : return signe(f)? gsub(x, mulir(f,y)): x;
757 : }
758 :
759 : GEN
760 46130860 : gmod(GEN x, GEN y)
761 : {
762 : pari_sp av;
763 : long ty, tx;
764 : GEN z;
765 :
766 46130860 : tx = typ(x); if (tx == t_INT && !is_bigint(x)) return gmodsg(itos(x),y);
767 1135613 : ty = typ(y); if (ty == t_INT && !is_bigint(y)) return gmodgs(x,itos(y));
768 1734533 : if (is_matvec_t(tx)) pari_APPLY_same(gmod(gel(x,i), y));
769 797213 : if (tx == t_POL || ty == t_POL) return grem(x,y);
770 511328 : if (!is_scalar_t(tx) || !is_scalar_t(ty)) pari_err_TYPE2("%",x,y);
771 511265 : switch(ty)
772 : {
773 510761 : case t_INT:
774 : switch(tx)
775 : {
776 507661 : case t_INT: return modii(x,y);
777 7 : case t_INTMOD: z=cgetg(3, t_INTMOD);
778 7 : gel(z,1) = gcdii(gel(x,1),y);
779 7 : gel(z,2) = modii(gel(x,2),gel(z,1)); return z;
780 491 : case t_FRAC: return Fp_div(gel(x,1),gel(x,2),y);
781 2567 : case t_PADIC: return padic_to_Fp(x, y);
782 14 : case t_QUAD: if (!is_realquad(x)) break;
783 : case t_REAL:
784 14 : av = avma; /* NB: conflicting semantic with lift(x * Mod(1,y)). */
785 14 : return gerepileupto(av, gsub(x, gmul(_quot(x,y),y)));
786 : }
787 21 : break;
788 126 : case t_QUAD:
789 126 : if (!is_realquad(y)) break;
790 : case t_REAL: case t_FRAC:
791 189 : if (!is_realext(x)) break;
792 84 : av = avma;
793 84 : return gerepileupto(av, gsub(x, gmul(_quot(x,y),y)));
794 : }
795 441 : pari_err_TYPE2("%",x,y);
796 : return NULL; /* LCOV_EXCL_LINE */
797 : }
798 :
799 : GEN
800 22028433 : gmodgs(GEN x, long y)
801 : {
802 : ulong u;
803 22028433 : long i, tx = typ(x);
804 : GEN z;
805 43822655 : if (is_matvec_t(tx)) pari_APPLY_same(gmodgs(gel(x,i), y));
806 19650135 : if (!y) pari_err_INV("gmodgs",gen_0);
807 19650135 : switch(tx)
808 : {
809 19566488 : case t_INT: return modis(x,y);
810 14 : case t_REAL: return modrs(x,y);
811 :
812 21 : case t_INTMOD: z=cgetg(3, t_INTMOD);
813 21 : u = (ulong)labs(y);
814 21 : i = ugcdiu(gel(x,1), u);
815 21 : gel(z,1) = utoi(i);
816 21 : gel(z,2) = modis(gel(x,2), i); return z;
817 :
818 82210 : case t_FRAC:
819 82210 : u = (ulong)labs(y);
820 82210 : return utoi( Fl_div(umodiu(gel(x,1), u),
821 82210 : umodiu(gel(x,2), u), u) );
822 28 : case t_QUAD:
823 : {
824 28 : pari_sp av = avma;
825 28 : if (!is_realquad(x)) break;
826 14 : return gerepileupto(av, gsub(x, gmulgs(_quotqs(x,y),y)));
827 : }
828 1318 : case t_PADIC: return padic_to_Fp(x, stoi(y));
829 14 : case t_POL: return scalarpol(Rg_get_0(x), varn(x));
830 14 : case t_POLMOD: return gmul(gen_0,x);
831 : }
832 42 : pari_err_TYPE2("%",x,stoi(y));
833 : return NULL; /* LCOV_EXCL_LINE */
834 : }
835 : GEN
836 44995247 : gmodsg(long x, GEN y)
837 : {
838 44995247 : switch(typ(y))
839 : {
840 44994890 : case t_INT: return modsi(x,y);
841 35 : case t_REAL: return modsr(x,y);
842 35 : case t_FRAC: return modsf(x,y);
843 63 : case t_QUAD:
844 : {
845 63 : pari_sp av = avma;
846 63 : if (!is_realquad(y)) break;
847 35 : return gerepileupto(av, gsubsg(x, gmul(_quotsq(x,y),y)));
848 : }
849 112 : case t_POL:
850 112 : if (!signe(y)) pari_err_INV("gmodsg",y);
851 112 : return degpol(y)? gmulsg(x, Rg_get_1(y)): Rg_get_0(y);
852 : }
853 140 : pari_err_TYPE2("%",stoi(x),y);
854 : return NULL; /* LCOV_EXCL_LINE */
855 : }
856 : /* divisibility: return 1 if y | x, 0 otherwise */
857 : int
858 15622 : gdvd(GEN x, GEN y)
859 : {
860 15622 : pari_sp av = avma;
861 15622 : return gc_bool(av, gequal0( gmod(x,y) ));
862 : }
863 :
864 : GEN
865 1052618 : gmodulss(long x, long y)
866 : {
867 1052618 : if (!y) pari_err_INV("%",gen_0);
868 1052611 : y = labs(y);
869 1052611 : retmkintmod(utoi(umodsu(x, y)), utoipos(y));
870 : }
871 : GEN
872 1357377 : gmodulsg(long x, GEN y)
873 : {
874 1357377 : switch(typ(y))
875 : {
876 1105957 : case t_INT:
877 1105957 : if (!is_bigint(y)) return gmodulss(x,itos(y));
878 62398 : retmkintmod(modsi(x,y), absi(y));
879 251414 : case t_POL:
880 251414 : if (!signe(y)) pari_err_INV("%", y);
881 251407 : retmkpolmod(degpol(y)? stoi(x): gen_0,RgX_copy(y));
882 : }
883 6 : pari_err_TYPE2("%",stoi(x),y);
884 : return NULL; /* LCOV_EXCL_LINE */
885 : }
886 : GEN
887 1920598 : gmodulo(GEN x,GEN y)
888 : {
889 1920598 : long tx = typ(x), vx, vy;
890 1920598 : if (tx == t_INT && !is_bigint(x)) return gmodulsg(itos(x), y);
891 1407026 : if (is_matvec_t(tx)) pari_APPLY_same(gmodulo(gel(x,i), y));
892 525488 : switch(typ(y))
893 : {
894 98215 : case t_INT:
895 98215 : if (!is_const_t(tx)) return gmul(x, gmodulsg(1,y));
896 98166 : if (tx == t_INTMOD) return gmod(x,y);
897 98159 : retmkintmod(Rg_to_Fp(x,y), absi(y));
898 427273 : case t_POL:
899 427273 : vx = gvar(x); vy = varn(y);
900 427273 : if (varncmp(vy, vx) > 0) return gmul(x, gmodulsg(1,y));
901 427182 : if (vx == vy && tx == t_POLMOD) return grem(x,y);
902 414302 : retmkpolmod(grem(x,y), RgX_copy(y));
903 : }
904 0 : pari_err_TYPE2("%",x,y);
905 : return NULL; /* LCOV_EXCL_LINE */
906 : }
907 :
908 : /*******************************************************************/
909 : /* */
910 : /* GENERIC EUCLIDEAN DIVISION */
911 : /* */
912 : /*******************************************************************/
913 : GEN
914 6204562 : gdivent(GEN x, GEN y)
915 : {
916 : long tx, ty;
917 6204562 : tx = typ(x); if (tx == t_INT && !is_bigint(x)) return gdiventsg(itos(x),y);
918 2188 : ty = typ(y); if (ty == t_INT && !is_bigint(y)) return gdiventgs(x,itos(y));
919 1960 : if (is_matvec_t(tx)) pari_APPLY_same(gdivent(gel(x,i), y));
920 1610 : if (tx == t_POL || ty == t_POL) return gdeuc(x,y);
921 1148 : switch(ty)
922 : {
923 112 : case t_INT:
924 : switch(tx)
925 : {
926 7 : case t_INT: return truedivii(x,y);
927 7 : case t_REAL: return quotri(x,y);
928 7 : case t_FRAC: return quotfi(x,y);
929 21 : case t_QUAD:
930 21 : if (!is_realquad(x)) break;
931 7 : return quot(x,y);
932 : }
933 84 : break;
934 252 : case t_QUAD:
935 252 : if (!is_realext(x) || !is_realquad(y)) break;
936 : case t_REAL: case t_FRAC:
937 252 : return quot(x,y);
938 : }
939 868 : pari_err_TYPE2("\\",x,y);
940 : return NULL; /* LCOV_EXCL_LINE */
941 : }
942 :
943 : GEN
944 298796 : gdiventgs(GEN x, long y)
945 : {
946 298796 : switch(typ(x))
947 : {
948 249257 : case t_INT: return truedivis(x,y);
949 14 : case t_REAL: return quotrs(x,y);
950 301 : case t_FRAC: return quotfs(x,y);
951 42 : case t_QUAD: if (!is_realquad(x)) break;
952 14 : return quotqs(x,y);
953 28 : case t_POL: return gdivgs(x,y);
954 288985 : case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gdiventgs(gel(x,i),y));
955 : }
956 168 : pari_err_TYPE2("\\",x,stoi(y));
957 : return NULL; /* LCOV_EXCL_LINE */
958 : }
959 : GEN
960 6202374 : gdiventsg(long x, GEN y)
961 : {
962 6202374 : switch(typ(y))
963 : {
964 6201919 : case t_INT: return truedivsi(x,y);
965 35 : case t_REAL: return quotsr(x,y);
966 35 : case t_FRAC: return quotsf(x,y);
967 91 : case t_QUAD: if (!is_realquad(y)) break;
968 35 : return quotsq(x,y);
969 70 : case t_POL:
970 70 : if (!signe(y)) pari_err_INV("gdiventsg",y);
971 70 : return degpol(y)? Rg_get_0(y): gdivsg(x,gel(y,2));
972 : }
973 280 : pari_err_TYPE2("\\",stoi(x),y);
974 : return NULL; /* LCOV_EXCL_LINE */
975 : }
976 :
977 : /* with remainder */
978 : static GEN
979 518 : quotrem(GEN x, GEN y, GEN *r)
980 : {
981 518 : GEN q = quot(x,y);
982 448 : pari_sp av = avma;
983 448 : *r = gerepileupto(av, gsub(x, gmul(q,y)));
984 448 : return q;
985 : }
986 :
987 : GEN
988 1064 : gdiventres(GEN x, GEN y)
989 : {
990 1064 : long tx = typ(x), ty = typ(y);
991 : GEN z;
992 :
993 1078 : if (is_matvec_t(tx)) pari_APPLY_same(gdiventres(gel(x,i), y));
994 1057 : z = cgetg(3,t_COL);
995 1057 : if (tx == t_POL || ty == t_POL)
996 : {
997 182 : gel(z,1) = poldivrem(x,y,(GEN*)(z+2));
998 168 : return z;
999 : }
1000 875 : switch(ty)
1001 : {
1002 252 : case t_INT:
1003 : switch(tx)
1004 : { /* equal to, but more efficient than next case */
1005 84 : case t_INT:
1006 84 : gel(z,1) = truedvmdii(x,y,(GEN*)(z+2));
1007 84 : return z;
1008 42 : case t_QUAD:
1009 42 : if (!is_realquad(x)) break;
1010 : case t_REAL: case t_FRAC:
1011 63 : gel(z,1) = quotrem(x,y,&gel(z,2));
1012 63 : return z;
1013 : }
1014 105 : break;
1015 154 : case t_QUAD:
1016 154 : if (!is_realext(x) || !is_realquad(y)) break;
1017 : case t_REAL: case t_FRAC:
1018 196 : gel(z,1) = quotrem(x,y,&gel(z,2));
1019 126 : return z;
1020 : }
1021 532 : pari_err_TYPE2("\\",x,y);
1022 : return NULL; /* LCOV_EXCL_LINE */
1023 : }
1024 :
1025 : GEN
1026 1057 : divrem(GEN x, GEN y, long v)
1027 : {
1028 1057 : pari_sp av = avma;
1029 : long vx, vy;
1030 : GEN q, r;
1031 1057 : if (v < 0 || typ(y) != t_POL || typ(x) != t_POL) return gdiventres(x,y);
1032 7 : vx = varn(x); if (vx != v) x = swap_vars(x,v);
1033 7 : vy = varn(y); if (vy != v) y = swap_vars(y,v);
1034 7 : q = RgX_divrem(x,y, &r);
1035 7 : if (v && (vx != v || vy != v))
1036 : {
1037 7 : GEN X = pol_x(v);
1038 7 : q = gsubst(q, v, X); /* poleval broken for t_RFRAC, subst is safe */
1039 7 : r = gsubst(r, v, X);
1040 : }
1041 7 : return gerepilecopy(av, mkcol2(q, r));
1042 : }
1043 :
1044 : GEN
1045 63649609 : diviiround(GEN x, GEN y)
1046 : {
1047 63649609 : pari_sp av1, av = avma;
1048 : GEN q,r;
1049 : int fl;
1050 :
1051 63649609 : q = dvmdii(x,y,&r); /* q = x/y rounded towards 0, sgn(r)=sgn(x) */
1052 63641214 : if (r==gen_0) return q;
1053 33836654 : av1 = avma;
1054 33836654 : fl = abscmpii(shifti(r,1),y);
1055 33840176 : set_avma(av1); cgiv(r);
1056 33850780 : if (fl >= 0) /* If 2*|r| >= |y| */
1057 : {
1058 18079544 : long sz = signe(x)*signe(y);
1059 18079544 : if (fl || sz > 0) q = gerepileuptoint(av, addis(q,sz));
1060 : }
1061 33852135 : return q;
1062 : }
1063 :
1064 : static GEN
1065 518 : _abs(GEN x)
1066 : {
1067 518 : if (typ(x) == t_QUAD) return (gsigne(x) < 0)? gneg(x): x;
1068 364 : return R_abs_shallow(x);
1069 : }
1070 :
1071 : /* If x and y are not both scalars, same as gdivent.
1072 : * Otherwise, compute the quotient x/y, rounded to the nearest integer
1073 : * (towards +oo in case of tie). */
1074 : GEN
1075 1467993 : gdivround(GEN x, GEN y)
1076 : {
1077 : pari_sp av;
1078 1467993 : long tx = typ(x), ty = typ(y);
1079 : GEN q, r;
1080 :
1081 1467993 : if (tx == t_INT && ty == t_INT) return diviiround(x,y);
1082 176969 : av = avma;
1083 176969 : if (is_realext(x) && is_realext(y))
1084 : { /* same as diviiround, less efficient */
1085 : pari_sp av1;
1086 : int fl;
1087 259 : q = quotrem(x,y,&r); av1 = avma;
1088 259 : fl = gcmp(gmul2n(_abs(r),1), _abs(y));
1089 259 : set_avma(av1); cgiv(r);
1090 259 : if (fl >= 0) /* If 2*|r| >= |y| */
1091 : {
1092 84 : long sz = gsigne(y);
1093 84 : if (fl || sz > 0) q = gerepileupto(av, gaddgs(q, sz));
1094 : }
1095 259 : return q;
1096 : }
1097 1589783 : if (is_matvec_t(tx)) pari_APPLY_same(gdivround(gel(x,i),y));
1098 931 : return gdivent(x,y);
1099 : }
1100 :
1101 : GEN
1102 0 : gdivmod(GEN x, GEN y, GEN *pr)
1103 : {
1104 0 : switch(typ(x))
1105 : {
1106 0 : case t_INT:
1107 0 : switch(typ(y))
1108 : {
1109 0 : case t_INT: return dvmdii(x,y,pr);
1110 0 : case t_POL: *pr=icopy(x); return gen_0;
1111 : }
1112 0 : break;
1113 0 : case t_POL: return poldivrem(x,y,pr);
1114 : }
1115 0 : pari_err_TYPE2("gdivmod",x,y);
1116 : return NULL;/*LCOV_EXCL_LINE*/
1117 : }
1118 :
1119 : /*******************************************************************/
1120 : /* */
1121 : /* SHIFT */
1122 : /* */
1123 : /*******************************************************************/
1124 :
1125 : /* Shift tronque si n<0 (multiplication tronquee par 2^n) */
1126 :
1127 : GEN
1128 47689922 : gshift(GEN x, long n)
1129 : {
1130 47689922 : switch(typ(x))
1131 : {
1132 38937490 : case t_INT: return shifti(x,n);
1133 8044381 : case t_REAL:return shiftr(x,n);
1134 2208356 : case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gshift(gel(x,i),n));
1135 : }
1136 142525 : return gmul2n(x,n);
1137 : }
1138 :
1139 : /*******************************************************************/
1140 : /* */
1141 : /* SUBSTITUTION DANS UN POLYNOME OU UNE SERIE */
1142 : /* */
1143 : /*******************************************************************/
1144 :
1145 : /* Convert t_SER --> t_POL, ignoring valser. INTERNAL ! */
1146 : GEN
1147 10124096 : ser2pol_i(GEN x, long lx)
1148 : {
1149 10124096 : long i = lx-1;
1150 : GEN y;
1151 13982713 : while (i > 1 && isrationalzero(gel(x,i))) i--;
1152 10124096 : if (!signe(x))
1153 : { /* danger */
1154 119 : if (i == 1) return zeropol(varn(x));
1155 119 : y = cgetg(3,t_POL); y[1] = x[1] & ~VALSERBITS;
1156 119 : gel(y,2) = gel(x,2); return y;
1157 : }
1158 10123977 : y = cgetg(i+1, t_POL); y[1] = x[1] & ~VALSERBITS;
1159 42854281 : for ( ; i > 1; i--) gel(y,i) = gel(x,i);
1160 10123977 : return y;
1161 : }
1162 :
1163 : GEN
1164 757181 : ser2pol_i_normalize(GEN x, long l, long *v)
1165 : {
1166 757181 : long i = 2, j = l-1, k;
1167 : GEN y;
1168 757216 : while (i < l && gequal0(gel(x,i))) i++;
1169 757181 : *v = i - 2; if (i == l) return zeropol(varn(x));
1170 1001515 : while (j > i && gequal0(gel(x,j))) j--;
1171 757167 : l = j - *v + 1;
1172 757167 : y = cgetg(l, t_POL); y[1] = x[1] & ~VALSERBITS;
1173 3913557 : k = l; while (k > 2) gel(y, --k) = gel(x,j--);
1174 757167 : return y;
1175 : }
1176 :
1177 : GEN
1178 45556 : ser_inv(GEN b)
1179 : {
1180 45556 : pari_sp av = avma;
1181 45556 : long e, l = lg(b);
1182 : GEN x, y;
1183 45556 : y = ser2pol_i_normalize(b, l, &e);
1184 45556 : if (e)
1185 : {
1186 0 : pari_warn(warner,"normalizing a series with 0 leading term");
1187 0 : l -= e; if (l <= 2) pari_err_INV("inv_ser", b);
1188 : }
1189 45556 : y = RgXn_inv_i(y, l-2);
1190 45549 : x = RgX_to_ser(y, l); setvalser(x, - valser(b) - e);
1191 45549 : return gerepilecopy(av, x);
1192 : }
1193 :
1194 : /* T t_POL in var v, mod out by T components of x which are t_POL/t_RFRAC in v.
1195 : * Recursively. Make sure that resulting polynomials of degree 0 in v are
1196 : * simplified (map K[X]_0 to K) */
1197 : static GEN
1198 196 : mod_r(GEN x, long v, GEN T)
1199 : {
1200 196 : long w, tx = typ(x);
1201 : GEN y;
1202 :
1203 196 : if (is_const_t(tx)) return x;
1204 175 : switch(tx)
1205 : {
1206 7 : case t_POLMOD:
1207 7 : w = varn(gel(x,1));
1208 7 : if (w == v) pari_err_PRIORITY("subst", gel(x,1), "=", v);
1209 7 : if (varncmp(v, w) < 0) return x;
1210 7 : return gmodulo(mod_r(gel(x,2),v,T), mod_r(gel(x,1),v,T));
1211 7 : case t_SER:
1212 7 : w = varn(x);
1213 7 : if (w == v) break; /* fail */
1214 7 : if (varncmp(v, w) < 0 || ser_isexactzero(x)) return x;
1215 21 : pari_APPLY_ser(mod_r(gel(x,i),v,T));
1216 133 : case t_POL:
1217 133 : w = varn(x);
1218 133 : if (w == v)
1219 : {
1220 105 : x = RgX_rem(x, T);
1221 105 : if (!degpol(x)) x = gel(x,2);
1222 105 : return x;
1223 : }
1224 28 : if (varncmp(v, w) < 0) return x;
1225 98 : pari_APPLY_pol(mod_r(gel(x,i),v,T));
1226 14 : case t_RFRAC:
1227 14 : x = gdiv(mod_r(gel(x,1),v,T), mod_r(gel(x,2),v,T));
1228 14 : if (typ(x) == t_POL && varn(x) == v && lg(x) == 3) x = gel(x,2);
1229 14 : return x;
1230 7 : case t_VEC: case t_COL: case t_MAT:
1231 21 : pari_APPLY_same(mod_r(gel(x,i),v,T));
1232 7 : case t_LIST:
1233 7 : y = mklist();
1234 7 : list_data(y) = list_data(x)? mod_r(list_data(x),v,T): NULL;
1235 7 : return y;
1236 : }
1237 0 : pari_err_TYPE("substpol",x);
1238 : return NULL;/*LCOV_EXCL_LINE*/
1239 : }
1240 : GEN
1241 8708 : gsubstpol(GEN x, GEN T, GEN y)
1242 : {
1243 8708 : pari_sp av = avma;
1244 : long v;
1245 : GEN z;
1246 8708 : if (typ(T) == t_POL && RgX_is_monomial(T) && gequal1(leading_coeff(T)))
1247 : { /* T = t^d */
1248 8687 : long d = degpol(T);
1249 8687 : v = varn(T); z = (d==1)? x: gdeflate(x, v, d);
1250 8673 : if (z) return gerepileupto(av, gsubst(z, v, y));
1251 : }
1252 49 : v = fetch_var(); T = simplify_shallow(T);
1253 49 : if (typ(T) == t_RFRAC)
1254 21 : z = gsub(gel(T,1), gmul(pol_x(v), gel(T,2)));
1255 : else
1256 28 : z = gsub(T, pol_x(v));
1257 49 : z = mod_r(x, gvar(T), z);
1258 49 : z = gsubst(z, v, y); (void)delete_var();
1259 49 : return gerepileupto(av, z);
1260 : }
1261 :
1262 : long
1263 1208787 : RgX_deflate_order(GEN x)
1264 : {
1265 1208787 : ulong d = 0, i, lx = (ulong)lg(x);
1266 2419672 : for (i=3; i<lx; i++)
1267 2076711 : if (!gequal0(gel(x,i))) { d = ugcd(d,i-2); if (d == 1) return 1; }
1268 342961 : return d? (long)d: 1;
1269 : }
1270 : long
1271 519798 : ZX_deflate_order(GEN x)
1272 : {
1273 519798 : ulong d = 0, i, lx = (ulong)lg(x);
1274 1620387 : for (i=3; i<lx; i++)
1275 1426620 : if (signe(gel(x,i))) { d = ugcd(d,i-2); if (d == 1) return 1; }
1276 193767 : return d? (long)d: 1;
1277 : }
1278 :
1279 : /* deflate (non-leaf) x recursively */
1280 : static GEN
1281 63 : vdeflate(GEN x, long v, long d)
1282 : {
1283 63 : long i = lontyp[typ(x)], lx;
1284 63 : GEN z = cgetg_copy(x, &lx);
1285 63 : if (i == 2) z[1] = x[1];
1286 154 : for (; i<lx; i++)
1287 : {
1288 133 : gel(z,i) = gdeflate(gel(x,i),v,d);
1289 133 : if (!z[i]) return NULL;
1290 : }
1291 21 : return z;
1292 : }
1293 :
1294 : /* don't return NULL if substitution fails (fallback won't be able to handle
1295 : * t_SER anyway), fail with a meaningful message */
1296 : static GEN
1297 5768 : serdeflate(GEN x, long v, long d)
1298 : {
1299 5768 : long V, dy, lx, vx = varn(x);
1300 : pari_sp av;
1301 : GEN y;
1302 5768 : if (varncmp(vx, v) < 0) return vdeflate(x,v,d);
1303 5761 : if (varncmp(vx, v) > 0) return gcopy(x);
1304 5761 : av = avma;
1305 5761 : V = valser(x);
1306 5761 : lx = lg(x);
1307 5761 : if (lx == 2) return zeroser(v, V / d);
1308 5761 : y = ser2pol_i(x, lx);
1309 5761 : dy = degpol(y);
1310 5761 : if (V % d != 0 || (dy > 0 && RgX_deflate_order(y) % d != 0))
1311 : {
1312 14 : const char *s = stack_sprintf("valuation(x) %% %ld", d);
1313 14 : pari_err_DOMAIN("gdeflate", s, "!=", gen_0,x);
1314 : }
1315 5747 : if (dy > 0) y = RgX_deflate(y, d);
1316 5747 : y = RgX_to_ser(y, 3 + (lx-3)/d);
1317 5747 : setvalser(y, V/d); return gerepilecopy(av, y);
1318 : }
1319 : static GEN
1320 8722 : poldeflate(GEN x, long v, long d)
1321 : {
1322 8722 : long vx = varn(x);
1323 : pari_sp av;
1324 8722 : if (varncmp(vx, v) < 0) return vdeflate(x,v,d);
1325 8694 : if (varncmp(vx, v) > 0 || degpol(x) <= 0) return gcopy(x);
1326 8659 : av = avma;
1327 : /* x nonconstant */
1328 8659 : if (RgX_deflate_order(x) % d != 0) return NULL;
1329 8631 : return gerepilecopy(av, RgX_deflate(x,d));
1330 : }
1331 : static GEN
1332 21 : listdeflate(GEN x, long v, long d)
1333 : {
1334 21 : GEN y = NULL, z = mklist();
1335 21 : if (list_data(x))
1336 : {
1337 14 : y = vdeflate(list_data(x),v,d);
1338 14 : if (!y) return NULL;
1339 : }
1340 14 : list_data(z) = y; return z;
1341 : }
1342 : /* return NULL if substitution fails */
1343 : GEN
1344 14553 : gdeflate(GEN x, long v, long d)
1345 : {
1346 14553 : if (d <= 0) pari_err_DOMAIN("gdeflate", "degree", "<=", gen_0,stoi(d));
1347 14553 : switch(typ(x))
1348 : {
1349 28 : case t_INT:
1350 : case t_REAL:
1351 : case t_INTMOD:
1352 : case t_FRAC:
1353 : case t_FFELT:
1354 : case t_COMPLEX:
1355 : case t_PADIC:
1356 28 : case t_QUAD: return gcopy(x);
1357 8722 : case t_POL: return poldeflate(x,v,d);
1358 5768 : case t_SER: return serdeflate(x,v,d);
1359 7 : case t_POLMOD:
1360 7 : if (varncmp(varn(gel(x,1)), v) >= 0) return gcopy(x);
1361 : /* fall through */
1362 : case t_RFRAC:
1363 : case t_VEC:
1364 : case t_COL:
1365 14 : case t_MAT: return vdeflate(x,v,d);
1366 21 : case t_LIST: return listdeflate(x,v,d);
1367 : }
1368 0 : pari_err_TYPE("gdeflate",x);
1369 : return NULL; /* LCOV_EXCL_LINE */
1370 : }
1371 :
1372 : /* set *m to the largest d such that x0 = A(X^d); return A */
1373 : GEN
1374 533245 : RgX_deflate_max(GEN x, long *m)
1375 : {
1376 533245 : *m = RgX_deflate_order(x);
1377 533244 : return RgX_deflate(x, *m);
1378 : }
1379 : GEN
1380 322232 : ZX_deflate_max(GEN x, long *m)
1381 : {
1382 322232 : *m = ZX_deflate_order(x);
1383 322232 : return RgX_deflate(x, *m);
1384 : }
1385 :
1386 : static int
1387 21161 : serequalXk(GEN x)
1388 : {
1389 21161 : long i, l = lg(x);
1390 21161 : if (l == 2 || !isint1(gel(x,2))) return 0;
1391 9786 : for (i = 3; i < l; i++)
1392 7833 : if (!isintzero(gel(x,i))) return 0;
1393 1953 : return 1;
1394 : }
1395 :
1396 : static GEN
1397 84 : gsubst_v(GEN e, long v, GEN x)
1398 245 : { pari_APPLY_same(gsubst(e, v, gel(x,i))); }
1399 :
1400 : static GEN
1401 14 : constmat(GEN z, long n)
1402 : {
1403 14 : GEN y = cgetg(n+1, t_MAT), c = const_col(n, gcopy(z));
1404 : long i;
1405 35 : for (i = 1; i <= n; i++) gel(y, i) = c;
1406 14 : return y;
1407 : }
1408 : static GEN
1409 56 : scalarmat2(GEN o, GEN z, long n)
1410 : {
1411 : GEN y;
1412 : long i;
1413 56 : if (n == 0) return cgetg(1, t_MAT);
1414 56 : if (n == 1) retmkmat(mkcol(gcopy(o)));
1415 35 : y = cgetg(n+1, t_MAT); z = gcopy(z); o = gcopy(o);
1416 105 : for (i = 1; i <= n; i++) { gel(y, i) = const_col(n, z); gcoeff(y,i,i) = o; }
1417 35 : return y;
1418 : }
1419 : /* x * y^0, n = dim(y) if t_MAT, else -1 */
1420 : static GEN
1421 704746 : subst_higher(GEN x, GEN y, long n)
1422 : {
1423 704746 : GEN o = Rg_get_1(y);
1424 704746 : if (o == gen_1) return n < 0? gcopy(x): scalarmat(x,n);
1425 98 : x = gmul(x,o); return n < 0? x: scalarmat2(x, Rg_get_0(y), n);
1426 : }
1427 :
1428 : /* x t_POLMOD, v strictly lower priority than var(x) */
1429 : static GEN
1430 553 : subst_polmod(GEN x, long v, GEN y)
1431 : {
1432 : long l, i;
1433 553 : GEN a = gsubst(gel(x,2),v,y), b = gsubst(gel(x,1),v,y), z;
1434 :
1435 553 : if (typ(b) != t_POL) pari_err_TYPE2("substitution",x,y);
1436 553 : if (typ(a) != t_POL || varncmp(varn(a), varn(b)) >= 0) return gmodulo(a, b);
1437 518 : l = lg(a); z = cgetg(l,t_POL); z[1] = a[1];
1438 4032 : for (i = 2; i < l; i++) gel(z,i) = gmodulo(gel(a,i),b);
1439 518 : return normalizepol_lg(z, l);
1440 : }
1441 : /* Trunc to n terms; x + O(t^(n + v(x))). FIXME: export ? */
1442 : static GEN
1443 70 : sertrunc(GEN x, long n)
1444 : {
1445 70 : long i, l = n + 2;
1446 : GEN y;
1447 70 : if (l >= lg(x)) return x;
1448 14 : if (n <= 0) return zeroser(varn(x), n + valser(x));
1449 14 : y = cgetg(l, t_SER);
1450 28 : for (i = 2; i < l; i++) gel(y,i) = gel(x,i);
1451 14 : y[1] = x[1]; return y;
1452 : }
1453 : /* FIXME: export ? */
1454 : static GEN
1455 1960 : sertrunc_copy(GEN x, long n)
1456 : {
1457 1960 : long i, l = minss(n + 2, lg(x));
1458 1960 : GEN y = cgetg(l, t_SER);
1459 13349 : for (i = 2; i < l; i++) gel(y,i) = gcopy(gel(x,i));
1460 1960 : y[1] = x[1]; return y;
1461 : }
1462 :
1463 : GEN
1464 2637357 : gsubst(GEN x, long v, GEN y)
1465 : {
1466 2637357 : long tx = typ(x), ty = typ(y), lx = lg(x), ly = lg(y);
1467 : long l, vx, vy, ex, ey, i, j, k, jb, matn;
1468 : pari_sp av, av2;
1469 : GEN X, t, z;
1470 :
1471 2637357 : switch(ty)
1472 : {
1473 84 : case t_VEC: case t_COL:
1474 84 : return gsubst_v(x, v, y);
1475 175 : case t_MAT:
1476 175 : if (ly==1) return cgetg(1,t_MAT);
1477 168 : if (ly == lgcols(y)) { matn = ly - 1; break; }
1478 : /* fall through */
1479 : case t_QFB:
1480 7 : pari_err_TYPE2("substitution",x,y);
1481 2637098 : default: matn = -1;
1482 : }
1483 2637259 : if (is_scalar_t(tx))
1484 : {
1485 357893 : if (tx == t_POLMOD && varncmp(v, varn(gel(x,1))) > 0)
1486 : {
1487 553 : av = avma;
1488 553 : return gerepileupto(av, subst_polmod(x, v, y));
1489 : }
1490 357340 : return subst_higher(x, y, matn);
1491 : }
1492 :
1493 2279366 : switch(tx)
1494 : {
1495 2038960 : case t_POL:
1496 2038960 : vx = varn(x);
1497 2038960 : if (varncmp(vx, v) > 0) return subst_higher(x, y, matn);
1498 2037735 : if (varncmp(vx, v) < 0)
1499 : {
1500 154078 : av = avma; z = cgetg(lx, t_POL); z[1] = x[1];
1501 154078 : if (lx == 2) return z;
1502 730862 : for (i = 2; i < lx; i++) gel(z,i) = gsubst(gel(x,i),v,y);
1503 153700 : z = normalizepol_lg(z, lx); lx = lg(z);
1504 153700 : if (lx == 2) { set_avma(av); return zeropol(vx); }
1505 153686 : if (lx == 3) return gerepileupto(av, gmul(pol_1(vx), gel(z,2)));
1506 132308 : return gerepileupto(av, poleval(z, pol_x(vx)));
1507 : }
1508 : /* v = vx */
1509 1883657 : if (lx == 2)
1510 : {
1511 27874 : GEN z = Rg_get_0(y);
1512 27874 : return matn >= 0? constmat(z, matn): z;
1513 : }
1514 1855783 : if (lx == 3)
1515 : {
1516 346174 : x = subst_higher(gel(x,2), y, matn);
1517 346174 : if (matn >= 0) return x;
1518 346160 : vy = gvar(y);
1519 346160 : return (vy == NO_VARIABLE)? x: gmul(x, pol_1(vy));
1520 : }
1521 1509609 : return matn >= 0? RgX_RgM_eval(x, y): poleval(x,y);
1522 :
1523 26635 : case t_SER:
1524 26635 : vx = varn(x);
1525 26635 : if (varncmp(vx, v) > 0) return subst_higher(x, y, matn);
1526 26628 : ex = valser(x);
1527 26628 : if (varncmp(vx, v) < 0)
1528 : {
1529 56 : if (lx == 2) return matn >= 0? scalarmat(x, matn): gcopy(x);
1530 56 : av = avma; X = pol_x(vx);
1531 56 : av2 = avma;
1532 56 : z = gadd(gsubst(gel(x,lx-1),v,y), zeroser(vx,1));
1533 224 : for (i = lx-2; i>=2; i--)
1534 : {
1535 168 : z = gadd(gmul(z,X), gsubst(gel(x,i),v,y));
1536 168 : if (gc_needed(av2,1))
1537 : {
1538 0 : if(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i);
1539 0 : z = gerepileupto(av2, z);
1540 : }
1541 : }
1542 56 : if (ex) z = gmul(z, pol_xnall(ex,vx));
1543 56 : return gerepileupto(av, z);
1544 : }
1545 26572 : switch(ty) /* here vx == v */
1546 : {
1547 21273 : case t_SER:
1548 21273 : vy = varn(y); ey = valser(y);
1549 21273 : if (ey < 1 || lx == 2) return zeroser(vy, ey*(ex+lx-2));
1550 21273 : if (ey == 1 && serequalXk(y)
1551 1953 : && (varncmp(vx,vy) >= 0 || varncmp(gvar2(x), vy) >= 0))
1552 : { /* y = t + O(t^N) */
1553 1953 : if (lx > ly)
1554 : { /* correct number of significant terms */
1555 1624 : l = ly;
1556 1624 : if (!ex)
1557 1603 : for (i = 3; i < lx; i++)
1558 1603 : if (++l >= lx || !gequal0(gel(x,i))) break;
1559 1624 : lx = l;
1560 : }
1561 1953 : z = sertrunc_copy(x, lx - 2); if (vx != vy) setvarn(z,vy);
1562 1953 : return z;
1563 : }
1564 19320 : if (vy != vx)
1565 : {
1566 28 : long nx = lx - 2, n = minss(ey * nx, ly - 2);
1567 28 : av = avma; z = gel(x, nx+1);
1568 91 : for (i = nx; i > 1; i--)
1569 : {
1570 63 : z = gadd(gmul(y,z), gel(x,i));
1571 63 : if (gc_needed(av,1))
1572 : {
1573 0 : if(DEBUGMEM>1) pari_warn(warnmem,"gsubst (i = %ld)", i);
1574 0 : z = gerepileupto(av, z);
1575 : }
1576 : }
1577 28 : if (ex)
1578 : {
1579 21 : if (ex < 0) { y = ginv(y); ex = -ex; }
1580 21 : z = gmul(z, gpowgs(sertrunc(y, n), ex));
1581 : }
1582 28 : if (lg(z)-2 > n) z = sertrunc_copy(z, n);
1583 28 : return gerepileupto(av,z);
1584 : }
1585 19292 : l = (lx-2)*ey + 2;
1586 19292 : if (ex) { if (l>ly) l = ly; }
1587 19243 : else if (lx != 3)
1588 : {
1589 19257 : for (i = 3; i < lx; i++)
1590 19257 : if (!isexactzero(gel(x,i))) break;
1591 19243 : l = minss(l, (i-2)*ey + (gequal0(y)? 2 : ly));
1592 : }
1593 19292 : av = avma; t = leafcopy(y);
1594 19292 : if (l < ly) setlg(t, l);
1595 19292 : z = scalarser(gen_1, varn(y), l-2);
1596 19292 : gel(z,2) = gel(x,2); /* ensure lg(z) = l even if x[2] = 0 */
1597 77224 : for (i = 3, jb = ey; jb <= l-2; i++,jb += ey)
1598 : {
1599 57939 : if (i < lx) {
1600 132286 : for (j = jb+2; j < minss(l, jb+ly); j++)
1601 74424 : gel(z,j) = gadd(gel(z,j), gmul(gel(x,i),gel(t,j-jb)));
1602 : }
1603 93275 : for (j = minss(ly-1, l-1-jb-ey); j > 1; j--)
1604 : {
1605 35343 : GEN a = gmul(gel(t,2), gel(y,j));
1606 84483 : for (k=2; k<j; k++) a = gadd(a, gmul(gel(t,j-k+2), gel(y,k)));
1607 35343 : gel(t,j) = a;
1608 : }
1609 57932 : if (gc_needed(av,1))
1610 : {
1611 0 : if(DEBUGMEM>1) pari_warn(warnmem,"gsubst");
1612 0 : gerepileall(av,2, &z,&t);
1613 : }
1614 : }
1615 19285 : if (!ex) return gerepilecopy(av,z);
1616 49 : if (ex < 0) { ex = -ex; y = ginv(y); }
1617 49 : return gerepileupto(av, gmul(z, gpowgs(sertrunc(y, l-2), ex)));
1618 :
1619 5257 : case t_POL: case t_RFRAC:
1620 : {
1621 5257 : long N, n = lx-2;
1622 5257 : vy = gvar(y); ey = gval(y,vy);
1623 5257 : if (ey == LONG_MAX)
1624 : { /* y = 0 */
1625 49 : if (ex < 0) pari_err_INV("gsubst",y);
1626 35 : if (!n) return gcopy(x);
1627 28 : if (ex > 0) return Rg_get_0(ty == t_RFRAC? gel(y,2): y);
1628 14 : y = Rg_get_1(ty == t_RFRAC? gel(y,2): y);
1629 14 : return gmul(y, gel(x,2));
1630 : }
1631 5208 : if (ey < 1 || n == 0) return zeroser(vy, ey*(ex+n));
1632 5201 : av = avma;
1633 5201 : n *= ey;
1634 5201 : N = ex? n: maxss(n-ey,1);
1635 5201 : y = (ty == t_RFRAC)? rfrac_to_ser_i(y, N+2): RgX_to_ser(y, N+2);
1636 5201 : if (lg(y)-2 > n) setlg(y, n+2);
1637 5201 : x = ser2pol_i(x, lx);
1638 5201 : if (varncmp(vy,vx) > 0)
1639 49 : z = gadd(poleval(x, y), zeroser(vy,n));
1640 : else
1641 : {
1642 5152 : z = RgXn_eval(x, ser2rfrac_i(y), n);
1643 5152 : if (varn(z) == vy) z = RgX_to_ser(z, n+2);
1644 0 : else z = scalarser(z, vy, n);
1645 : }
1646 5201 : if (!ex) return gerepilecopy(av, z);
1647 5096 : return gerepileupto(av, gmul(z, gpowgs(y,ex)));
1648 : }
1649 :
1650 42 : default:
1651 42 : if (isexactzero(y))
1652 : {
1653 35 : if (ex < 0) pari_err_INV("gsubst",y);
1654 14 : if (ex > 0) return gcopy(y);
1655 7 : if (lx > 2) return gadd(gel(x,2), y); /*add maps to correct ring*/
1656 : }
1657 7 : pari_err_TYPE2("substitution",x,y);
1658 : }
1659 0 : break;
1660 :
1661 1281 : case t_RFRAC:
1662 : {
1663 1281 : GEN a = gel(x,1), b = gel(x,2);
1664 1281 : av = avma;
1665 1281 : a = gsubst(a, v, y);
1666 1281 : b = gsubst(b, v, y); return gerepileupto(av, gdiv(a, b));
1667 : }
1668 :
1669 660227 : case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gsubst(gel(x,i),v,y));
1670 56 : case t_LIST:
1671 56 : z = mklist();
1672 56 : list_data(z) = list_data(x)? gsubst(list_data(x),v,y): NULL;
1673 56 : return z;
1674 : }
1675 0 : return gcopy(x);
1676 : }
1677 :
1678 : /* Return P(x * h), not memory clean */
1679 : GEN
1680 4193 : ser_unscale(GEN P, GEN h)
1681 : {
1682 4193 : long l = lg(P);
1683 4193 : GEN Q = cgetg(l,t_SER);
1684 4193 : Q[1] = P[1];
1685 4193 : if (l != 2)
1686 : {
1687 4193 : long i = 2;
1688 4193 : GEN hi = gpowgs(h, valser(P));
1689 4193 : gel(Q,i) = gmul(gel(P,i), hi);
1690 200508 : for (i++; i<l; i++) { hi = gmul(hi,h); gel(Q,i) = gmul(gel(P,i), hi); }
1691 : }
1692 4193 : return Q;
1693 : }
1694 :
1695 : static int
1696 1358 : safe_polmod(GEN r)
1697 : {
1698 1358 : GEN a = gel(r,1), b = gel(r,2);
1699 1358 : long t = typ(a);
1700 1358 : return 0;
1701 : if (gvar2(b) != NO_VARIABLE) return 0;
1702 : if (is_scalar_t(t)) return 1;
1703 : return (t == t_POL && varn(a) == varn(b) && gvar2(a) == NO_VARIABLE);
1704 : }
1705 : GEN
1706 966 : gsubstvec(GEN e, GEN v, GEN r)
1707 : {
1708 966 : pari_sp av = avma;
1709 966 : long i, j, k, l = lg(v);
1710 : GEN w, z, R;
1711 966 : if ( !is_vec_t(typ(v)) ) pari_err_TYPE("substvec",v);
1712 966 : if ( !is_vec_t(typ(r)) ) pari_err_TYPE("substvec",r);
1713 966 : if (lg(r)!=l) pari_err_DIM("substvec");
1714 966 : w = cgetg(l, t_VECSMALL);
1715 966 : z = cgetg(l, t_VECSMALL);
1716 966 : R = cgetg(l, t_VEC); k = 0;
1717 4256 : for(i = j = 1; i < l; i++)
1718 : {
1719 3290 : GEN T = gel(v,i), ri = gel(r,i);
1720 3290 : if (!gequalX(T)) pari_err_TYPE("substvec [not a variable]", T);
1721 3290 : if (gvar(ri) == NO_VARIABLE || (typ(ri) == t_POLMOD && safe_polmod(ri)))
1722 : { /* no need to take precautions */
1723 1855 : e = gsubst(e, varn(T), ri);
1724 1855 : if (is_vec_t(typ(ri)) && k++) e = shallowconcat1(e);
1725 : }
1726 : else
1727 : {
1728 1435 : w[j] = varn(T);
1729 1435 : z[j] = fetch_var_higher();
1730 1435 : gel(R,j) = ri; j++;
1731 : }
1732 : }
1733 2401 : for(i = 1; i < j; i++) e = gsubst(e,w[i],pol_x(z[i]));
1734 2401 : for(i = 1; i < j; i++)
1735 : {
1736 1435 : e = gsubst(e,z[i],gel(R,i));
1737 1435 : if (is_vec_t(typ(gel(R,i))) && k++) e = shallowconcat1(e);
1738 : }
1739 2401 : for(i = 1; i < j; i++) (void)delete_var();
1740 966 : return k > 1? gerepilecopy(av, e): gerepileupto(av, e);
1741 : }
1742 :
1743 : /*******************************************************************/
1744 : /* */
1745 : /* SERIE RECIPROQUE D'UNE SERIE */
1746 : /* */
1747 : /*******************************************************************/
1748 :
1749 : GEN
1750 98 : serreverse(GEN x)
1751 : {
1752 98 : long v=varn(x), lx = lg(x), i, mi;
1753 98 : pari_sp av0 = avma, av;
1754 : GEN a, y, u;
1755 :
1756 98 : if (typ(x)!=t_SER) pari_err_TYPE("serreverse",x);
1757 98 : if (valser(x)!=1) pari_err_DOMAIN("serreverse", "valuation", "!=", gen_1,x);
1758 91 : if (lx < 3) pari_err_DOMAIN("serreverse", "x", "=", gen_0,x);
1759 91 : y = ser_normalize(x);
1760 91 : if (y == x) a = NULL; else { a = gel(x,2); x = y; }
1761 91 : av = avma;
1762 252 : mi = lx-1; while (mi>=3 && gequal0(gel(x,mi))) mi--;
1763 91 : u = cgetg(lx,t_SER);
1764 91 : y = cgetg(lx,t_SER);
1765 91 : u[1] = y[1] = evalsigne(1) | _evalvalser(1) | evalvarn(v);
1766 91 : gel(u,2) = gel(y,2) = gen_1;
1767 91 : if (lx > 3)
1768 : {
1769 84 : gel(u,3) = gmulsg(-2,gel(x,3));
1770 84 : gel(y,3) = gneg(gel(x,3));
1771 : }
1772 1113 : for (i=3; i<lx-1; )
1773 : {
1774 : pari_sp av2;
1775 : GEN p1;
1776 1022 : long j, k, K = minss(i,mi);
1777 8456 : for (j=3; j<i+1; j++)
1778 : {
1779 7434 : av2 = avma; p1 = gel(x,j);
1780 39291 : for (k = maxss(3,j+2-mi); k < j; k++)
1781 31857 : p1 = gadd(p1, gmul(gel(u,k),gel(x,j-k+2)));
1782 7434 : p1 = gneg(p1);
1783 7434 : gel(u,j) = gerepileupto(av2, gadd(gel(u,j), p1));
1784 : }
1785 1022 : av2 = avma;
1786 1022 : p1 = gmulsg(i,gel(x,i+1));
1787 8309 : for (k = 2; k < K; k++)
1788 : {
1789 7287 : GEN p2 = gmul(gel(x,k+1),gel(u,i-k+2));
1790 7287 : p1 = gadd(p1, gmulsg(k,p2));
1791 : }
1792 1022 : i++;
1793 1022 : gel(u,i) = gerepileupto(av2, gneg(p1));
1794 1022 : gel(y,i) = gdivgu(gel(u,i), i-1);
1795 1022 : if (gc_needed(av,2))
1796 : {
1797 0 : GEN dummy = cgetg(1,t_VEC);
1798 0 : if(DEBUGMEM>1) pari_warn(warnmem,"serreverse");
1799 0 : for(k=i+1; k<lx; k++) gel(u,k) = gel(y,k) = dummy;
1800 0 : gerepileall(av,2, &u,&y);
1801 : }
1802 : }
1803 91 : if (a) y = ser_unscale(y, ginv(a));
1804 91 : return gerepilecopy(av0,y);
1805 : }
1806 :
1807 : /*******************************************************************/
1808 : /* */
1809 : /* DERIVATION ET INTEGRATION */
1810 : /* */
1811 : /*******************************************************************/
1812 : GEN
1813 25424 : derivser(GEN x)
1814 : {
1815 25424 : long i, vx = varn(x), e = valser(x), lx = lg(x);
1816 : GEN y;
1817 25424 : if (ser_isexactzero(x))
1818 : {
1819 7 : x = gcopy(x);
1820 7 : if (e) setvalser(x,e-1);
1821 7 : return x;
1822 : }
1823 25417 : if (e)
1824 : {
1825 602 : y = cgetg(lx,t_SER); y[1] = evalsigne(1)|evalvalser(e-1) | evalvarn(vx);
1826 22960 : for (i=2; i<lx; i++) gel(y,i) = gmulsg(i+e-2,gel(x,i));
1827 : } else {
1828 24815 : if (lx == 3) return zeroser(vx, 0);
1829 20951 : lx--;
1830 20951 : y = cgetg(lx,t_SER); y[1] = evalsigne(1)|_evalvalser(0) | evalvarn(vx);
1831 67382 : for (i=2; i<lx; i++) gel(y,i) = gmulsg(i-1,gel(x,i+1));
1832 : }
1833 21553 : return normalizeser(y);
1834 : }
1835 :
1836 : static GEN
1837 56 : rfrac_deriv(GEN x, long v)
1838 : {
1839 56 : pari_sp av = avma;
1840 56 : GEN y = cgetg(3,t_RFRAC), a = gel(x,1), b = gel(x,2), bp, b0, t, T;
1841 56 : long vx = varn(b);
1842 :
1843 56 : bp = deriv(b, v);
1844 56 : t = simplify_shallow(RgX_gcd(bp, b));
1845 56 : if (typ(t) != t_POL || varn(t) != vx)
1846 : {
1847 35 : if (gequal1(t)) b0 = b;
1848 : else
1849 : {
1850 0 : b0 = RgX_Rg_div(b, t);
1851 0 : bp = RgX_Rg_div(bp, t);
1852 : }
1853 35 : a = gsub(gmul(b0, deriv(a,v)), gmul(a, bp));
1854 35 : if (isexactzero(a)) return gerepileupto(av, a);
1855 35 : if (b0 == b)
1856 : {
1857 35 : gel(y,1) = gerepileupto((pari_sp)y, a);
1858 35 : gel(y,2) = RgX_sqr(b);
1859 : }
1860 : else
1861 : {
1862 0 : gel(y,1) = a;
1863 0 : gel(y,2) = RgX_Rg_mul(RgX_sqr(b0), t);
1864 0 : y = gerepilecopy(av, y);
1865 : }
1866 35 : return y;
1867 : }
1868 21 : b0 = gdivexact(b, t);
1869 21 : bp = gdivexact(bp,t);
1870 21 : a = gsub(gmul(b0, deriv(a,v)), gmul(a, bp));
1871 21 : if (isexactzero(a)) return gerepileupto(av, a);
1872 14 : T = RgX_gcd(a, t);
1873 14 : if (typ(T) != t_POL || varn(T) != vx)
1874 : {
1875 0 : a = gdiv(a, T);
1876 0 : t = gdiv(t, T);
1877 : }
1878 14 : else if (!gequal1(T))
1879 : {
1880 0 : a = gdivexact(a, T);
1881 0 : t = gdivexact(t, T);
1882 : }
1883 14 : gel(y,1) = a;
1884 14 : gel(y,2) = gmul(RgX_sqr(b0), t);
1885 14 : return gerepilecopy(av, y);
1886 : }
1887 :
1888 : GEN
1889 114128 : deriv(GEN x, long v)
1890 : {
1891 114128 : long tx = typ(x);
1892 114128 : if (is_const_t(tx))
1893 39795 : switch(tx)
1894 : {
1895 14 : case t_INTMOD: retmkintmod(gen_0, icopy(gel(x,1)));
1896 14 : case t_FFELT: return FF_zero(x);
1897 39767 : default: return gen_0;
1898 : }
1899 74333 : if (v < 0)
1900 : {
1901 49 : if (tx == t_CLOSURE) return closure_deriv(x);
1902 49 : v = gvar9(x);
1903 : }
1904 74333 : switch(tx)
1905 : {
1906 14 : case t_POLMOD:
1907 : {
1908 14 : GEN a = gel(x,2), b = gel(x,1);
1909 14 : if (v == varn(b)) return Rg_get_0(b);
1910 7 : retmkpolmod(deriv(a,v), RgX_copy(b));
1911 : }
1912 74074 : case t_POL:
1913 74074 : switch(varncmp(varn(x), v))
1914 : {
1915 0 : case 1: return Rg_get_0(x);
1916 66479 : case 0: return RgX_deriv(x);
1917 : }
1918 113505 : pari_APPLY_pol(deriv(gel(x,i),v));
1919 :
1920 147 : case t_SER:
1921 147 : switch(varncmp(varn(x), v))
1922 : {
1923 0 : case 1: return Rg_get_0(x);
1924 133 : case 0: return derivser(x);
1925 : }
1926 14 : if (ser_isexactzero(x)) return gcopy(x);
1927 28 : pari_APPLY_ser(deriv(gel(x,i),v));
1928 :
1929 56 : case t_RFRAC:
1930 56 : return rfrac_deriv(x,v);
1931 :
1932 42 : case t_VEC: case t_COL: case t_MAT:
1933 84 : pari_APPLY_same(deriv(gel(x,i),v));
1934 : }
1935 0 : pari_err_TYPE("deriv",x);
1936 : return NULL; /* LCOV_EXCL_LINE */
1937 : }
1938 :
1939 : /* n-th derivative of t_SER x, n > 0 */
1940 : static GEN
1941 189 : derivnser(GEN x, long n)
1942 : {
1943 189 : long i, vx = varn(x), e = valser(x), lx = lg(x);
1944 : GEN y;
1945 189 : if (ser_isexactzero(x))
1946 : {
1947 7 : x = gcopy(x);
1948 7 : if (e) setvalser(x,e-n);
1949 7 : return x;
1950 : }
1951 182 : if (e < 0 || e >= n)
1952 : {
1953 154 : y = cgetg(lx,t_SER);
1954 154 : y[1] = evalsigne(1)| evalvalser(e-n) | evalvarn(vx);
1955 714 : for (i=0; i<lx-2; i++)
1956 560 : gel(y,i+2) = gmul(muls_interval(i+e-n+1,i+e), gel(x,i+2));
1957 : } else {
1958 28 : if (lx <= n+2) return zeroser(vx, 0);
1959 28 : lx -= n;
1960 28 : y = cgetg(lx,t_SER);
1961 28 : y[1] = evalsigne(1)|_evalvalser(0) | evalvarn(vx);
1962 91 : for (i=0; i<lx-2; i++)
1963 63 : gel(y,i+2) = gmul(mulu_interval(i+1,i+n),gel(x,i+2+n-e));
1964 : }
1965 182 : return normalizeser(y);
1966 : }
1967 :
1968 : /* n-th derivative of t_POL x, n > 0 */
1969 : static GEN
1970 833 : RgX_derivn(GEN x, long n)
1971 : {
1972 833 : long i, vx = varn(x), lx = lg(x);
1973 : GEN y;
1974 833 : if (lx <= n+2) return pol_0(vx);
1975 749 : lx -= n;
1976 749 : y = cgetg(lx,t_POL);
1977 749 : y[1] = evalsigne(1)| evalvarn(vx);
1978 50904 : for (i=0; i<lx-2; i++)
1979 50155 : gel(y,i+2) = gmul(mulu_interval(i+1,i+n),gel(x,i+2+n));
1980 749 : return normalizepol_lg(y, lx);
1981 : }
1982 :
1983 : static GEN
1984 42 : rfrac_derivn(GEN x, long n, long vs)
1985 : {
1986 42 : pari_sp av = avma;
1987 42 : GEN u = gel(x,1), v = gel(x,2);
1988 42 : GEN dv = deriv(v, vs);
1989 : long i;
1990 112 : for (i=1; i<=n; i++)
1991 : {
1992 70 : GEN du = deriv(u, vs);
1993 70 : u = gadd(gmul(du, v), gmulsg (-i, gmul(dv, u)));
1994 : }
1995 42 : v = gpowgs(v, n+1);
1996 42 : return gerepileupto(av, gdiv(u, v));
1997 : }
1998 :
1999 : GEN
2000 1351 : derivn(GEN x, long n, long v)
2001 : {
2002 : long tx;
2003 1351 : if (n < 0) pari_err_DOMAIN("derivn","n","<", gen_0, stoi(n));
2004 1344 : if (n == 0) return gcopy(x);
2005 1344 : tx = typ(x);
2006 1344 : if (is_const_t(tx))
2007 49 : switch(tx)
2008 : {
2009 21 : case t_INTMOD: retmkintmod(gen_0, icopy(gel(x,1)));
2010 21 : case t_FFELT: return FF_zero(x);
2011 7 : default: return gen_0;
2012 : }
2013 1295 : if (v < 0)
2014 : {
2015 1057 : if (tx == t_CLOSURE) return closure_derivn(x, n);
2016 952 : v = gvar9(x);
2017 : }
2018 1190 : switch(tx)
2019 : {
2020 21 : case t_POLMOD:
2021 : {
2022 21 : GEN a = gel(x,2), b = gel(x,1);
2023 21 : if (v == varn(b)) return Rg_get_0(b);
2024 14 : retmkpolmod(derivn(a,n,v), RgX_copy(b));
2025 : }
2026 861 : case t_POL:
2027 861 : switch(varncmp(varn(x), v))
2028 : {
2029 0 : case 1: return Rg_get_0(x);
2030 833 : case 0: return RgX_derivn(x,n);
2031 : }
2032 84 : pari_APPLY_pol(derivn(gel(x,i),n,v));
2033 :
2034 196 : case t_SER:
2035 196 : switch(varncmp(varn(x), v))
2036 : {
2037 0 : case 1: return Rg_get_0(x);
2038 189 : case 0: return derivnser(x, n);
2039 : }
2040 7 : if (ser_isexactzero(x)) return gcopy(x);
2041 28 : pari_APPLY_ser(derivn(gel(x,i),n,v));
2042 :
2043 42 : case t_RFRAC:
2044 42 : return rfrac_derivn(x, n, v);
2045 :
2046 63 : case t_VEC: case t_COL: case t_MAT:
2047 126 : pari_APPLY_same(derivn(gel(x,i),n,v));
2048 : }
2049 7 : pari_err_TYPE("derivn",x);
2050 : return NULL; /* LCOV_EXCL_LINE */
2051 : }
2052 :
2053 : static long
2054 833 : lookup(GEN v, long vx)
2055 : {
2056 833 : long i ,l = lg(v);
2057 1491 : for(i=1; i<l; i++)
2058 1253 : if (varn(gel(v,i)) == vx) return i;
2059 238 : return 0;
2060 : }
2061 :
2062 : GEN
2063 3535 : diffop(GEN x, GEN v, GEN dv)
2064 : {
2065 : pari_sp av;
2066 3535 : long i, idx, lx, tx = typ(x), vx;
2067 : GEN y;
2068 3535 : if (!is_vec_t(typ(v))) pari_err_TYPE("diffop",v);
2069 3535 : if (!is_vec_t(typ(dv))) pari_err_TYPE("diffop",dv);
2070 3535 : if (lg(v)!=lg(dv)) pari_err_DIM("diffop");
2071 3535 : if (is_const_t(tx)) return gen_0;
2072 1148 : switch(tx)
2073 : {
2074 84 : case t_POLMOD:
2075 84 : av = avma;
2076 84 : vx = varn(gel(x,1)); idx = lookup(v,vx);
2077 84 : if (idx) /*Assume the users now what they are doing */
2078 0 : y = gmodulo(diffop(gel(x,2),v,dv), gel(x,1));
2079 : else
2080 : {
2081 84 : GEN m = gel(x,1), pol=gel(x,2);
2082 84 : GEN u = gneg(gdiv(diffop(m,v,dv),RgX_deriv(m)));
2083 84 : y = diffop(pol,v,dv);
2084 84 : if (typ(pol)==t_POL && varn(pol)==varn(m))
2085 70 : y = gadd(y, gmul(u,RgX_deriv(pol)));
2086 84 : y = gmodulo(y, gel(x,1));
2087 : }
2088 84 : return gerepileupto(av, y);
2089 952 : case t_POL:
2090 952 : if (signe(x)==0) return gen_0;
2091 742 : vx = varn(x); idx = lookup(v,vx);
2092 742 : av = avma; lx = lg(x);
2093 742 : y = diffop(gel(x,lx-1),v,dv);
2094 2842 : for (i=lx-2; i>=2; i--) y = gadd(gmul(y,pol_x(vx)),diffop(gel(x,i),v,dv));
2095 742 : if (idx) y = gadd(y, gmul(gel(dv,idx),RgX_deriv(x)));
2096 742 : return gerepileupto(av, y);
2097 :
2098 7 : case t_SER:
2099 7 : if (signe(x)==0) return gen_0;
2100 7 : vx = varn(x); idx = lookup(v,vx);
2101 7 : if (!idx) return gen_0;
2102 7 : av = avma;
2103 7 : if (ser_isexactzero(x)) y = x;
2104 : else
2105 : {
2106 7 : y = cgetg_copy(x, &lx); y[1] = x[1];
2107 119 : for (i=2; i<lx; i++) gel(y,i) = diffop(gel(x,i),v,dv);
2108 7 : y = normalizeser(y); /* y is probably invalid */
2109 7 : y = gsubst(y, vx, pol_x(vx)); /* Fix that */
2110 : }
2111 7 : y = gadd(y, gmul(gel(dv,idx),derivser(x)));
2112 7 : return gerepileupto(av, y);
2113 :
2114 105 : case t_RFRAC: {
2115 105 : GEN a = gel(x,1), b = gel(x,2), ap, bp;
2116 105 : av = avma;
2117 105 : ap = diffop(a, v, dv); bp = diffop(b, v, dv);
2118 105 : y = gsub(gdiv(ap,b),gdiv(gmul(a,bp),gsqr(b)));
2119 105 : return gerepileupto(av, y);
2120 : }
2121 :
2122 0 : case t_VEC: case t_COL: case t_MAT:
2123 0 : pari_APPLY_same(diffop(gel(x,i),v,dv));
2124 : }
2125 0 : pari_err_TYPE("diffop",x);
2126 : return NULL; /* LCOV_EXCL_LINE */
2127 : }
2128 :
2129 : GEN
2130 42 : diffop0(GEN x, GEN v, GEN dv, long n)
2131 : {
2132 42 : pari_sp av=avma;
2133 : long i;
2134 245 : for(i=1; i<=n; i++)
2135 203 : x = gerepileupto(av, diffop(x,v,dv));
2136 42 : return x;
2137 : }
2138 :
2139 : /********************************************************************/
2140 : /** **/
2141 : /** TAYLOR SERIES **/
2142 : /** **/
2143 : /********************************************************************/
2144 : /* swap vars (vx,v) in x (assume vx < v, vx main variable in x), then call
2145 : * act(data, v, x). FIXME: use in other places */
2146 : static GEN
2147 28 : swapvar_act(GEN x, long vx, long v, GEN (*act)(void*, long, GEN), void *data)
2148 : {
2149 28 : long v0 = fetch_var();
2150 28 : GEN y = act(data, v, gsubst(x,vx,pol_x(v0)));
2151 21 : y = gsubst(y,v0,pol_x(vx));
2152 21 : (void)delete_var(); return y;
2153 : }
2154 : /* x + O(v^data) */
2155 : static GEN
2156 14 : tayl_act(void *data, long v, GEN x) { return gadd(zeroser(v, (long)data), x); }
2157 : static GEN
2158 14 : integ_act(void *data, long v, GEN x) { (void)data; return integ(x,v); }
2159 :
2160 : GEN
2161 21 : tayl(GEN x, long v, long precS)
2162 : {
2163 21 : long vx = gvar9(x);
2164 : pari_sp av;
2165 :
2166 21 : if (varncmp(v, vx) <= 0) return gadd(zeroser(v,precS), x);
2167 14 : av = avma;
2168 14 : return gerepileupto(av, swapvar_act(x, vx, v, tayl_act, (void*)precS));
2169 : }
2170 :
2171 : GEN
2172 6986 : ggrando(GEN x, long n)
2173 : {
2174 : long m, v;
2175 :
2176 6986 : switch(typ(x))
2177 : {
2178 4039 : case t_INT:/* bug 3 + O(1) */
2179 4039 : if (signe(x) <= 0) pari_err_DOMAIN("O", "x", "<=", gen_0, x);
2180 4039 : if (!is_pm1(x)) return zeropadic(x,n);
2181 : /* +/-1 = x^0 */
2182 91 : v = m = 0; break;
2183 2940 : case t_POL:
2184 2940 : if (!signe(x)) pari_err_DOMAIN("O", "x", "=", gen_0, x);
2185 2940 : v = varn(x);
2186 2940 : m = n * RgX_val(x); break;
2187 7 : case t_RFRAC:
2188 7 : if (gequal0(gel(x,1))) pari_err_DOMAIN("O", "x", "=", gen_0, x);
2189 7 : v = gvar(x);
2190 7 : m = n * gval(x,v); break;
2191 0 : default: pari_err_TYPE("O", x);
2192 : v = m = 0; /* LCOV_EXCL_LINE */
2193 : }
2194 3038 : return zeroser(v,m);
2195 : }
2196 :
2197 : /*******************************************************************/
2198 : /* */
2199 : /* FORMAL INTEGRATION */
2200 : /* */
2201 : /*******************************************************************/
2202 : GEN
2203 105 : RgX_integ(GEN x)
2204 : {
2205 105 : long i, lx = lg(x);
2206 : GEN y;
2207 105 : if (lx == 2) return RgX_copy(x);
2208 91 : y = cgetg(lx+1, t_POL); y[1] = x[1]; gel(y,2) = gen_0;
2209 273 : for (i=3; i<=lx; i++) gel(y,i) = gdivgu(gel(x,i-1),i-2);
2210 91 : return y;
2211 : }
2212 :
2213 : static void
2214 35 : err_intformal(GEN x)
2215 35 : { pari_err_DOMAIN("intformal", "residue(series, pole)", "!=", gen_0, x); }
2216 :
2217 : GEN
2218 26061 : integser(GEN x)
2219 : {
2220 26061 : long i, lx = lg(x), vx = varn(x), e = valser(x);
2221 : GEN y;
2222 26061 : if (lx == 2) return zeroser(vx, e+1);
2223 22176 : y = cgetg(lx, t_SER);
2224 96754 : for (i=2; i<lx; i++)
2225 : {
2226 74585 : long j = i+e-1;
2227 74585 : GEN c = gel(x,i);
2228 74585 : if (j)
2229 74270 : c = gdivgs(c, j);
2230 : else
2231 : { /* should be isexactzero, but try to avoid error */
2232 315 : if (!gequal0(c)) err_intformal(x);
2233 308 : c = gen_0;
2234 : }
2235 74578 : gel(y,i) = c;
2236 : }
2237 22169 : y[1] = evalsigne(1) | evalvarn(vx) | evalvalser(e+1); return y;
2238 : }
2239 :
2240 : GEN
2241 350 : integ(GEN x, long v)
2242 : {
2243 350 : long tx = typ(x), vx, n;
2244 350 : pari_sp av = avma;
2245 : GEN y, p1;
2246 :
2247 350 : if (v < 0) { v = gvar9(x); if (v == NO_VARIABLE) v = 0; }
2248 350 : if (is_scalar_t(tx))
2249 : {
2250 63 : if (tx == t_POLMOD)
2251 : {
2252 14 : GEN a = gel(x,2), b = gel(x,1);
2253 14 : vx = varn(b);
2254 14 : if (varncmp(v, vx) > 0) retmkpolmod(integ(a,v), RgX_copy(b));
2255 7 : if (v == vx) pari_err_PRIORITY("intformal",x,"=",v);
2256 : }
2257 49 : return deg1pol(x, gen_0, v);
2258 : }
2259 :
2260 287 : switch(tx)
2261 : {
2262 112 : case t_POL:
2263 112 : vx = varn(x);
2264 112 : if (v == vx) return RgX_integ(x);
2265 42 : if (lg(x) == 2) {
2266 14 : if (varncmp(vx, v) < 0) v = vx;
2267 14 : return zeropol(v);
2268 : }
2269 28 : if (varncmp(vx, v) > 0) return deg1pol(x, gen_0, v);
2270 84 : pari_APPLY_pol(integ(gel(x,i),v));
2271 :
2272 77 : case t_SER:
2273 77 : vx = varn(x);
2274 77 : if (v == vx) return integser(x);
2275 21 : if (lg(x) == 2) {
2276 14 : if (varncmp(vx, v) < 0) v = vx;
2277 14 : return zeroser(v, valser(x));
2278 : }
2279 7 : if (varncmp(vx, v) > 0) return deg1pol(x, gen_0, v);
2280 28 : pari_APPLY_ser(integ(gel(x,i),v));
2281 :
2282 56 : case t_RFRAC:
2283 : {
2284 56 : GEN a = gel(x,1), b = gel(x,2), c, d, s;
2285 56 : vx = varn(b);
2286 56 : if (varncmp(vx, v) > 0) return deg1pol(x, gen_0, v);
2287 49 : if (varncmp(vx, v) < 0)
2288 14 : return gerepileupto(av, swapvar_act(x, vx, v, integ_act, NULL));
2289 :
2290 35 : n = degpol(b);
2291 35 : if (typ(a) == t_POL && varn(a) == vx) n += degpol(a);
2292 35 : y = integ(gadd(x, zeroser(v,n + 2)), v);
2293 35 : y = gdiv(gtrunc(gmul(b, y)), b);
2294 35 : if (typ(y) != t_RFRAC) pari_err_BUG("intformal(t_RFRAC)");
2295 35 : c = gel(y,1); d = gel(y,2);
2296 35 : s = gsub(gmul(deriv(c,v),d), gmul(c,deriv(d,v)));
2297 : /* (c'd-cd')/d^2 = y' = x = a/b ? */
2298 35 : if (!gequal(gmul(s,b), gmul(a,gsqr(d)))) err_intformal(x);
2299 7 : if (typ(y)==t_RFRAC && lg(gel(y,1)) == lg(gel(y,2)))
2300 : {
2301 7 : GEN p2 = leading_coeff(gel(y,2));
2302 7 : p1 = gel(y,1);
2303 7 : if (typ(p1) == t_POL && varn(p1) == vx) p1 = leading_coeff(p1);
2304 7 : y = gsub(y, gdiv(p1,p2));
2305 : }
2306 7 : return gerepileupto(av,y);
2307 : }
2308 :
2309 42 : case t_VEC: case t_COL: case t_MAT:
2310 84 : pari_APPLY_same(integ(gel(x,i),v));
2311 : }
2312 0 : pari_err_TYPE("integ",x);
2313 : return NULL; /* LCOV_EXCL_LINE */
2314 : }
2315 :
2316 : /*******************************************************************/
2317 : /* */
2318 : /* FLOOR */
2319 : /* */
2320 : /*******************************************************************/
2321 : static GEN
2322 518 : quad_floor(GEN x)
2323 : {
2324 518 : GEN Q = gel(x,1), D = quad_disc(x), u, v, b, d, z;
2325 518 : if (signe(D) < 0) return NULL;
2326 490 : x = Q_remove_denom(x, &d);
2327 490 : u = gel(x,2);
2328 490 : v = gel(x,3); b = gel(Q,3);
2329 490 : if (typ(u) != t_INT || typ(v) != t_INT) return NULL;
2330 : /* x0 = (2u + v*(-b + sqrt(D))) / (2d) */
2331 483 : z = sqrti(mulii(D, sqri(v)));
2332 483 : if (signe(v) < 0) { z = addiu(z,1); togglesign(z); }
2333 : /* z = floor(v * sqrt(D)) */
2334 483 : z = addii(subii(shifti(u,1), mulii(v,b)), z);
2335 483 : return truedivii(z, d? shifti(d,1): gen_2);
2336 : }
2337 : GEN
2338 5354806 : gfloor(GEN x)
2339 : {
2340 5354806 : switch(typ(x))
2341 : {
2342 5299367 : case t_INT: return icopy(x);
2343 35 : case t_POL: return RgX_copy(x);
2344 37925 : case t_REAL: return floorr(x);
2345 16653 : case t_FRAC: return truedivii(gel(x,1),gel(x,2));
2346 511 : case t_QUAD:
2347 : {
2348 511 : pari_sp av = avma;
2349 : GEN y;
2350 511 : if (!(y = quad_floor(x))) break;
2351 476 : return gerepileuptoint(av, y);
2352 : }
2353 14 : case t_RFRAC: return gdeuc(gel(x,1),gel(x,2));
2354 98 : case t_VEC: case t_COL: case t_MAT:
2355 1533 : pari_APPLY_same(gfloor(gel(x,i)));
2356 : }
2357 238 : pari_err_TYPE("gfloor",x);
2358 : return NULL; /* LCOV_EXCL_LINE */
2359 : }
2360 :
2361 : GEN
2362 426311 : gfrac(GEN x)
2363 : {
2364 : pari_sp av;
2365 : GEN y;
2366 426311 : switch(typ(x))
2367 : {
2368 23614 : case t_INT: return gen_0;
2369 7 : case t_POL: return pol_0(varn(x));
2370 164416 : case t_REAL: av = avma; return gerepileuptoleaf(av, subri(x, floorr(x)));
2371 234544 : case t_FRAC: retmkfrac(modii(gel(x,1),gel(x,2)), icopy(gel(x,2)));
2372 7 : case t_QUAD:
2373 7 : av = avma; if (!(y = quad_floor(x))) break;
2374 7 : return gerepileupto(av, gsub(x, y));
2375 7 : case t_RFRAC: retmkrfrac(grem(gel(x,1),gel(x,2)), gcopy(gel(x,2)));
2376 3688 : case t_VEC: case t_COL: case t_MAT:
2377 34423 : pari_APPLY_same(gfrac(gel(x,i)));
2378 : }
2379 28 : pari_err_TYPE("gfrac",x);
2380 : return NULL; /* LCOV_EXCL_LINE */
2381 : }
2382 :
2383 : /* assume x t_REAL */
2384 : GEN
2385 2454 : ceilr(GEN x)
2386 : {
2387 2454 : pari_sp av = avma;
2388 2454 : GEN y = floorr(x);
2389 2454 : if (cmpri(x, y)) return gerepileuptoint(av, addui(1,y));
2390 29 : return y;
2391 : }
2392 :
2393 : GEN
2394 235460 : gceil(GEN x)
2395 : {
2396 : pari_sp av;
2397 : GEN y;
2398 235460 : switch(typ(x))
2399 : {
2400 17962 : case t_INT: return icopy(x);
2401 21 : case t_POL: return RgX_copy(x);
2402 2376 : case t_REAL: return ceilr(x);
2403 214975 : case t_FRAC:
2404 214975 : av = avma; y = divii(gel(x,1),gel(x,2));
2405 214976 : if (signe(gel(x,1)) > 0) y = gerepileuptoint(av, addui(1,y));
2406 214976 : return y;
2407 49 : case t_QUAD:
2408 49 : if (!is_realquad(x)) break;
2409 42 : if (gequal0(gel(x,3))) return gceil(gel(x,2));
2410 35 : av = avma; return gerepileupto(av, addiu(gfloor(x), 1));
2411 7 : case t_RFRAC:
2412 7 : return gdeuc(gel(x,1),gel(x,2));
2413 35 : case t_VEC: case t_COL: case t_MAT:
2414 105 : pari_APPLY_same(gceil(gel(x,i)));
2415 : }
2416 42 : pari_err_TYPE("gceil",x);
2417 : return NULL; /* LCOV_EXCL_LINE */
2418 : }
2419 :
2420 : GEN
2421 6027 : round0(GEN x, GEN *pte)
2422 : {
2423 6027 : if (pte) { long e; x = grndtoi(x,&e); *pte = stoi(e); }
2424 6020 : return ground(x);
2425 : }
2426 :
2427 : /* x t_REAL, return q=floor(x+1/2), set e = expo(x-q) */
2428 : static GEN
2429 52611134 : round_i(GEN x, long *pe)
2430 : {
2431 : long e;
2432 52611134 : GEN B, q,r, m = mantissa_real(x, &e); /* x = m/2^e */
2433 52607247 : if (e <= 0)
2434 : {
2435 13371638 : if (e) m = shifti(m,-e);
2436 13371514 : if (pe) *pe = -e;
2437 13371514 : return m;
2438 : }
2439 39235609 : B = int2n(e-1);
2440 39235821 : m = addii(m, B);
2441 39235965 : q = shifti(m, -e);
2442 39235798 : r = remi2n(m, e);
2443 : /* 2^e (x+1/2) = m = 2^e q + r, sgn(r)=sgn(m), |r|<2^e */
2444 39237962 : if (!signe(r))
2445 24630 : { if (pe) *pe = -1; }
2446 : else
2447 : {
2448 39213332 : if (signe(m) < 0)
2449 : {
2450 15846897 : q = subiu(q,1);
2451 15846846 : r = addii(r, B);
2452 : }
2453 : else
2454 23366435 : r = subii(r, B);
2455 : /* |x - q| = |r| / 2^e */
2456 39212901 : if (pe) *pe = signe(r)? expi(r) - e: -e;
2457 39212860 : cgiv(r);
2458 : }
2459 39238114 : return q;
2460 : }
2461 : /* assume x a t_REAL */
2462 : GEN
2463 3050880 : roundr(GEN x)
2464 : {
2465 3050880 : long ex, s = signe(x);
2466 : pari_sp av;
2467 3050880 : if (!s || (ex=expo(x)) < -1) return gen_0;
2468 2366686 : if (ex == -1) return s>0? gen_1:
2469 188717 : absrnz_equal2n(x)? gen_0: gen_m1;
2470 1757108 : av = avma; x = round_i(x, &ex);
2471 1757100 : if (ex >= 0) pari_err_PREC( "roundr (precision loss in truncation)");
2472 1757100 : return gerepileuptoint(av, x);
2473 : }
2474 : GEN
2475 284850 : roundr_safe(GEN x)
2476 : {
2477 284850 : long ex, s = signe(x);
2478 : pari_sp av;
2479 :
2480 284850 : if (!s || (ex = expo(x)) < -1) return gen_0;
2481 284806 : if (ex == -1) return s>0? gen_1:
2482 0 : absrnz_equal2n(x)? gen_0: gen_m1;
2483 284779 : av = avma; x = round_i(x, NULL);
2484 284779 : return gerepileuptoint(av, x);
2485 : }
2486 :
2487 : GEN
2488 2810739 : ground(GEN x)
2489 : {
2490 : pari_sp av;
2491 : GEN y;
2492 :
2493 2810739 : switch(typ(x))
2494 : {
2495 582233 : case t_INT: return icopy(x);
2496 14 : case t_INTMOD: return gcopy(x);
2497 1663998 : case t_REAL: return roundr(x);
2498 60702 : case t_FRAC: return diviiround(gel(x,1), gel(x,2));
2499 49 : case t_QUAD:
2500 : {
2501 49 : GEN Q = gel(x,1), u, v, b, d, z;
2502 49 : av = avma;
2503 49 : if (is_realquad(x)) return gerepileupto(av, gfloor(gadd(x, ghalf)));
2504 7 : u = gel(x,2);
2505 7 : v = gel(x,3); b = gel(Q,3);
2506 7 : u = ground(gsub(u, gmul2n(gmul(v,b),-1)));
2507 7 : v = Q_remove_denom(v, &d);
2508 7 : if (!d) d = gen_1;
2509 : /* Im x = v sqrt(|D|) / (2d),
2510 : * Im(round(x)) = floor((d + v sqrt(|D|)) / (2d))
2511 : * = floor(floor(d + v sqrt(|D|)) / (2d)) */
2512 7 : z = sqrti(mulii(sqri(v), quad_disc(x)));
2513 7 : if (signe(v) < 0) { z = addiu(z,1); togglesign(z); }
2514 : /* z = floor(v * sqrt(|D|)) */
2515 7 : v = truedivii(addii(z, d), shifti(d,1));
2516 7 : return gerepilecopy(av, signe(v)? mkcomplex(u,v): u);
2517 : }
2518 14 : case t_POLMOD:
2519 14 : retmkpolmod(ground(gel(x,2)), RgX_copy(gel(x,1)));
2520 :
2521 4257 : case t_COMPLEX:
2522 4257 : av = avma; y = cgetg(3, t_COMPLEX);
2523 4257 : gel(y,2) = ground(gel(x,2));
2524 4257 : if (!signe(gel(y,2))) { set_avma(av); return ground(gel(x,1)); }
2525 217 : gel(y,1) = ground(gel(x,1)); return y;
2526 :
2527 91 : case t_POL:
2528 4011 : pari_APPLY_pol(ground(gel(x,i)));
2529 182 : case t_SER:
2530 182 : if (ser_isexactzero(x)) return gcopy(x);
2531 42 : pari_APPLY_ser(ground(gel(x,i)));
2532 21 : case t_RFRAC:
2533 21 : av = avma;
2534 21 : return gerepileupto(av, gdiv(ground(gel(x,1)), ground(gel(x,2))));
2535 499183 : case t_VEC: case t_COL: case t_MAT:
2536 2426191 : pari_APPLY_same(ground(gel(x,i)));
2537 : }
2538 6 : pari_err_TYPE("ground",x);
2539 : return NULL; /* LCOV_EXCL_LINE */
2540 : }
2541 :
2542 : /* e = number of error bits on integral part */
2543 : GEN
2544 89352381 : grndtoi(GEN x, long *e)
2545 : {
2546 : GEN y;
2547 : long i, lx, e1;
2548 : pari_sp av;
2549 :
2550 89352381 : if (e) *e = -(long)HIGHEXPOBIT;
2551 89352381 : switch(typ(x))
2552 : {
2553 10041235 : case t_INT: return icopy(x);
2554 55628561 : case t_REAL: {
2555 55628561 : long ex = expo(x);
2556 55628561 : if (!signe(x) || ex < -1)
2557 : {
2558 5059121 : if (e) *e = ex;
2559 5059121 : return gen_0;
2560 : }
2561 50569440 : av = avma; x = round_i(x, e);
2562 50566955 : return gerepileuptoint(av, x);
2563 : }
2564 27629 : case t_FRAC:
2565 27629 : y = diviiround(gel(x,1), gel(x,2)); if (!e) return y;
2566 26432 : av = avma; *e = gexpo(gsub(x, y)); set_avma(av);
2567 26432 : return y;
2568 7 : case t_INTMOD: return gcopy(x);
2569 7 : case t_QUAD:
2570 7 : y = ground(x); av = avma; if (!e) return y;
2571 7 : *e = gexpo(gsub(x,y)); set_avma(avma); return y;
2572 1634127 : case t_COMPLEX:
2573 1634127 : av = avma; y = cgetg(3, t_COMPLEX);
2574 1634127 : gel(y,2) = grndtoi(gel(x,2), e);
2575 1634127 : if (!signe(gel(y,2))) {
2576 244554 : set_avma(av);
2577 244554 : y = grndtoi(gel(x,1), e? &e1: NULL);
2578 : }
2579 : else
2580 1389573 : gel(y,1) = grndtoi(gel(x,1), e? &e1: NULL);
2581 1634127 : if (e && e1 > *e) *e = e1;
2582 1634127 : return y;
2583 :
2584 7 : case t_POLMOD:
2585 7 : retmkpolmod(grndtoi(gel(x,2), e), RgX_copy(gel(x,1)));
2586 :
2587 317692 : case t_POL:
2588 317692 : y = cgetg_copy(x, &lx); y[1] = x[1];
2589 3232781 : for (i=2; i<lx; i++)
2590 : {
2591 2915098 : gel(y,i) = grndtoi(gel(x,i), &e1);
2592 2915089 : if (e && e1 > *e) *e = e1;
2593 : }
2594 317683 : return normalizepol_lg(y, lx);
2595 168 : case t_SER:
2596 168 : if (ser_isexactzero(x)) return gcopy(x);
2597 154 : y = cgetg_copy(x, &lx); y[1] = x[1];
2598 462 : for (i=2; i<lx; i++)
2599 : {
2600 308 : gel(y,i) = grndtoi(gel(x,i), &e1);
2601 308 : if (e && e1 > *e) *e = e1;
2602 : }
2603 154 : return normalizeser(y);
2604 7 : case t_RFRAC:
2605 7 : y = cgetg(3,t_RFRAC);
2606 7 : gel(y,1) = grndtoi(gel(x,1), e? &e1: NULL); if (e && e1 > *e) *e = e1;
2607 7 : gel(y,2) = grndtoi(gel(x,2), e? &e1: NULL); if (e && e1 > *e) *e = e1;
2608 7 : return y;
2609 21703788 : case t_VEC: case t_COL: case t_MAT:
2610 21703788 : y = cgetg_copy(x, &lx);
2611 77243122 : for (i=1; i<lx; i++)
2612 : {
2613 55539972 : gel(y,i) = grndtoi(gel(x,i), e? &e1: NULL);
2614 55539330 : if (e && e1 > *e) *e = e1;
2615 : }
2616 21703150 : return y;
2617 : }
2618 6 : pari_err_TYPE("grndtoi",x);
2619 : return NULL; /* LCOV_EXCL_LINE */
2620 : }
2621 :
2622 : /* trunc(x * 2^s). lindep() sanity checks rely on this function to return a
2623 : * t_INT or fail when fed a non-t_COMPLEX input; so do not make this one
2624 : * recursive [ or change the lindep call ] */
2625 : GEN
2626 117137100 : gtrunc2n(GEN x, long s)
2627 : {
2628 : GEN z;
2629 117137100 : switch(typ(x))
2630 : {
2631 37434489 : case t_INT: return shifti(x, s);
2632 62493534 : case t_REAL: return trunc2nr(x, s);
2633 497 : case t_FRAC: {
2634 : pari_sp av;
2635 497 : GEN a = gel(x,1), b = gel(x,2), q;
2636 497 : if (s == 0) return divii(a, b);
2637 497 : av = avma;
2638 497 : if (s < 0) q = divii(shifti(a, s), b);
2639 : else {
2640 : GEN r;
2641 497 : q = dvmdii(a, b, &r);
2642 497 : q = addii(shifti(q,s), divii(shifti(r,s), b));
2643 : }
2644 497 : return gerepileuptoint(av, q);
2645 : }
2646 17293739 : case t_COMPLEX:
2647 17293739 : z = cgetg(3, t_COMPLEX);
2648 17297094 : gel(z,2) = gtrunc2n(gel(x,2), s);
2649 17294654 : if (!signe(gel(z,2))) {
2650 1604118 : set_avma((pari_sp)(z + 3));
2651 1604111 : return gtrunc2n(gel(x,1), s);
2652 : }
2653 15690536 : gel(z,1) = gtrunc2n(gel(x,1), s);
2654 15688518 : return z;
2655 0 : default: pari_err_TYPE("gtrunc2n",x);
2656 : return NULL; /* LCOV_EXCL_LINE */
2657 : }
2658 : }
2659 :
2660 : /* e = number of error bits on integral part */
2661 : GEN
2662 1133676 : gcvtoi(GEN x, long *e)
2663 : {
2664 1133676 : long tx = typ(x), lx, e1;
2665 : GEN y;
2666 :
2667 1133676 : if (tx == t_REAL)
2668 : {
2669 1133543 : long ex = expo(x); if (ex < 0) { *e = ex; return gen_0; }
2670 1133452 : e1 = ex - bit_prec(x) + 1;
2671 1133453 : y = mantissa2nr(x, e1);
2672 1133445 : if (e1 <= 0) { pari_sp av = avma; e1 = expo(subri(x,y)); set_avma(av); }
2673 1133432 : *e = e1; return y;
2674 : }
2675 133 : *e = -(long)HIGHEXPOBIT;
2676 133 : if (is_matvec_t(tx))
2677 : {
2678 : long i;
2679 28 : y = cgetg_copy(x, &lx);
2680 84 : for (i=1; i<lx; i++)
2681 : {
2682 56 : gel(y,i) = gcvtoi(gel(x,i),&e1);
2683 56 : if (e1 > *e) *e = e1;
2684 : }
2685 28 : return y;
2686 : }
2687 105 : return gtrunc(x);
2688 : }
2689 :
2690 : int
2691 445890 : isint(GEN n, GEN *ptk)
2692 : {
2693 445890 : switch(typ(n))
2694 : {
2695 396792 : case t_INT: *ptk = n; return 1;
2696 1330 : case t_REAL: {
2697 1330 : pari_sp av0 = avma;
2698 1330 : GEN z = floorr(n);
2699 1330 : pari_sp av = avma;
2700 1330 : long s = signe(subri(n, z));
2701 1330 : if (s) return gc_bool(av0,0);
2702 21 : *ptk = z; return gc_bool(av,1);
2703 : }
2704 30618 : case t_FRAC: return 0;
2705 16961 : case t_COMPLEX: return gequal0(gel(n,2)) && isint(gel(n,1),ptk);
2706 0 : case t_QUAD: return gequal0(gel(n,3)) && isint(gel(n,2),ptk);
2707 189 : default: pari_err_TYPE("isint",n);
2708 : return 0; /* LCOV_EXCL_LINE */
2709 : }
2710 : }
2711 :
2712 : int
2713 326463 : issmall(GEN n, long *ptk)
2714 : {
2715 326463 : pari_sp av = avma;
2716 : GEN z;
2717 : long k;
2718 326463 : if (!isint(n, &z)) return 0;
2719 324881 : k = itos_or_0(z); set_avma(av);
2720 324881 : if (k || lgefint(z) == 2) { *ptk = k; return 1; }
2721 0 : return 0;
2722 : }
2723 :
2724 : /* smallest integer greater than any incarnations of the real x
2725 : * Avoid "precision loss in truncation" */
2726 : GEN
2727 1050825 : ceil_safe(GEN x)
2728 : {
2729 1050825 : pari_sp av = avma;
2730 1050825 : long e, tx = typ(x);
2731 : GEN y;
2732 :
2733 1050825 : if (is_rational_t(tx)) return gceil(x);
2734 1050534 : y = gcvtoi(x,&e);
2735 1050524 : if (gsigne(x) >= 0)
2736 : {
2737 1050024 : if (e < 0) e = 0;
2738 1050024 : y = addii(y, int2n(e));
2739 : }
2740 1050523 : return gerepileuptoint(av, y);
2741 : }
2742 : /* largest integer smaller than any incarnations of the real x
2743 : * Avoid "precision loss in truncation" */
2744 : GEN
2745 71307 : floor_safe(GEN x)
2746 : {
2747 71307 : pari_sp av = avma;
2748 71307 : long e, tx = typ(x);
2749 : GEN y;
2750 :
2751 71307 : if (is_rational_t(tx)) return gfloor(x);
2752 71307 : y = gcvtoi(x,&e);
2753 71304 : if (gsigne(x) <= 0)
2754 : {
2755 21 : if (e < 0) e = 0;
2756 21 : y = subii(y, int2n(e));
2757 : }
2758 71305 : return gerepileuptoint(av, y);
2759 : }
2760 :
2761 : GEN
2762 10997 : ser2rfrac_i(GEN x)
2763 : {
2764 10997 : long e = valser(x);
2765 10997 : GEN a = ser2pol_i(x, lg(x));
2766 10997 : if (e) {
2767 6384 : if (e > 0) a = RgX_shift_shallow(a, e);
2768 0 : else a = gred_rfrac_simple(a, pol_xn(-e, varn(a)));
2769 : }
2770 10997 : return a;
2771 : }
2772 :
2773 : static GEN
2774 651 : ser2rfrac(GEN x)
2775 : {
2776 651 : pari_sp av = avma;
2777 651 : return gerepilecopy(av, ser2rfrac_i(x));
2778 : }
2779 :
2780 : /* x t_PADIC, truncate to rational (t_INT/t_FRAC) */
2781 : GEN
2782 689405 : padic_to_Q(GEN x)
2783 : {
2784 689405 : GEN u = gel(x,4), p;
2785 : long v;
2786 689405 : if (!signe(u)) return gen_0;
2787 683343 : v = valp(x);
2788 683343 : if (!v) return icopy(u);
2789 258503 : p = gel(x,2);
2790 258503 : if (v>0)
2791 : {
2792 258390 : pari_sp av = avma;
2793 258390 : return gerepileuptoint(av, mulii(u, powiu(p,v)));
2794 : }
2795 113 : retmkfrac(icopy(u), powiu(p,-v));
2796 : }
2797 : GEN
2798 14 : padic_to_Q_shallow(GEN x)
2799 : {
2800 14 : GEN u = gel(x,4), p, q, q2;
2801 : long v;
2802 14 : if (!signe(u)) return gen_0;
2803 14 : q = gel(x,3); q2 = shifti(q,-1);
2804 14 : v = valp(x);
2805 14 : u = Fp_center_i(u, q, q2);
2806 14 : if (!v) return u;
2807 7 : p = gel(x,2);
2808 7 : if (v>0) return mulii(powiu(p,v), u);
2809 7 : return mkfrac(u, powiu(p,-v));
2810 : }
2811 : GEN
2812 196 : QpV_to_QV(GEN v)
2813 : {
2814 : long i, l;
2815 196 : GEN w = cgetg_copy(v, &l);
2816 931 : for (i = 1; i < l; i++)
2817 : {
2818 735 : GEN c = gel(v,i);
2819 735 : switch(typ(c))
2820 : {
2821 721 : case t_INT:
2822 721 : case t_FRAC: break;
2823 14 : case t_PADIC: c = padic_to_Q_shallow(c); break;
2824 0 : default: pari_err_TYPE("padic_to_Q", v);
2825 : }
2826 735 : gel(w,i) = c;
2827 : }
2828 196 : return w;
2829 : }
2830 :
2831 : GEN
2832 597727 : gtrunc(GEN x)
2833 : {
2834 597727 : switch(typ(x))
2835 : {
2836 84175 : case t_INT: return icopy(x);
2837 49098 : case t_REAL: return truncr(x);
2838 56 : case t_FRAC: return divii(gel(x,1),gel(x,2));
2839 432730 : case t_PADIC: return padic_to_Q(x);
2840 42 : case t_POL: return RgX_copy(x);
2841 14 : case t_RFRAC: return gdeuc(gel(x,1),gel(x,2));
2842 623 : case t_SER: return ser2rfrac(x);
2843 187215 : case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(gtrunc(gel(x,i)));
2844 : }
2845 56 : pari_err_TYPE("gtrunc",x);
2846 : return NULL; /* LCOV_EXCL_LINE */
2847 : }
2848 :
2849 : GEN
2850 217 : trunc0(GEN x, GEN *pte)
2851 : {
2852 217 : if (pte) { long e; x = gcvtoi(x,&e); *pte = stoi(e); }
2853 189 : return gtrunc(x);
2854 : }
2855 : /*******************************************************************/
2856 : /* */
2857 : /* CONVERSIONS --> INT, POL & SER */
2858 : /* */
2859 : /*******************************************************************/
2860 :
2861 : /* return a_(n-1) B^(n-1) + ... + a_0, where B = 2^32.
2862 : * The a_i are 32bits integers */
2863 : GEN
2864 24076 : mkintn(long n, ...)
2865 : {
2866 : va_list ap;
2867 : GEN x, y;
2868 : long i;
2869 : #ifdef LONG_IS_64BIT
2870 20670 : long e = (n&1);
2871 20670 : n = (n+1) >> 1;
2872 : #endif
2873 24076 : va_start(ap,n);
2874 24076 : x = cgetipos(n+2);
2875 24076 : y = int_MSW(x);
2876 85138 : for (i=0; i <n; i++)
2877 : {
2878 : #ifdef LONG_IS_64BIT
2879 47700 : ulong a = (e && !i)? 0: (ulong) va_arg(ap, unsigned int);
2880 47700 : ulong b = (ulong) va_arg(ap, unsigned int);
2881 47700 : *y = (a << 32) | b;
2882 : #else
2883 13362 : *y = (ulong) va_arg(ap, unsigned int);
2884 : #endif
2885 61062 : y = int_precW(y);
2886 : }
2887 24076 : va_end(ap);
2888 24076 : return int_normalize(x, 0);
2889 : }
2890 :
2891 : /* 2^32 a + b */
2892 : GEN
2893 243460 : uu32toi(ulong a, ulong b)
2894 : {
2895 : #ifdef LONG_IS_64BIT
2896 196151 : return utoi((a<<32) | b);
2897 : #else
2898 47309 : return uutoi(a, b);
2899 : #endif
2900 : }
2901 : /* - (2^32 a + b), assume a or b != 0 */
2902 : GEN
2903 72138 : uu32toineg(ulong a, ulong b)
2904 : {
2905 : #ifdef LONG_IS_64BIT
2906 61713 : return utoineg((a<<32) | b);
2907 : #else
2908 10425 : return uutoineg(a, b);
2909 : #endif
2910 : }
2911 :
2912 : /* return a_(n-1) x^(n-1) + ... + a_0 */
2913 : GEN
2914 5465146 : mkpoln(long n, ...)
2915 : {
2916 : va_list ap;
2917 : GEN x, y;
2918 5465146 : long i, l = n+2;
2919 5465146 : va_start(ap,n);
2920 5465146 : x = cgetg(l, t_POL); y = x + 2;
2921 5466429 : x[1] = evalvarn(0);
2922 23993979 : for (i=n-1; i >= 0; i--) gel(y,i) = va_arg(ap, GEN);
2923 5470942 : va_end(ap); return normalizepol_lg(x, l);
2924 : }
2925 :
2926 : /* return [a_1, ..., a_n] */
2927 : GEN
2928 1141729 : mkvecn(long n, ...)
2929 : {
2930 : va_list ap;
2931 : GEN x;
2932 : long i;
2933 1141729 : va_start(ap,n);
2934 1141729 : x = cgetg(n+1, t_VEC);
2935 7323011 : for (i=1; i <= n; i++) gel(x,i) = va_arg(ap, GEN);
2936 1141720 : va_end(ap); return x;
2937 : }
2938 :
2939 : GEN
2940 1379 : mkcoln(long n, ...)
2941 : {
2942 : va_list ap;
2943 : GEN x;
2944 : long i;
2945 1379 : va_start(ap,n);
2946 1379 : x = cgetg(n+1, t_COL);
2947 11032 : for (i=1; i <= n; i++) gel(x,i) = va_arg(ap, GEN);
2948 1379 : va_end(ap); return x;
2949 : }
2950 :
2951 : GEN
2952 126234 : mkvecsmalln(long n, ...)
2953 : {
2954 : va_list ap;
2955 : GEN x;
2956 : long i;
2957 126234 : va_start(ap,n);
2958 126234 : x = cgetg(n+1, t_VECSMALL);
2959 878967 : for (i=1; i <= n; i++) x[i] = va_arg(ap, long);
2960 126234 : va_end(ap); return x;
2961 : }
2962 :
2963 : GEN
2964 17762361 : scalarpol(GEN x, long v)
2965 : {
2966 : GEN y;
2967 17762361 : if (isrationalzero(x)) return zeropol(v);
2968 6001789 : y = cgetg(3,t_POL);
2969 6001813 : y[1] = gequal0(x)? evalvarn(v)
2970 6001810 : : evalvarn(v) | evalsigne(1);
2971 6001810 : gel(y,2) = gcopy(x); return y;
2972 : }
2973 : GEN
2974 3676135 : scalarpol_shallow(GEN x, long v)
2975 : {
2976 : GEN y;
2977 3676135 : if (isrationalzero(x)) return zeropol(v);
2978 3566848 : y = cgetg(3,t_POL);
2979 3566848 : y[1] = gequal0(x)? evalvarn(v)
2980 3566847 : : evalvarn(v) | evalsigne(1);
2981 3566847 : gel(y,2) = x; return y;
2982 : }
2983 :
2984 : /* x0 + x1*T, do not assume x1 != 0 */
2985 : GEN
2986 560319 : deg1pol(GEN x1, GEN x0,long v)
2987 : {
2988 560319 : GEN x = cgetg(4,t_POL);
2989 560319 : x[1] = evalsigne(1) | evalvarn(v);
2990 560319 : gel(x,2) = x0 == gen_0? x0: gcopy(x0); /* gen_0 frequent */
2991 560319 : gel(x,3) = gcopy(x1); return normalizepol_lg(x,4);
2992 : }
2993 :
2994 : /* same, no copy */
2995 : GEN
2996 8544227 : deg1pol_shallow(GEN x1, GEN x0,long v)
2997 : {
2998 8544227 : GEN x = cgetg(4,t_POL);
2999 8544338 : x[1] = evalsigne(1) | evalvarn(v);
3000 8544338 : gel(x,2) = x0;
3001 8544338 : gel(x,3) = x1; return normalizepol_lg(x,4);
3002 : }
3003 :
3004 : GEN
3005 320249 : deg2pol_shallow(GEN x2, GEN x1, GEN x0, long v)
3006 : {
3007 320249 : GEN x = cgetg(5,t_POL);
3008 320251 : x[1] = evalsigne(1) | evalvarn(v);
3009 320251 : gel(x,2) = x0;
3010 320251 : gel(x,3) = x1;
3011 320251 : gel(x,4) = x2;
3012 320251 : return normalizepol_lg(x,5);
3013 : }
3014 :
3015 : static GEN
3016 3469446 : _gtopoly(GEN x, long v, int reverse)
3017 : {
3018 3469446 : long tx = typ(x);
3019 : GEN y;
3020 :
3021 3469446 : if (v<0) v = 0;
3022 3469446 : switch(tx)
3023 : {
3024 21 : case t_POL:
3025 21 : if (varncmp(varn(x), v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v);
3026 21 : y = RgX_copy(x); break;
3027 28 : case t_SER:
3028 28 : if (varncmp(varn(x), v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v);
3029 28 : y = ser2rfrac(x);
3030 28 : if (typ(y) != t_POL)
3031 0 : pari_err_DOMAIN("gtopoly", "valuation", "<", gen_0, x);
3032 28 : break;
3033 42 : case t_RFRAC:
3034 : {
3035 42 : GEN a = gel(x,1), b = gel(x,2);
3036 42 : long vb = varn(b);
3037 42 : if (varncmp(vb, v) < 0) pari_err_PRIORITY("gtopoly", x, "<", v);
3038 42 : if (typ(a) != t_POL || varn(a) != vb) return zeropol(v);
3039 21 : y = RgX_div(a,b); break;
3040 : }
3041 337043 : case t_VECSMALL: x = zv_to_ZV(x); /* fall through */
3042 3468788 : case t_QFB: case t_VEC: case t_COL: case t_MAT:
3043 : {
3044 3468788 : long j, k, lx = lg(x);
3045 : GEN z;
3046 3468788 : if (tx == t_QFB) lx--;
3047 3468788 : if (varncmp(gvar(x), v) <= 0) pari_err_PRIORITY("gtopoly", x, "<=", v);
3048 3468795 : y = cgetg(lx+1, t_POL);
3049 3468794 : y[1] = evalvarn(v);
3050 3468794 : if (reverse) {
3051 2434012 : x--;
3052 26224492 : for (j=2; j<=lx; j++) gel(y,j) = gel(x,j);
3053 : } else {
3054 5299367 : for (j=2, k=lx; k>=2; j++) gel(y,j) = gel(x,--k);
3055 : }
3056 3468794 : z = RgX_copy(normalizepol_lg(y,lx+1));
3057 3468791 : settyp(y, t_VECSMALL);/* left on stack */
3058 3468791 : return z;
3059 : }
3060 567 : default:
3061 567 : if (is_scalar_t(tx)) return scalarpol(x,v);
3062 7 : pari_err_TYPE("gtopoly",x);
3063 : return NULL; /* LCOV_EXCL_LINE */
3064 : }
3065 70 : setvarn(y,v); return y;
3066 : }
3067 :
3068 : GEN
3069 2434047 : gtopolyrev(GEN x, long v) { return _gtopoly(x,v,1); }
3070 :
3071 : GEN
3072 1035398 : gtopoly(GEN x, long v) { return _gtopoly(x,v,0); }
3073 :
3074 : static GEN
3075 1092 : gtovecpost(GEN x, long n)
3076 : {
3077 1092 : long i, imax, lx, tx = typ(x);
3078 1092 : GEN y = zerovec(n);
3079 :
3080 1092 : if (is_scalar_t(tx) || tx == t_RFRAC) { gel(y,1) = gcopy(x); return y; }
3081 343 : switch(tx)
3082 : {
3083 56 : case t_POL:
3084 56 : lx = lg(x); imax = minss(lx-2, n);
3085 224 : for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,lx-i));
3086 56 : return y;
3087 28 : case t_SER:
3088 28 : lx = lg(x); imax = minss(lx-2, n); x++;
3089 84 : for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i));
3090 28 : return y;
3091 28 : case t_QFB:
3092 28 : lx = lg(x)-1; /* remove discriminant */
3093 28 : imax = minss(lx-1, n);
3094 112 : for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i));
3095 28 : return y;
3096 28 : case t_VEC: case t_COL:
3097 28 : lx = lg(x); imax = minss(lx-1, n);
3098 84 : for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i));
3099 28 : return y;
3100 63 : case t_LIST:
3101 63 : if (list_typ(x) == t_LIST_MAP) pari_err_TYPE("gtovec",x);
3102 56 : x = list_data(x); lx = x? lg(x): 1;
3103 56 : imax = minss(lx-1, n);
3104 252 : for (i=1; i<=imax; i++) gel(y,i) = gcopy(gel(x,i));
3105 56 : return y;
3106 56 : case t_STR:
3107 : {
3108 56 : char *s = GSTR(x);
3109 56 : imax = minss(strlen(s), n); s--;
3110 224 : for (i=1; i<=imax; i++) gel(y,i) = chartoGENstr(s[i]);
3111 56 : return y;
3112 : }
3113 28 : case t_VECSMALL:
3114 28 : lx = lg(x); imax = minss(lx-1, n);
3115 84 : for (i=1; i<=imax; i++) gel(y,i) = stoi(x[i]);
3116 28 : return y;
3117 56 : default: pari_err_TYPE("gtovec",x);
3118 : return NULL; /*LCOV_EXCL_LINE*/
3119 : }
3120 : }
3121 :
3122 : static GEN
3123 3563 : init_vectopre(long a, long n, GEN y, long *imax)
3124 : {
3125 3563 : if (n <= a) { *imax = n; return y; }
3126 2765 : *imax = a; return y + n - a;
3127 : }
3128 : /* assume n > 0 */
3129 : static GEN
3130 3619 : gtovecpre(GEN x, long n)
3131 : {
3132 3619 : long a, i, imax, lx, tx = typ(x);
3133 3619 : GEN y = zerovec(n), y0;
3134 :
3135 3619 : if (is_scalar_t(tx) || tx == t_RFRAC) { gel(y,n) = gcopy(x); return y; }
3136 3563 : switch(tx)
3137 : {
3138 56 : case t_POL:
3139 56 : lx = lg(x); a = lx-2;
3140 56 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x -= a-imax;
3141 224 : for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,lx-i));
3142 56 : return y;
3143 3248 : case t_SER:
3144 3248 : a = lg(x)-2; x++;
3145 3248 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3146 131425 : for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i));
3147 3248 : return y;
3148 28 : case t_QFB:
3149 28 : a = lg(x)-2; /* remove discriminant */
3150 28 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3151 112 : for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i));
3152 28 : return y;
3153 28 : case t_VEC: case t_COL:
3154 28 : a = lg(x)-1;
3155 28 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3156 84 : for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i));
3157 28 : return y;
3158 63 : case t_LIST:
3159 63 : if (list_typ(x) == t_LIST_MAP) pari_err_TYPE("gtovec",x);
3160 56 : x = list_data(x); a = x? lg(x)-1: 0;
3161 56 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3162 252 : for (i=1; i<=imax; i++) gel(y0,i) = gcopy(gel(x,i));
3163 56 : return y;
3164 56 : case t_STR:
3165 : {
3166 56 : char *s = GSTR(x);
3167 56 : a = strlen(s);
3168 56 : y0 = init_vectopre(a, n, y, &imax); s--; if (imax == n) s += a-imax;
3169 224 : for (i=1; i<=imax; i++) gel(y,i) = chartoGENstr(s[i]);
3170 56 : return y;
3171 : }
3172 28 : case t_VECSMALL:
3173 28 : a = lg(x)-1;
3174 28 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3175 84 : for (i=1; i<=imax; i++) gel(y0,i) = stoi(x[i]);
3176 28 : return y;
3177 56 : default: pari_err_TYPE("gtovec",x);
3178 : return NULL; /*LCOV_EXCL_LINE*/
3179 : }
3180 : }
3181 : GEN
3182 123206 : gtovec0(GEN x, long n)
3183 : {
3184 123206 : if (!n) return gtovec(x);
3185 4711 : if (n > 0) return gtovecpost(x, n);
3186 3619 : return gtovecpre(x, -n);
3187 : }
3188 :
3189 : GEN
3190 118985 : gtovec(GEN x)
3191 : {
3192 118985 : long i, lx, tx = typ(x);
3193 : GEN y;
3194 :
3195 118985 : if (is_scalar_t(tx)) return mkveccopy(x);
3196 118852 : switch(tx)
3197 : {
3198 15232 : case t_POL:
3199 15232 : lx=lg(x); y=cgetg(lx-1,t_VEC);
3200 1498371 : for (i=1; i<=lx-2; i++) gel(y,i) = gcopy(gel(x,lx-i));
3201 15232 : return y;
3202 385 : case t_SER:
3203 385 : lx=lg(x); y=cgetg(lx-1,t_VEC); x++;
3204 12264 : for (i=1; i<=lx-2; i++) gel(y,i) = gcopy(gel(x,i));
3205 385 : return y;
3206 28 : case t_RFRAC: return mkveccopy(x);
3207 70049 : case t_QFB:
3208 70049 : retmkvec3(icopy(gel(x,1)), icopy(gel(x,2)), icopy(gel(x,3)));
3209 31066 : case t_VEC: case t_COL: case t_MAT:
3210 31066 : lx=lg(x); y=cgetg(lx,t_VEC);
3211 1662150 : for (i=1; i<lx; i++) gel(y,i) = gcopy(gel(x,i));
3212 31066 : return y;
3213 426 : case t_LIST:
3214 426 : if (list_typ(x) == t_LIST_MAP) return mapdomain(x);
3215 412 : x = list_data(x); lx = x? lg(x): 1;
3216 412 : y = cgetg(lx, t_VEC);
3217 20373 : for (i=1; i<lx; i++) gel(y,i) = gcopy(gel(x,i));
3218 412 : return y;
3219 105 : case t_STR:
3220 : {
3221 105 : char *s = GSTR(x);
3222 105 : lx = strlen(s)+1; y = cgetg(lx, t_VEC);
3223 105 : s--;
3224 340239 : for (i=1; i<lx; i++) gel(y,i) = chartoGENstr(s[i]);
3225 105 : return y;
3226 : }
3227 1498 : case t_VECSMALL:
3228 1498 : return vecsmall_to_vec(x);
3229 63 : case t_ERROR:
3230 63 : lx=lg(x); y = cgetg(lx,t_VEC);
3231 63 : gel(y,1) = errname(x);
3232 168 : for (i=2; i<lx; i++) gel(y,i) = gcopy(gel(x,i));
3233 63 : return y;
3234 0 : default: pari_err_TYPE("gtovec",x);
3235 : return NULL; /*LCOV_EXCL_LINE*/
3236 : }
3237 : }
3238 :
3239 : GEN
3240 308 : gtovecrev0(GEN x, long n)
3241 : {
3242 308 : GEN y = gtovec0(x, -n);
3243 280 : vecreverse_inplace(y);
3244 280 : return y;
3245 : }
3246 : GEN
3247 0 : gtovecrev(GEN x) { return gtovecrev0(x, 0); }
3248 :
3249 : GEN
3250 3808 : gtocol0(GEN x, long n)
3251 : {
3252 : GEN y;
3253 3808 : if (!n) return gtocol(x);
3254 3458 : y = gtovec0(x, n);
3255 3402 : settyp(y, t_COL); return y;
3256 : }
3257 : GEN
3258 350 : gtocol(GEN x)
3259 : {
3260 : long lx, tx, i, j, h;
3261 : GEN y;
3262 350 : tx = typ(x);
3263 350 : if (tx != t_MAT) { y = gtovec(x); settyp(y, t_COL); return y; }
3264 14 : lx = lg(x); if (lx == 1) return cgetg(1, t_COL);
3265 14 : h = lgcols(x); y = cgetg(h, t_COL);
3266 42 : for (i = 1 ; i < h; i++) {
3267 28 : gel(y,i) = cgetg(lx, t_VEC);
3268 112 : for (j = 1; j < lx; j++) gmael(y,i,j) = gcopy(gcoeff(x,i,j));
3269 : }
3270 14 : return y;
3271 : }
3272 :
3273 : GEN
3274 294 : gtocolrev0(GEN x, long n)
3275 : {
3276 294 : GEN y = gtocol0(x, -n);
3277 266 : long ly = lg(y), lim = ly>>1, i;
3278 763 : for (i = 1; i <= lim; i++) swap(gel(y,i), gel(y,ly-i));
3279 266 : return y;
3280 : }
3281 : GEN
3282 0 : gtocolrev(GEN x) { return gtocolrev0(x, 0); }
3283 :
3284 : static long
3285 19047 : Itos(GEN x)
3286 : {
3287 19047 : if (typ(x) != t_INT) pari_err_TYPE("vectosmall",x);
3288 19047 : return itos(x);
3289 : }
3290 :
3291 : static GEN
3292 98 : gtovecsmallpost(GEN x, long n)
3293 : {
3294 : long i, imax, lx;
3295 98 : GEN y = zero_Flv(n);
3296 :
3297 98 : switch(typ(x))
3298 : {
3299 7 : case t_INT:
3300 7 : y[1] = itos(x); return y;
3301 14 : case t_POL:
3302 14 : lx=lg(x); imax = minss(lx-2, n);
3303 56 : for (i=1; i<=imax; i++) y[i] = Itos(gel(x,lx-i));
3304 14 : return y;
3305 7 : case t_SER:
3306 7 : lx=lg(x); imax = minss(lx-2, n); x++;
3307 21 : for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i));
3308 7 : return y;
3309 7 : case t_VEC: case t_COL:
3310 7 : lx=lg(x); imax = minss(lx-1, n);
3311 21 : for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i));
3312 7 : return y;
3313 14 : case t_LIST:
3314 14 : x = list_data(x); lx = x? lg(x): 1;
3315 14 : imax = minss(lx-1, n);
3316 63 : for (i=1; i<=imax; i++) y[i] = Itos(gel(x,i));
3317 14 : return y;
3318 7 : case t_VECSMALL:
3319 7 : lx=lg(x);
3320 7 : imax = minss(lx-1, n);
3321 21 : for (i=1; i<=imax; i++) y[i] = x[i];
3322 7 : return y;
3323 14 : case t_STR:
3324 : {
3325 14 : unsigned char *s = (unsigned char*)GSTR(x);
3326 14 : imax = minss(strlen((const char *)s), n); s--;
3327 56 : for (i=1; i<=imax; i++) y[i] = (long)s[i];
3328 14 : return y;
3329 : }
3330 28 : default: pari_err_TYPE("gtovecsmall",x);
3331 : return NULL; /*LCOV_EXCL_LINE*/
3332 : }
3333 : }
3334 : static GEN
3335 98 : gtovecsmallpre(GEN x, long n)
3336 : {
3337 98 : GEN y = zero_Flv(n), y0;
3338 : long a, i, imax, lx;
3339 :
3340 98 : switch(typ(x))
3341 : {
3342 7 : case t_INT:
3343 7 : y[n] = itos(x); return y;
3344 14 : case t_POL:
3345 14 : lx = lg(x); a = lx-2;
3346 14 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x -= a-imax;
3347 56 : for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,lx-i));
3348 14 : return y;
3349 7 : case t_SER:
3350 7 : a = lg(x)-2; x++;
3351 7 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3352 21 : for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i));
3353 7 : return y;
3354 7 : case t_VEC: case t_COL:
3355 7 : a = lg(x)-1;
3356 7 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3357 21 : for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i));
3358 7 : return y;
3359 14 : case t_LIST:
3360 14 : x = list_data(x); a = x? lg(x)-1: 0;
3361 14 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3362 63 : for (i=1; i<=imax; i++) y0[i] = Itos(gel(x,i));
3363 14 : return y;
3364 7 : case t_VECSMALL:
3365 7 : a = lg(x)-1;
3366 7 : y0 = init_vectopre(a, n, y, &imax); if (imax == n) x += a-imax;
3367 21 : for (i=1; i<=imax; i++) y0[i] = x[i];
3368 7 : return y;
3369 14 : case t_STR:
3370 : {
3371 14 : unsigned char *s = (unsigned char*)GSTR(x);
3372 14 : a = strlen((const char *)s);
3373 14 : y0 = init_vectopre(a, n, y, &imax); s--; if (imax == n) s += a-imax;
3374 56 : for (i=1; i<=imax; i++) y0[i] = (long)s[i];
3375 14 : return y;
3376 : }
3377 28 : default: pari_err_TYPE("gtovecsmall",x);
3378 : return NULL; /*LCOV_EXCL_LINE*/
3379 : }
3380 : }
3381 :
3382 : GEN
3383 7777 : gtovecsmall0(GEN x, long n)
3384 : {
3385 7777 : if (!n) return gtovecsmall(x);
3386 196 : if (n > 0) return gtovecsmallpost(x, n);
3387 98 : return gtovecsmallpre(x, -n);
3388 : }
3389 :
3390 : GEN
3391 19019 : gtovecsmall(GEN x)
3392 : {
3393 : GEN V;
3394 : long l, i;
3395 :
3396 19019 : switch(typ(x))
3397 : {
3398 112 : case t_INT: return mkvecsmall(itos(x));
3399 28 : case t_STR:
3400 : {
3401 28 : unsigned char *s = (unsigned char*)GSTR(x);
3402 28 : l = strlen((const char *)s);
3403 28 : V = cgetg(l+1, t_VECSMALL);
3404 28 : s--;
3405 1953 : for (i=1; i<=l; i++) V[i] = (long)s[i];
3406 28 : return V;
3407 : }
3408 13139 : case t_VECSMALL: return leafcopy(x);
3409 14 : case t_LIST:
3410 14 : x = list_data(x);
3411 14 : if (!x) return cgetg(1, t_VECSMALL);
3412 : /* fall through */
3413 : case t_VEC: case t_COL:
3414 5691 : l = lg(x); V = cgetg(l,t_VECSMALL);
3415 24437 : for(i=1; i<l; i++) V[i] = Itos(gel(x,i));
3416 5691 : return V;
3417 14 : case t_POL:
3418 14 : l = lg(x); V = cgetg(l-1,t_VECSMALL);
3419 63 : for (i=1; i<=l-2; i++) V[i] = Itos(gel(x,l-i));
3420 14 : return V;
3421 7 : case t_SER:
3422 7 : l = lg(x); V = cgetg(l-1,t_VECSMALL); x++;
3423 21 : for (i=1; i<=l-2; i++) V[i] = Itos(gel(x,i));
3424 7 : return V;
3425 28 : default:
3426 28 : pari_err_TYPE("vectosmall",x);
3427 : return NULL; /* LCOV_EXCL_LINE */
3428 : }
3429 : }
3430 :
3431 : GEN
3432 327 : compo(GEN x, long n)
3433 : {
3434 327 : long tx = typ(x);
3435 327 : ulong l, lx = (ulong)lg(x);
3436 :
3437 327 : if (!is_recursive_t(tx))
3438 : {
3439 63 : if (tx == t_VECSMALL)
3440 : {
3441 21 : if (n < 1) pari_err_COMPONENT("", "<", gen_1, stoi(n));
3442 21 : if ((ulong)n >= lx) pari_err_COMPONENT("", ">", utoi(lx-1), stoi(n));
3443 7 : return stoi(x[n]);
3444 : }
3445 42 : pari_err_TYPE("component [leaf]", x);
3446 : }
3447 264 : if (n < 1) pari_err_COMPONENT("", "<", gen_1, stoi(n));
3448 257 : if (tx == t_LIST) {
3449 28 : x = list_data(x); tx = t_VEC;
3450 28 : lx = (ulong)(x? lg(x): 1);
3451 : }
3452 257 : l = (ulong)lontyp[tx] + (ulong)n-1; /* beware overflow */
3453 257 : if (l >= lx) pari_err_COMPONENT("", ">", utoi(lx-lontyp[tx]), stoi(n));
3454 173 : return gcopy(gel(x,l));
3455 : }
3456 :
3457 : /* assume x a t_POL */
3458 : static GEN
3459 2598291 : _polcoef(GEN x, long n, long v)
3460 : {
3461 2598291 : long i, w, lx = lg(x), dx = lx-3;
3462 : GEN z;
3463 2598291 : if (dx < 0) return gen_0;
3464 2020315 : if (v < 0 || v == (w=varn(x)))
3465 1341335 : return (n < 0 || n > dx)? gen_0: gel(x,n+2);
3466 678980 : if (varncmp(w,v) > 0) return n? gen_0: x;
3467 : /* w < v */
3468 678140 : z = cgetg(lx, t_POL); z[1] = x[1];
3469 2716116 : for (i = 2; i < lx; i++) gel(z,i) = polcoef_i(gel(x,i), n, v);
3470 678140 : z = normalizepol_lg(z, lx);
3471 678141 : switch(lg(z))
3472 : {
3473 27956 : case 2: z = gen_0; break;
3474 410944 : case 3: z = gel(z,2); break;
3475 : }
3476 678141 : return z;
3477 : }
3478 :
3479 : /* assume x a t_SER */
3480 : static GEN
3481 111902 : _sercoef(GEN x, long n, long v)
3482 : {
3483 111902 : long i, w = varn(x), lx = lg(x), dx = lx-3, N;
3484 : GEN z;
3485 111902 : if (v < 0) v = w;
3486 111902 : N = v == w? n - valser(x): n;
3487 111902 : if (dx < 0)
3488 : {
3489 21 : if (N >= 0) pari_err_DOMAIN("polcoef", "t_SER", "=", x, x);
3490 14 : return gen_0;
3491 : }
3492 111881 : if (v == w)
3493 : {
3494 111839 : if (!dx && !signe(x) && !isinexact(gel(x,2))) dx = -1;
3495 111839 : if (N > dx)
3496 28 : pari_err_DOMAIN("polcoef", "degree", ">", stoi(dx+valser(x)), stoi(n));
3497 111811 : return (N < 0)? gen_0: gel(x,N+2);
3498 : }
3499 42 : if (varncmp(w,v) > 0) return N? gen_0: x;
3500 : /* w < v */
3501 28 : z = cgetg(lx, t_SER); z[1] = x[1];
3502 91 : for (i = 2; i < lx; i++) gel(z,i) = polcoef_i(gel(x,i), n, v);
3503 28 : return normalizeser(z);
3504 : }
3505 :
3506 : /* assume x a t_RFRAC(n) */
3507 : static GEN
3508 21 : _rfraccoef(GEN x, long n, long v)
3509 : {
3510 21 : GEN P,Q, p = gel(x,1), q = gel(x,2);
3511 21 : long vp = gvar(p), vq = gvar(q);
3512 21 : if (v < 0) v = varncmp(vp, vq) < 0? vp: vq;
3513 21 : P = (vp == v)? p: swap_vars(p, v);
3514 21 : Q = (vq == v)? q: swap_vars(q, v);
3515 21 : if (!RgX_is_monomial(Q)) pari_err_TYPE("polcoef", x);
3516 21 : n += degpol(Q);
3517 21 : return gdiv(_polcoef(P, n, v), leading_coeff(Q));
3518 : }
3519 :
3520 : GEN
3521 3605368 : polcoef_i(GEN x, long n, long v)
3522 : {
3523 3605368 : long tx = typ(x);
3524 3605368 : switch(tx)
3525 : {
3526 2598270 : case t_POL: return _polcoef(x,n,v);
3527 111902 : case t_SER: return _sercoef(x,n,v);
3528 21 : case t_RFRAC: return _rfraccoef(x,n,v);
3529 : }
3530 895175 : if (!is_scalar_t(tx)) pari_err_TYPE("polcoef", x);
3531 894980 : return n? gen_0: x;
3532 : }
3533 :
3534 : /* with respect to the main variable if v<0, with respect to the variable v
3535 : * otherwise. v ignored if x is not a polynomial/series. */
3536 : GEN
3537 727580 : polcoef(GEN x, long n, long v)
3538 : {
3539 727580 : pari_sp av = avma;
3540 727580 : x = polcoef_i(x,n,v);
3541 727349 : if (x == gen_0) return x;
3542 130725 : return (avma == av)? gcopy(x): gerepilecopy(av, x);
3543 : }
3544 :
3545 : static GEN
3546 242315 : vecdenom(GEN v, long imin, long imax)
3547 : {
3548 242315 : long i = imin;
3549 : GEN s;
3550 242315 : if (imin > imax) return gen_1;
3551 242315 : s = denom_i(gel(v,i));
3552 2104290 : for (i++; i<=imax; i++)
3553 : {
3554 1861975 : GEN t = denom_i(gel(v,i));
3555 1861975 : if (t != gen_1) s = glcm(s,t);
3556 : }
3557 242315 : return s;
3558 : }
3559 : static GEN denompol(GEN x, long v);
3560 : static GEN
3561 14 : vecdenompol(GEN v, long imin, long imax, long vx)
3562 : {
3563 14 : long i = imin;
3564 : GEN s;
3565 14 : if (imin > imax) return gen_1;
3566 14 : s = denompol(gel(v,i), vx);
3567 14 : for (i++; i<=imax; i++)
3568 : {
3569 0 : GEN t = denompol(gel(v,i), vx);
3570 0 : if (t != gen_1) s = glcm(s,t);
3571 : }
3572 14 : return s;
3573 : }
3574 : GEN
3575 12236169 : denom_i(GEN x)
3576 : {
3577 12236169 : switch(typ(x))
3578 : {
3579 4647592 : case t_INT:
3580 : case t_REAL:
3581 : case t_INTMOD:
3582 : case t_FFELT:
3583 : case t_PADIC:
3584 : case t_SER:
3585 4647592 : case t_VECSMALL: return gen_1;
3586 81559 : case t_FRAC: return gel(x,2);
3587 294 : case t_COMPLEX: return vecdenom(x,1,2);
3588 69069 : case t_QUAD: return vecdenom(x,2,3);
3589 42 : case t_POLMOD: return denom_i(gel(x,2));
3590 7263674 : case t_RFRAC: return gel(x,2);
3591 973 : case t_POL: return pol_1(varn(x));
3592 172952 : case t_VEC: case t_COL: case t_MAT: return vecdenom(x, 1, lg(x)-1);
3593 : }
3594 14 : pari_err_TYPE("denom",x);
3595 : return NULL; /* LCOV_EXCL_LINE */
3596 : }
3597 : /* v has lower (or equal) priority as x's main variable */
3598 : static GEN
3599 119 : denompol(GEN x, long v)
3600 : {
3601 119 : long vx, tx = typ(x);
3602 119 : if (is_scalar_t(tx)) return gen_1;
3603 105 : switch(typ(x))
3604 : {
3605 14 : case t_SER:
3606 14 : if (varn(x) != v) return x;
3607 14 : vx = valser(x); return vx < 0? pol_xn(-vx, v): pol_1(v);
3608 63 : case t_RFRAC: x = gel(x,2); return varn(x) == v? x: pol_1(v);
3609 14 : case t_POL: return pol_1(v);
3610 14 : case t_VEC: case t_COL: case t_MAT: return vecdenompol(x, 1, lg(x)-1, v);
3611 : }
3612 0 : pari_err_TYPE("denom",x);
3613 : return NULL; /* LCOV_EXCL_LINE */
3614 : }
3615 : GEN
3616 228909 : denom(GEN x) { pari_sp av = avma; return gerepilecopy(av, denom_i(x)); }
3617 :
3618 : static GEN
3619 287 : denominator_v(GEN x, long v)
3620 : {
3621 287 : long v0 = gvar(x);
3622 : GEN d;
3623 287 : if (v0 == NO_VARIABLE || varncmp(v0,v) > 0) return pol_1(v);
3624 105 : if (v0 != v) { v0 = fetch_var_higher(); x = gsubst(x, v, pol_x(v0)); }
3625 105 : d = denompol(x, v0);
3626 105 : if (v0 != v) { d = gsubst(d, v0, pol_x(v)); (void)delete_var(); }
3627 105 : return d;
3628 : }
3629 : GEN
3630 128149 : denominator(GEN x, GEN D)
3631 : {
3632 128149 : pari_sp av = avma;
3633 : GEN d;
3634 128149 : if (!D) return denom(x);
3635 280 : if (isint1(D))
3636 : {
3637 140 : d = Q_denom_safe(x);
3638 140 : if (!d) { set_avma(av); return gen_1; }
3639 105 : return gerepilecopy(av, d);
3640 : }
3641 140 : if (!gequalX(D)) pari_err_TYPE("denominator", D);
3642 140 : return gerepileupto(av, denominator_v(x, varn(D)));
3643 : }
3644 : GEN
3645 8925 : numerator(GEN x, GEN D)
3646 : {
3647 8925 : pari_sp av = avma;
3648 : long v;
3649 8925 : if (!D) return numer(x);
3650 294 : if (isint1(D)) return Q_remove_denom(x,NULL);
3651 154 : if (!gequalX(D)) pari_err_TYPE("numerator", D);
3652 154 : v = varn(D); /* optimization */
3653 154 : if (typ(x) == t_RFRAC && varn(gel(x,2)) == v) return gcopy(gel(x,1));
3654 147 : return gerepileupto(av, gmul(x, denominator_v(x,v)));
3655 : }
3656 : GEN
3657 131005 : content0(GEN x, GEN D)
3658 : {
3659 131005 : pari_sp av = avma;
3660 : long v, v0;
3661 : GEN d;
3662 131005 : if (!D) return content(x);
3663 294 : if (isint1(D))
3664 : {
3665 140 : d = Q_content_safe(x);
3666 140 : return d? d: gen_1;
3667 : }
3668 154 : if (!gequalX(D)) pari_err_TYPE("content", D);
3669 154 : v = varn(D);
3670 154 : v0 = gvar(x); if (v0 == NO_VARIABLE) return gen_1;
3671 56 : if (varncmp(v0,v) > 0)
3672 : {
3673 0 : v0 = gvar2(x);
3674 0 : return v0 == NO_VARIABLE? gen_1: pol_1(v0);
3675 : }
3676 56 : if (v0 != v) { v0 = fetch_var_higher(); x = gsubst(x, v, pol_x(v0)); }
3677 56 : d = content(x);
3678 : /* gsubst is needed because of content([x]) = x */
3679 56 : if (v0 != v) { d = gsubst(d, v0, pol_x(v)); (void)delete_var(); }
3680 56 : return gerepileupto(av, d);
3681 : }
3682 :
3683 : GEN
3684 8979619 : numer_i(GEN x)
3685 : {
3686 8979619 : switch(typ(x))
3687 : {
3688 1717863 : case t_INT:
3689 : case t_REAL:
3690 : case t_INTMOD:
3691 : case t_FFELT:
3692 : case t_PADIC:
3693 : case t_SER:
3694 : case t_VECSMALL:
3695 1717863 : case t_POL: return x;
3696 28 : case t_POLMOD: return mkpolmod(numer_i(gel(x,2)), gel(x,1));
3697 7261539 : case t_FRAC:
3698 7261539 : case t_RFRAC: return gel(x,1);
3699 175 : case t_COMPLEX:
3700 : case t_QUAD:
3701 : case t_VEC:
3702 : case t_COL:
3703 175 : case t_MAT: return gmul(denom_i(x),x);
3704 : }
3705 14 : pari_err_TYPE("numer",x);
3706 : return NULL; /* LCOV_EXCL_LINE */
3707 : }
3708 : GEN
3709 8631 : numer(GEN x) { pari_sp av = avma; return gerepilecopy(av, numer_i(x)); }
3710 :
3711 : /* Lift only intmods if v does not occur in x, lift with respect to main
3712 : * variable of x if v < 0, with respect to variable v otherwise */
3713 : GEN
3714 2473702 : lift0(GEN x, long v)
3715 : {
3716 : GEN y;
3717 :
3718 2473702 : switch(typ(x))
3719 : {
3720 30380 : case t_INT: return icopy(x);
3721 2320808 : case t_INTMOD: return v < 0? icopy(gel(x,2)): gcopy(x);
3722 92169 : case t_POLMOD:
3723 92169 : if (v < 0 || v == varn(gel(x,1))) return gcopy(gel(x,2));
3724 14 : y = cgetg(3, t_POLMOD);
3725 14 : gel(y,1) = lift0(gel(x,1),v);
3726 14 : gel(y,2) = lift0(gel(x,2),v); return y;
3727 665 : case t_PADIC: return v < 0? padic_to_Q(x): gcopy(x);
3728 8715 : case t_POL:
3729 41405 : pari_APPLY_pol(lift0(gel(x,i), v));
3730 56 : case t_SER:
3731 56 : if (ser_isexactzero(x))
3732 : {
3733 14 : if (lg(x) == 2) return gcopy(x);
3734 14 : y = scalarser(lift0(gel(x,2),v), varn(x), 1);
3735 14 : setvalser(y, valser(x)); return y;
3736 : }
3737 434 : pari_APPLY_ser(lift0(gel(x,i), v));
3738 20720 : case t_COMPLEX: case t_QUAD: case t_RFRAC:
3739 : case t_VEC: case t_COL: case t_MAT:
3740 221970 : pari_APPLY_same(lift0(gel(x,i), v));
3741 189 : default: return gcopy(x);
3742 : }
3743 : }
3744 : /* same as lift, shallow */
3745 : GEN
3746 616809 : lift_shallow(GEN x)
3747 : {
3748 : GEN y;
3749 616809 : switch(typ(x))
3750 : {
3751 205078 : case t_INTMOD: case t_POLMOD: return gel(x,2);
3752 476 : case t_PADIC: return padic_to_Q(x);
3753 0 : case t_SER:
3754 0 : if (ser_isexactzero(x))
3755 : {
3756 0 : if (lg(x) == 2) return x;
3757 0 : y = scalarser(lift_shallow(gel(x,2)), varn(x), 1);
3758 0 : setvalser(y, valser(x)); return y;
3759 : }
3760 0 : pari_APPLY_ser(lift_shallow(gel(x,i)));
3761 50645 : case t_POL:
3762 288775 : pari_APPLY_pol(lift_shallow(gel(x,i)));
3763 11228 : case t_COMPLEX: case t_QUAD: case t_RFRAC:
3764 : case t_VEC: case t_COL: case t_MAT:
3765 275751 : pari_APPLY_same(lift_shallow(gel(x,i)));
3766 349382 : default: return x;
3767 : }
3768 : }
3769 : GEN
3770 2156870 : lift(GEN x) { return lift0(x,-1); }
3771 :
3772 : GEN
3773 2003435 : liftall_shallow(GEN x)
3774 : {
3775 : GEN y;
3776 2003435 : switch(typ(x))
3777 : {
3778 533778 : case t_INTMOD: return gel(x,2);
3779 547519 : case t_POLMOD:
3780 547519 : return liftall_shallow(gel(x,2));
3781 581 : case t_PADIC: return padic_to_Q(x);
3782 555912 : case t_POL:
3783 1356460 : pari_APPLY_pol(liftall_shallow(gel(x,i)));
3784 7 : case t_SER:
3785 7 : if (ser_isexactzero(x))
3786 : {
3787 0 : if (lg(x) == 2) return x;
3788 0 : y = scalarser(liftall_shallow(gel(x,2)), varn(x), 1);
3789 0 : setvalser(y, valser(x)); return y;
3790 : }
3791 35 : pari_APPLY_ser(liftall_shallow(gel(x,i)));
3792 132762 : case t_COMPLEX: case t_QUAD: case t_RFRAC:
3793 : case t_VEC: case t_COL: case t_MAT:
3794 760515 : pari_APPLY_same(liftall_shallow(gel(x,i)));
3795 232876 : default: return x;
3796 : }
3797 : }
3798 : GEN
3799 26243 : liftall(GEN x)
3800 26243 : { pari_sp av = avma; return gerepilecopy(av, liftall_shallow(x)); }
3801 :
3802 : GEN
3803 546 : liftint_shallow(GEN x)
3804 : {
3805 : GEN y;
3806 546 : switch(typ(x))
3807 : {
3808 266 : case t_INTMOD: return gel(x,2);
3809 28 : case t_PADIC: return padic_to_Q(x);
3810 21 : case t_POL:
3811 70 : pari_APPLY_pol(liftint_shallow(gel(x,i)));
3812 14 : case t_SER:
3813 14 : if (ser_isexactzero(x))
3814 : {
3815 7 : if (lg(x) == 2) return x;
3816 7 : y = scalarser(liftint_shallow(gel(x,2)), varn(x), 1);
3817 7 : setvalser(y, valser(x)); return y;
3818 : }
3819 35 : pari_APPLY_ser(liftint_shallow(gel(x,i)));
3820 161 : case t_POLMOD: case t_COMPLEX: case t_QUAD: case t_RFRAC:
3821 : case t_VEC: case t_COL: case t_MAT:
3822 504 : pari_APPLY_same(liftint_shallow(gel(x,i)));
3823 56 : default: return x;
3824 : }
3825 : }
3826 : GEN
3827 119 : liftint(GEN x)
3828 119 : { pari_sp av = avma; return gerepilecopy(av, liftint_shallow(x)); }
3829 :
3830 : GEN
3831 21702258 : liftpol_shallow(GEN x)
3832 : {
3833 : GEN y;
3834 21702258 : switch(typ(x))
3835 : {
3836 2146346 : case t_POLMOD:
3837 2146346 : return liftpol_shallow(gel(x,2));
3838 2954140 : case t_POL:
3839 12211974 : pari_APPLY_pol(liftpol_shallow(gel(x,i)));
3840 7 : case t_SER:
3841 7 : if (ser_isexactzero(x))
3842 : {
3843 0 : if (lg(x) == 2) return x;
3844 0 : y = scalarser(liftpol(gel(x,2)), varn(x), 1);
3845 0 : setvalser(y, valser(x)); return y;
3846 : }
3847 35 : pari_APPLY_ser(liftpol_shallow(gel(x,i)));
3848 135891 : case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
3849 964803 : pari_APPLY_same(liftpol_shallow(gel(x,i)));
3850 16465874 : default: return x;
3851 : }
3852 : }
3853 : GEN
3854 5726 : liftpol(GEN x)
3855 5726 : { pari_sp av = avma; return gerepilecopy(av, liftpol_shallow(x)); }
3856 :
3857 : static GEN
3858 42518 : centerliftii(GEN x, GEN y)
3859 : {
3860 42518 : pari_sp av = avma;
3861 42518 : long i = cmpii(shifti(x,1), y);
3862 42518 : set_avma(av); return (i > 0)? subii(x,y): icopy(x);
3863 : }
3864 :
3865 : /* see lift0 */
3866 : GEN
3867 707 : centerlift0(GEN x, long v)
3868 707 : { return v < 0? centerlift(x): lift0(x,v); }
3869 : GEN
3870 60473 : centerlift(GEN x)
3871 : {
3872 : long v;
3873 : GEN y;
3874 60473 : switch(typ(x))
3875 : {
3876 784 : case t_INT: return icopy(x);
3877 784 : case t_INTMOD: return centerliftii(gel(x,2), gel(x,1));
3878 7 : case t_POLMOD: return gcopy(gel(x,2));
3879 1554 : case t_POL:
3880 9912 : pari_APPLY_pol(centerlift(gel(x,i)));
3881 7 : case t_SER:
3882 7 : if (ser_isexactzero(x)) return lift(x);
3883 35 : pari_APPLY_ser(centerlift(gel(x,i)));
3884 5551 : case t_COMPLEX: case t_QUAD: case t_RFRAC:
3885 : case t_VEC: case t_COL: case t_MAT:
3886 56210 : pari_APPLY_same(centerlift(gel(x,i)));
3887 51779 : case t_PADIC:
3888 51779 : if (!signe(gel(x,4))) return gen_0;
3889 41734 : v = valp(x);
3890 41734 : if (v>=0)
3891 : { /* here p^v is an integer */
3892 41727 : GEN z = centerliftii(gel(x,4), gel(x,3));
3893 : pari_sp av;
3894 41727 : if (!v) return z;
3895 27027 : av = avma; y = powiu(gel(x,2),v);
3896 27027 : return gerepileuptoint(av, mulii(y,z));
3897 : }
3898 7 : y = cgetg(3,t_FRAC);
3899 7 : gel(y,1) = centerliftii(gel(x,4), gel(x,3));
3900 7 : gel(y,2) = powiu(gel(x,2),-v);
3901 7 : return y;
3902 7 : default: return gcopy(x);
3903 : }
3904 : }
3905 :
3906 : /*******************************************************************/
3907 : /* */
3908 : /* REAL & IMAGINARY PARTS */
3909 : /* */
3910 : /*******************************************************************/
3911 :
3912 : static GEN
3913 202934032 : op_ReIm(GEN f(GEN), GEN x)
3914 : {
3915 202934032 : switch(typ(x))
3916 : {
3917 591819426 : case t_POL: pari_APPLY_pol(f(gel(x,i)));
3918 64463 : case t_SER: pari_APPLY_ser(f(gel(x,i)));
3919 42 : case t_RFRAC: {
3920 42 : pari_sp av = avma;
3921 42 : GEN n, d, dxb = conj_i(gel(x,2));
3922 42 : n = gmul(gel(x,1), dxb);
3923 42 : d = gmul(gel(x,2), dxb);
3924 42 : return gerepileupto(av, gdiv(f(n), d));
3925 : }
3926 19832729 : case t_VEC: case t_COL: case t_MAT: pari_APPLY_same(f(gel(x, i)));
3927 : }
3928 12 : pari_err_TYPE("greal/gimag",x);
3929 : return NULL; /* LCOV_EXCL_LINE */
3930 : }
3931 :
3932 : GEN
3933 320453157 : real_i(GEN x)
3934 : {
3935 320453157 : switch(typ(x))
3936 : {
3937 171851336 : case t_INT: case t_REAL: case t_FRAC:
3938 171851336 : return x;
3939 44506567 : case t_COMPLEX:
3940 44506567 : return gel(x,1);
3941 0 : case t_QUAD:
3942 0 : return gel(x,2);
3943 : }
3944 104095254 : return op_ReIm(real_i,x);
3945 : }
3946 : GEN
3947 298186521 : imag_i(GEN x)
3948 : {
3949 298186521 : switch(typ(x))
3950 : {
3951 166525474 : case t_INT: case t_REAL: case t_FRAC:
3952 166525474 : return gen_0;
3953 32889576 : case t_COMPLEX:
3954 32889576 : return gel(x,2);
3955 0 : case t_QUAD:
3956 0 : return gel(x,3);
3957 : }
3958 98771471 : return op_ReIm(imag_i,x);
3959 : }
3960 : GEN
3961 7014 : greal(GEN x)
3962 : {
3963 7014 : switch(typ(x))
3964 : {
3965 707 : case t_INT: case t_REAL:
3966 707 : return mpcopy(x);
3967 :
3968 7 : case t_FRAC:
3969 7 : return gcopy(x);
3970 :
3971 6055 : case t_COMPLEX:
3972 6055 : return gcopy(gel(x,1));
3973 :
3974 7 : case t_QUAD:
3975 7 : return gcopy(gel(x,2));
3976 : }
3977 238 : return op_ReIm(greal,x);
3978 : }
3979 : GEN
3980 29344 : gimag(GEN x)
3981 : {
3982 29344 : switch(typ(x))
3983 : {
3984 525 : case t_INT: case t_REAL: case t_FRAC:
3985 525 : return gen_0;
3986 :
3987 28203 : case t_COMPLEX:
3988 28203 : return gcopy(gel(x,2));
3989 :
3990 7 : case t_QUAD:
3991 7 : return gcopy(gel(x,3));
3992 : }
3993 609 : return op_ReIm(gimag,x);
3994 : }
3995 :
3996 : /* return Re(x * y), x and y scalars */
3997 : GEN
3998 15696170 : mulreal(GEN x, GEN y)
3999 : {
4000 15696170 : if (typ(x) == t_COMPLEX)
4001 : {
4002 15552447 : if (typ(y) == t_COMPLEX)
4003 : {
4004 14329682 : pari_sp av = avma;
4005 14329682 : GEN a = gmul(gel(x,1), gel(y,1));
4006 14329681 : GEN b = gmul(gel(x,2), gel(y,2));
4007 14329677 : return gerepileupto(av, gsub(a, b));
4008 : }
4009 1222765 : x = gel(x,1);
4010 : }
4011 : else
4012 143723 : if (typ(y) == t_COMPLEX) y = gel(y,1);
4013 1366488 : return gmul(x,y);
4014 : }
4015 : /* Compute Re(x * y), x and y matrices of compatible dimensions
4016 : * assume scalar entries */
4017 : GEN
4018 0 : RgM_mulreal(GEN x, GEN y)
4019 : {
4020 0 : long i, j, k, l, lx = lg(x), ly = lg(y);
4021 0 : GEN z = cgetg(ly,t_MAT);
4022 0 : l = (lx == 1)? 1: lgcols(x);
4023 0 : for (j=1; j<ly; j++)
4024 : {
4025 0 : GEN zj = cgetg(l,t_COL), yj = gel(y,j);
4026 0 : gel(z,j) = zj;
4027 0 : for (i=1; i<l; i++)
4028 : {
4029 0 : pari_sp av = avma;
4030 0 : GEN c = mulreal(gcoeff(x,i,1),gel(yj,1));
4031 0 : for (k=2; k<lx; k++) c = gadd(c, mulreal(gcoeff(x,i,k),gel(yj,k)));
4032 0 : gel(zj, i) = gerepileupto(av, c);
4033 : }
4034 : }
4035 0 : return z;
4036 : }
4037 :
4038 : /* Compute Re(x * y), symmetric result, x and y vectors of compatible
4039 : * dimensions; assume scalar entries */
4040 : GEN
4041 21630 : RgC_RgV_mulrealsym(GEN x, GEN y)
4042 : {
4043 21630 : long i, j, l = lg(x);
4044 21630 : GEN q = cgetg(l, t_MAT);
4045 86520 : for (j = 1; j < l; j++)
4046 : {
4047 64890 : gel(q,j) = cgetg(l,t_COL);
4048 194670 : for (i = 1; i <= j; i++)
4049 129780 : gcoeff(q,i,j) = gcoeff(q,j,i) = mulreal(gel(x,i), gel(y,j));
4050 : }
4051 21630 : return q;
4052 : }
4053 :
4054 : /*******************************************************************/
4055 : /* */
4056 : /* LOGICAL OPERATIONS */
4057 : /* */
4058 : /*******************************************************************/
4059 : static long
4060 108072723 : _egal_i(GEN x, GEN y)
4061 : {
4062 108072723 : x = simplify_shallow(x);
4063 108072731 : y = simplify_shallow(y);
4064 108072713 : if (typ(y) == t_INT)
4065 : {
4066 107083851 : if (equali1(y)) return gequal1(x);
4067 61904164 : if (equalim1(y)) return gequalm1(x);
4068 : }
4069 988862 : else if (typ(x) == t_INT)
4070 : {
4071 140 : if (equali1(x)) return gequal1(y);
4072 91 : if (equalim1(x)) return gequalm1(y);
4073 : }
4074 62761403 : return gequal(x, y);
4075 : }
4076 : static long
4077 108072721 : _egal(GEN x, GEN y)
4078 108072721 : { pari_sp av = avma; return gc_long(av, _egal_i(x, y)); }
4079 :
4080 : GEN
4081 6328207 : glt(GEN x, GEN y) { return gcmp(x,y)<0? gen_1: gen_0; }
4082 :
4083 : GEN
4084 7628237 : gle(GEN x, GEN y) { return gcmp(x,y)<=0? gen_1: gen_0; }
4085 :
4086 : GEN
4087 248443 : gge(GEN x, GEN y) { return gcmp(x,y)>=0? gen_1: gen_0; }
4088 :
4089 : GEN
4090 2374906 : ggt(GEN x, GEN y) { return gcmp(x,y)>0? gen_1: gen_0; }
4091 :
4092 : GEN
4093 47214652 : geq(GEN x, GEN y) { return _egal(x,y)? gen_1: gen_0; }
4094 :
4095 : GEN
4096 60858069 : gne(GEN x, GEN y) { return _egal(x,y)? gen_0: gen_1; }
4097 :
4098 : GEN
4099 604044 : gnot(GEN x) { return gequal0(x)? gen_1: gen_0; }
4100 :
4101 : /*******************************************************************/
4102 : /* */
4103 : /* FORMAL SIMPLIFICATIONS */
4104 : /* */
4105 : /*******************************************************************/
4106 :
4107 : GEN
4108 11020 : geval_gp(GEN x, GEN t)
4109 : {
4110 11020 : long lx, i, tx = typ(x);
4111 : pari_sp av;
4112 : GEN y, z;
4113 :
4114 11020 : if (is_const_t(tx) || tx==t_VECSMALL) return gcopy(x);
4115 10999 : switch(tx)
4116 : {
4117 10992 : case t_STR:
4118 10992 : return localvars_read_str(GSTR(x),t);
4119 :
4120 0 : case t_POLMOD:
4121 0 : av = avma;
4122 0 : return gerepileupto(av, gmodulo(geval_gp(gel(x,2),t),
4123 0 : geval_gp(gel(x,1),t)));
4124 :
4125 7 : case t_POL:
4126 7 : lx=lg(x); if (lx==2) return gen_0;
4127 7 : z = fetch_var_value(varn(x),t);
4128 7 : if (!z) return RgX_copy(x);
4129 7 : av = avma; y = geval_gp(gel(x,lx-1),t);
4130 14 : for (i=lx-2; i>1; i--)
4131 7 : y = gadd(geval_gp(gel(x,i),t), gmul(z,y));
4132 7 : return gerepileupto(av, y);
4133 :
4134 0 : case t_SER:
4135 0 : pari_err_IMPL( "evaluation of a power series");
4136 :
4137 0 : case t_RFRAC:
4138 0 : av = avma;
4139 0 : return gerepileupto(av, gdiv(geval_gp(gel(x,1),t), geval_gp(gel(x,2),t)));
4140 :
4141 0 : case t_QFB: case t_VEC: case t_COL: case t_MAT:
4142 0 : pari_APPLY_same(geval_gp(gel(x,i),t));
4143 :
4144 0 : case t_CLOSURE:
4145 0 : if (closure_arity(x) || closure_is_variadic(x))
4146 0 : pari_err_IMPL("eval on functions with parameters");
4147 0 : return closure_evalres(x);
4148 : }
4149 0 : pari_err_TYPE("geval",x);
4150 : return NULL; /* LCOV_EXCL_LINE */
4151 : }
4152 : GEN
4153 0 : geval(GEN x) { return geval_gp(x,NULL); }
4154 :
4155 : GEN
4156 530020397 : simplify_shallow(GEN x)
4157 : {
4158 : long v, lx;
4159 : GEN y, z;
4160 530020397 : if (!x) pari_err_BUG("simplify, NULL input");
4161 :
4162 530020397 : switch(typ(x))
4163 : {
4164 447148666 : case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_FFELT:
4165 : case t_PADIC: case t_QFB: case t_LIST: case t_STR: case t_VECSMALL:
4166 : case t_CLOSURE: case t_ERROR: case t_INFINITY:
4167 447148666 : return x;
4168 738429 : case t_COMPLEX: return isintzero(gel(x,2))? gel(x,1): x;
4169 805 : case t_QUAD: return isintzero(gel(x,3))? gel(x,2): x;
4170 :
4171 197012 : case t_POLMOD: y = cgetg(3,t_POLMOD);
4172 197012 : z = gel(x,1); v = varn(z); z = simplify_shallow(z);
4173 197012 : if (typ(z) != t_POL || varn(z) != v) z = scalarpol_shallow(z, v);
4174 197012 : gel(y,1) = z;
4175 197012 : gel(y,2) = simplify_shallow(gel(x,2)); return y;
4176 :
4177 68795800 : case t_POL:
4178 68795800 : lx = lg(x);
4179 68795800 : if (lx==2) return gen_0;
4180 61210560 : if (lx==3) return simplify_shallow(gel(x,2));
4181 197740413 : pari_APPLY_pol(simplify_shallow(gel(x,i)));
4182 :
4183 3633 : case t_SER:
4184 1065337 : pari_APPLY_ser(simplify_shallow(gel(x,i)));
4185 :
4186 651873 : case t_RFRAC: y = cgetg(3,t_RFRAC);
4187 651873 : gel(y,1) = simplify_shallow(gel(x,1));
4188 651873 : z = simplify_shallow(gel(x,2));
4189 651873 : if (typ(z) != t_POL) return gdiv(gel(y,1), z);
4190 651873 : gel(y,2) = z; return y;
4191 :
4192 12484179 : case t_VEC: case t_COL: case t_MAT:
4193 70195679 : pari_APPLY_same(simplify_shallow(gel(x,i)));
4194 : }
4195 0 : pari_err_BUG("simplify_shallow, type unknown");
4196 : return NULL; /* LCOV_EXCL_LINE */
4197 : }
4198 :
4199 : GEN
4200 11845702 : simplify(GEN x)
4201 : {
4202 11845702 : pari_sp av = avma;
4203 11845702 : GEN y = simplify_shallow(x);
4204 11845702 : return av == avma ? gcopy(y): gerepilecopy(av, y);
4205 : }
4206 :
4207 : /*******************************************************************/
4208 : /* */
4209 : /* EVALUATION OF SOME SIMPLE OBJECTS */
4210 : /* */
4211 : /*******************************************************************/
4212 : /* q is a real symmetric matrix, x a RgV. Horner-type evaluation of q(x)
4213 : * using (n^2+3n-2)/2 mul */
4214 : GEN
4215 17023 : qfeval(GEN q, GEN x)
4216 : {
4217 17023 : pari_sp av = avma;
4218 17023 : long i, j, l = lg(q);
4219 : GEN z;
4220 17023 : if (lg(x) != l) pari_err_DIM("qfeval");
4221 17016 : if (l==1) return gen_0;
4222 17016 : if (lgcols(q) != l) pari_err_DIM("qfeval");
4223 : /* l = lg(x) = lg(q) > 1 */
4224 17009 : z = gmul(gcoeff(q,1,1), gsqr(gel(x,1)));
4225 74015 : for (i=2; i<l; i++)
4226 : {
4227 57006 : GEN c = gel(q,i), s;
4228 57006 : if (isintzero(gel(x,i))) continue;
4229 43356 : s = gmul(gel(c,1), gel(x,1));
4230 131810 : for (j=2; j<i; j++) s = gadd(s, gmul(gel(c,j),gel(x,j)));
4231 43356 : s = gadd(gshift(s,1), gmul(gel(c,i),gel(x,i)));
4232 43356 : z = gadd(z, gmul(gel(x,i), s));
4233 : }
4234 17009 : return gerepileupto(av,z);
4235 : }
4236 :
4237 : static GEN
4238 347816 : qfbeval(GEN q, GEN z)
4239 : {
4240 347816 : GEN A, a = gel(q,1), b = gel(q,2), c = gel(q,3), x = gel(z,1), y = gel(z,2);
4241 347816 : pari_sp av = avma;
4242 347816 : A = gadd(gmul(x, gadd(gmul(a,x), gmul(b,y))), gmul(c, gsqr(y)));
4243 347816 : return gerepileupto(av, A);
4244 : }
4245 : static GEN
4246 7 : qfbevalb(GEN q, GEN z, GEN z2)
4247 : {
4248 7 : GEN A, a = gel(q,1), b = gel(q,2), c = gel(q,3);
4249 7 : GEN x = gel(z,1), y = gel(z,2);
4250 7 : GEN X = gel(z2,1), Y = gel(z2,2);
4251 7 : GEN a2 = shifti(a,1), c2 = shifti(c,1);
4252 7 : pari_sp av = avma;
4253 : /* a2 x X + b (x Y + X y) + c2 y Y */
4254 7 : A = gadd(gmul(x, gadd(gmul(a2,X), gmul(b,Y))),
4255 : gmul(y, gadd(gmul(c2,Y), gmul(b,X))));
4256 7 : return gerepileupto(av, gmul2n(A, -1));
4257 : }
4258 : GEN
4259 61920 : qfb_ZM_apply(GEN q, GEN M)
4260 : {
4261 61920 : pari_sp av = avma;
4262 61920 : GEN A, B, C, a = gel(q,1), b = gel(q,2), c = gel(q,3);
4263 61920 : GEN x = gcoeff(M,1,1), y = gcoeff(M,2,1);
4264 61920 : GEN z = gcoeff(M,1,2), t = gcoeff(M,2,2);
4265 61920 : GEN by = mulii(b,y), bt = mulii(b,t), bz = mulii(b,z);
4266 61920 : GEN a2 = shifti(a,1), c2 = shifti(c,1);
4267 :
4268 61920 : A = addii(mulii(x, addii(mulii(a,x), by)), mulii(c, sqri(y)));
4269 61920 : B = addii(mulii(x, addii(mulii(a2,z), bt)),
4270 : mulii(y, addii(mulii(c2,t), bz)));
4271 61920 : C = addii(mulii(z, addii(mulii(a,z), bt)), mulii(c, sqri(t)));
4272 61920 : q = leafcopy(q);
4273 61920 : gel(q,1) = A; gel(q,2) = B; gel(q,3) = C;
4274 61920 : return gerepilecopy(av, q);
4275 : }
4276 :
4277 : static GEN
4278 348012 : qfnorm0(GEN q, GEN x)
4279 : {
4280 348012 : if (!q) switch(typ(x))
4281 : {
4282 7 : case t_VEC: case t_COL: return RgV_dotsquare(x);
4283 7 : case t_MAT: return gram_matrix(x);
4284 7 : default: pari_err_TYPE("qfeval",x);
4285 : }
4286 347991 : switch(typ(q))
4287 : {
4288 161 : case t_MAT: break;
4289 347823 : case t_QFB:
4290 347823 : if (lg(x) == 3) switch(typ(x))
4291 : {
4292 347816 : case t_VEC:
4293 347816 : case t_COL: return qfbeval(q,x);
4294 7 : case t_MAT: if (RgM_is_ZM(x)) return qfb_ZM_apply(q,x);
4295 0 : default: pari_err_TYPE("qfeval",x);
4296 : }
4297 7 : default: pari_err_TYPE("qfeval",q);
4298 : }
4299 161 : switch(typ(x))
4300 : {
4301 154 : case t_VEC: case t_COL: break;
4302 7 : case t_MAT: return qf_RgM_apply(q, x);
4303 0 : default: pari_err_TYPE("qfeval",x);
4304 : }
4305 154 : return qfeval(q,x);
4306 : }
4307 : /* obsolete, use qfeval0 */
4308 : GEN
4309 0 : qfnorm(GEN x, GEN q) { return qfnorm0(q,x); }
4310 :
4311 : /* assume q is square, x~ * q * y using n^2+n mul */
4312 : GEN
4313 21 : qfevalb(GEN q, GEN x, GEN y)
4314 : {
4315 21 : pari_sp av = avma;
4316 21 : long l = lg(q);
4317 21 : if (lg(x) != l || lg(y) != l) pari_err_DIM("qfevalb");
4318 14 : return gerepileupto(av, RgV_dotproduct(RgV_RgM_mul(x,q), y));
4319 : }
4320 :
4321 : /* obsolete, use qfeval0 */
4322 : GEN
4323 0 : qfbil(GEN x, GEN y, GEN q)
4324 : {
4325 0 : if (!is_vec_t(typ(x))) pari_err_TYPE("qfbil",x);
4326 0 : if (!is_vec_t(typ(y))) pari_err_TYPE("qfbil",y);
4327 0 : if (!q) {
4328 0 : if (lg(x) != lg(y)) pari_err_DIM("qfbil");
4329 0 : return RgV_dotproduct(x,y);
4330 : }
4331 0 : if (typ(q) != t_MAT) pari_err_TYPE("qfbil",q);
4332 0 : return qfevalb(q,x,y);
4333 : }
4334 : GEN
4335 348068 : qfeval0(GEN q, GEN x, GEN y)
4336 : {
4337 348068 : if (!y) return qfnorm0(q, x);
4338 56 : if (!is_vec_t(typ(x))) pari_err_TYPE("qfeval",x);
4339 42 : if (!is_vec_t(typ(y))) pari_err_TYPE("qfeval",y);
4340 42 : if (!q) {
4341 14 : if (lg(x) != lg(y)) pari_err_DIM("qfeval");
4342 7 : return RgV_dotproduct(x,y);
4343 : }
4344 28 : switch(typ(q))
4345 : {
4346 21 : case t_MAT: break;
4347 7 : case t_QFB:
4348 7 : if (lg(x) == 3 && lg(y) == 3) return qfbevalb(q,x,y);
4349 0 : default: pari_err_TYPE("qfeval",q);
4350 : }
4351 21 : return qfevalb(q,x,y);
4352 : }
4353 :
4354 : /* q a hermitian complex matrix, x a RgV */
4355 : GEN
4356 0 : hqfeval(GEN q, GEN x)
4357 : {
4358 0 : pari_sp av = avma;
4359 0 : long i, j, l = lg(q);
4360 : GEN z, xc;
4361 :
4362 0 : if (lg(x) != l) pari_err_DIM("hqfeval");
4363 0 : if (l==1) return gen_0;
4364 0 : if (lgcols(q) != l) pari_err_DIM("hqfeval");
4365 0 : if (l == 2) return gerepileupto(av, gmul(gcoeff(q,1,1), gnorm(gel(x,1))));
4366 : /* l = lg(x) = lg(q) > 2 */
4367 0 : xc = conj_i(x);
4368 0 : z = mulreal(gcoeff(q,2,1), gmul(gel(x,2),gel(xc,1)));
4369 0 : for (i=3;i<l;i++)
4370 0 : for (j=1;j<i;j++)
4371 0 : z = gadd(z, mulreal(gcoeff(q,i,j), gmul(gel(x,i),gel(xc,j))));
4372 0 : z = gshift(z,1);
4373 0 : for (i=1;i<l;i++) z = gadd(z, gmul(gcoeff(q,i,i), gnorm(gel(x,i))));
4374 0 : return gerepileupto(av,z);
4375 : }
4376 :
4377 : static void
4378 504697 : init_qf_apply(GEN q, GEN M, long *l)
4379 : {
4380 504697 : long k = lg(M);
4381 504697 : *l = lg(q);
4382 504697 : if (*l == 1) { if (k == 1) return; }
4383 504690 : else { if (k != 1 && lgcols(M) == *l) return; }
4384 0 : pari_err_DIM("qf_RgM_apply");
4385 : }
4386 : /* Return X = M'.q.M, assuming q is a symmetric matrix and M is a
4387 : * matrix of compatible dimensions. X_ij are X_ji identical, not copies */
4388 : GEN
4389 7663 : qf_RgM_apply(GEN q, GEN M)
4390 : {
4391 7663 : pari_sp av = avma;
4392 7663 : long l; init_qf_apply(q, M, &l); if (l == 1) return cgetg(1, t_MAT);
4393 7663 : return gerepileupto(av, RgM_transmultosym(M, RgM_mul(q, M)));
4394 : }
4395 : GEN
4396 497034 : qf_ZM_apply(GEN q, GEN M)
4397 : {
4398 497034 : pari_sp av = avma;
4399 497034 : long l; init_qf_apply(q, M, &l); if (l == 1) return cgetg(1, t_MAT);
4400 : /* FIXME: ZM_transmultosym is asymptotically slow, so choose some random
4401 : * threshold defaulting to default implementation: this is suboptimal but
4402 : * has the right complexity in the dimension. Should implement M'*q*M as an
4403 : * atomic operation with the right complexity, see ZM_mul_i. */
4404 497027 : if (l > 20)
4405 161 : M = ZM_mul(shallowtrans(M), ZM_mul(q, M));
4406 : else
4407 496866 : M = ZM_transmultosym(M, ZM_mul(q, M));
4408 497027 : return gerepileupto(av, M);
4409 : }
4410 :
4411 : GEN
4412 2896837 : poleval(GEN x, GEN y)
4413 : {
4414 2896837 : long i, j, imin, tx = typ(x);
4415 2896837 : pari_sp av0 = avma, av;
4416 : GEN t, t2, r, s;
4417 :
4418 2896837 : if (is_scalar_t(tx)) return gcopy(x);
4419 2715265 : switch(tx)
4420 : {
4421 2713340 : case t_POL:
4422 2713340 : i = lg(x)-1; imin = 2; break;
4423 :
4424 1568 : case t_RFRAC:
4425 1568 : return gerepileupto(av0, gdiv(poleval(gel(x,1),y),
4426 1568 : poleval(gel(x,2),y)));
4427 :
4428 357 : case t_VEC: case t_COL:
4429 357 : i = lg(x)-1; imin = 1; break;
4430 0 : default: pari_err_TYPE("poleval",x);
4431 : return NULL; /* LCOV_EXCL_LINE */
4432 : }
4433 2713697 : if (i<=imin) return (i==imin)? gmul(gel(x,imin),Rg_get_1(y)): Rg_get_0(y);
4434 2553243 : if (isintzero(y)) return gcopy(gel(x,imin));
4435 :
4436 2545992 : t = gel(x,i); i--;
4437 2545992 : if (typ(y)!=t_COMPLEX)
4438 : {
4439 : #if 0 /* standard Horner's rule */
4440 : for ( ; i>=imin; i--)
4441 : t = gadd(gmul(t,y),gel(x,i));
4442 : #endif
4443 : /* specific attention to sparse polynomials */
4444 18604771 : for ( ; i>=imin; i=j-1)
4445 : {
4446 18837945 : for (j=i; isexactzero(gel(x,j)); j--)
4447 2681336 : if (j==imin)
4448 : {
4449 971511 : if (i!=j) y = gpowgs(y, i-j+1);
4450 971511 : return gerepileupto(av0, gmul(t,y));
4451 : }
4452 16156608 : r = (i==j)? y: gpowgs(y, i-j+1);
4453 16156608 : t = gadd(gmul(t,r), gel(x,j));
4454 16156568 : if (gc_needed(av0,2))
4455 : {
4456 109 : if (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i);
4457 109 : t = gerepileupto(av0, t);
4458 : }
4459 : }
4460 1476651 : return gerepileupto(av0, t);
4461 : }
4462 :
4463 97789 : t2 = gel(x,i); i--; r = gtrace(y); s = gneg_i(gnorm(y));
4464 97789 : av = avma;
4465 4957905 : for ( ; i>=imin; i--)
4466 : {
4467 4860116 : GEN p = gadd(t2, gmul(r, t));
4468 4860116 : t2 = gadd(gel(x,i), gmul(s, t)); t = p;
4469 4860116 : if (gc_needed(av0,2))
4470 : {
4471 0 : if (DEBUGMEM>1) pari_warn(warnmem,"poleval: i = %ld",i);
4472 0 : gerepileall(av, 2, &t, &t2);
4473 : }
4474 : }
4475 97789 : return gerepileupto(av0, gadd(t2, gmul(y, t)));
4476 : }
4477 :
4478 : /* Evaluate a polynomial using Horner. Unstable!
4479 : * If ui != NULL, ui = 1/u, evaluate P(1/u)*u^(deg P): useful for |u|>1 */
4480 : GEN
4481 2412528 : RgX_cxeval(GEN T, GEN u, GEN ui)
4482 : {
4483 2412528 : pari_sp ltop = avma;
4484 : GEN S;
4485 2412528 : long n, lim = lg(T)-1;
4486 2412528 : if (lim == 1) return gen_0;
4487 2412528 : if (lim == 2) return gcopy(gel(T,2));
4488 2411370 : if (!ui)
4489 : {
4490 1664248 : n = lim; S = gel(T,n);
4491 14920311 : for (n--; n >= 2; n--) S = gadd(gmul(u,S), gel(T,n));
4492 : }
4493 : else
4494 : {
4495 747122 : n = 2; S = gel(T,2);
4496 4484033 : for (n++; n <= lim; n++) S = gadd(gmul(ui,S), gel(T,n));
4497 747117 : S = gmul(gpowgs(u, lim-2), S);
4498 : }
4499 2411142 : return gerepileupto(ltop, S);
4500 : }
4501 :
4502 : GEN
4503 63 : RgXY_cxevalx(GEN x, GEN u, GEN ui)
4504 : {
4505 427 : pari_APPLY_pol(typ(gel(x,i))==t_POL? RgX_cxeval(gel(x,i), u, ui): gel(x,i));
4506 : }
|