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 : /** (first part) **/
19 : /** **/
20 : /********************************************************************/
21 : #include "pari.h"
22 : #include "paripriv.h"
23 :
24 : #define DEBUGLEVEL DEBUGLEVEL_mod
25 :
26 : /* assume z[1] was created last */
27 : #define fix_frac_if_int(z) if (equali1(gel(z,2)))\
28 : z = gerepileupto((pari_sp)(z+3), gel(z,1));
29 :
30 : /* assume z[1] was created last */
31 : #define fix_frac_if_int_GC(z,tetpil) { if (equali1(gel(z,2)))\
32 : z = gerepileupto((pari_sp)(z+3), gel(z,1));\
33 : else\
34 : gerepilecoeffssp((pari_sp)z, tetpil, z+1, 2); }
35 :
36 : static void
37 105 : warn_coercion(GEN x, GEN y, GEN z)
38 : {
39 105 : if (DEBUGLEVEL)
40 56 : pari_warn(warner,"coercing quotient rings; moduli %Ps and %Ps -> %Ps",x,y,z);
41 105 : }
42 :
43 : static long
44 28 : kro_quad(GEN x, GEN y)
45 28 : { pari_sp av=avma; return gc_long(av, kronecker(quad_disc(x), y)); }
46 :
47 : /* is -1 not a square in Zp, assume p prime */
48 : INLINE int
49 42 : Zp_nosquare_m1(GEN p) { return (mod4(p) & 2); /* 2 or 3 mod 4 */ }
50 :
51 : static GEN addsub_pp(GEN x, GEN y, GEN(*op)(GEN,GEN));
52 : static GEN mulpp(GEN x, GEN y);
53 : static GEN divpp(GEN x, GEN y);
54 : /* Argument codes for inline routines
55 : * c: complex, p: padic, q: quad, f: floating point (REAL, some complex)
56 : * R: without imaginary part (INT, REAL, INTMOD, FRAC, PADIC if -1 not square)
57 : * T: some type (to be converted to PADIC)
58 : */
59 : static GEN
60 287388373 : addRc(GEN x, GEN y) {
61 287388373 : GEN z = cgetg(3,t_COMPLEX);
62 287395551 : gel(z,1) = gadd(x,gel(y,1));
63 287316340 : gel(z,2) = gcopy(gel(y,2)); return z;
64 : }
65 : static GEN
66 326254936 : mulRc(GEN x, GEN y) {
67 326254936 : GEN z = cgetg(3,t_COMPLEX);
68 326130940 : gel(z,1) = isintzero(gel(y,1))? gen_0: gmul(x,gel(y,1));
69 325759984 : gel(z,2) = gmul(x,gel(y,2)); return z;
70 : }
71 : /* for INTMODs: can't simplify when Re(x) = gen_0 */
72 : static GEN
73 49 : mulRc_direct(GEN x, GEN y) {
74 49 : GEN z = cgetg(3,t_COMPLEX);
75 49 : gel(z,1) = gmul(x,gel(y,1));
76 49 : gel(z,2) = gmul(x,gel(y,2)); return z;
77 : }
78 : static GEN
79 2163731 : divRc(GEN x, GEN y) {
80 2163731 : GEN t = gdiv(x, cxnorm(y)), mt = gneg(t); /* left on stack for efficiency */
81 2163730 : GEN z = cgetg(3,t_COMPLEX);
82 2163729 : gel(z,1) = isintzero(gel(y,1))? gen_0: gmul(t, gel(y,1));
83 2163722 : gel(z,2) = gmul(mt, gel(y,2));
84 2163722 : return z;
85 : }
86 : static GEN
87 19405839 : divcR(GEN x, GEN y) {
88 19405839 : GEN z = cgetg(3,t_COMPLEX);
89 19405750 : gel(z,1) = isintzero(gel(x,1))? gen_0: gdiv(gel(x,1), y);
90 19404678 : gel(z,2) = gdiv(gel(x,2), y); return z;
91 : }
92 : static GEN
93 1274 : addRq(GEN x, GEN y) {
94 1274 : GEN z = cgetg(4,t_QUAD);
95 1274 : gel(z,1) = ZX_copy(gel(y,1));
96 1274 : gel(z,2) = gadd(x, gel(y,2));
97 1274 : gel(z,3) = gcopy(gel(y,3)); return z;
98 : }
99 : static GEN
100 2352 : mulRq(GEN x, GEN y) {
101 2352 : GEN z = cgetg(4,t_QUAD);
102 2352 : gel(z,1) = ZX_copy(gel(y,1));
103 2352 : gel(z,2) = gmul(x,gel(y,2));
104 2352 : gel(z,3) = gmul(x,gel(y,3)); return z;
105 : }
106 : static GEN
107 77 : addqf(GEN x, GEN y, long prec) { pari_sp av = avma;
108 77 : long i = gexpo(x) - gexpo(y);
109 77 : if (i > 0) prec += nbits2extraprec(i);
110 77 : return gerepileupto(av, gadd(y, quadtofp(x, prec)));
111 : }
112 : static GEN
113 30144092 : mulrfrac(GEN x, GEN y)
114 : {
115 : pari_sp av;
116 30144092 : GEN z, a = gel(y,1), b = gel(y,2);
117 30144092 : if (is_pm1(a)) /* frequent special case */
118 : {
119 5400644 : z = divri(x, b); if (signe(a) < 0) togglesign(z);
120 5400537 : return z;
121 : }
122 24743443 : av = avma;
123 24743443 : return gerepileuptoleaf(av, divri(mulri(x,a), b));
124 : }
125 : static GEN
126 28 : mulqf(GEN x, GEN y, long prec) { pari_sp av = avma;
127 28 : return gerepileupto(av, gmul(y, quadtofp(x, prec)));
128 : }
129 : static GEN
130 63 : divqf(GEN x, GEN y, long prec) { pari_sp av = avma;
131 63 : return gerepileupto(av, gdiv(quadtofp(x,prec), y));
132 : }
133 : static GEN
134 42 : divfq(GEN x, GEN y, long prec) { pari_sp av = avma;
135 42 : return gerepileupto(av, gdiv(x, quadtofp(y,prec)));
136 : }
137 : /* y PADIC, x + y by converting x to padic */
138 : static GEN
139 7 : addTp(GEN x, GEN y) { pari_sp av = avma; GEN z;
140 :
141 7 : if (!valp(y)) z = cvtop2(x,y);
142 : else {
143 7 : long l = signe(gel(y,4))? valp(y) + precp(y): valp(y);
144 7 : z = cvtop(x, gel(y,2), l);
145 : }
146 7 : return gerepileupto(av, addsub_pp(z, y, addii));
147 : }
148 : /* y PADIC, x * y by converting x to padic */
149 : static GEN
150 4892508 : mulTp(GEN x, GEN y) { pari_sp av = avma;
151 4892508 : return gerepileupto(av, mulpp(cvtop2(x,y), y));
152 : }
153 : /* y PADIC, non zero x / y by converting x to padic */
154 : static GEN
155 3681 : divTp(GEN x, GEN y) { pari_sp av = avma;
156 3681 : return gerepileupto(av, divpp(cvtop2(x,y), y));
157 : }
158 : /* x PADIC, x / y by converting y to padic. Assume x != 0; otherwise y
159 : * converted to O(p^e) and division by 0 */
160 : static GEN
161 1201732 : divpT(GEN x, GEN y) { pari_sp av = avma;
162 1201732 : return gerepileupto(av, divpp(x, cvtop2(y,x)));
163 : }
164 :
165 : /* z := Mod(x,X) + Mod(y,X) [ t_INTMOD preallocated ], x,y,X INT, 0 <= x,y < X
166 : * clean memory from z on */
167 : static GEN
168 3690602 : add_intmod_same(GEN z, GEN X, GEN x, GEN y) {
169 3690602 : if (lgefint(X) == 3) {
170 3367366 : ulong u = Fl_add(itou(x),itou(y), X[2]);
171 3367366 : set_avma((pari_sp)z); gel(z,2) = utoi(u);
172 : }
173 : else {
174 323236 : GEN u = addii(x,y); if (cmpii(u, X) >= 0) u = subii(u, X);
175 323234 : gel(z,2) = gerepileuptoint((pari_sp)z, u);
176 : }
177 3690601 : gel(z,1) = icopy(X); return z;
178 : }
179 : static GEN
180 1158469 : sub_intmod_same(GEN z, GEN X, GEN x, GEN y) {
181 1158469 : if (lgefint(X) == 3) {
182 784435 : ulong u = Fl_sub(itou(x),itou(y), X[2]);
183 784435 : set_avma((pari_sp)z); gel(z,2) = utoi(u);
184 : }
185 : else {
186 374034 : GEN u = subii(x,y); if (signe(u) < 0) u = addii(u, X);
187 374034 : gel(z,2) = gerepileuptoint((pari_sp)z, u);
188 : }
189 1158469 : gel(z,1) = icopy(X); return z;
190 : }
191 : /* cf add_intmod_same */
192 : static GEN
193 3102324 : mul_intmod_same(GEN z, GEN X, GEN x, GEN y) {
194 3102324 : if (lgefint(X) == 3) {
195 2960060 : ulong u = Fl_mul(itou(x),itou(y), X[2]);
196 2960060 : set_avma((pari_sp)z); gel(z,2) = utoi(u);
197 : }
198 : else
199 142264 : gel(z,2) = gerepileuptoint((pari_sp)z, remii(mulii(x,y), X) );
200 3102325 : gel(z,1) = icopy(X); return z;
201 : }
202 : /* cf add_intmod_same */
203 : static GEN
204 341888 : div_intmod_same(GEN z, GEN X, GEN x, GEN y)
205 : {
206 341888 : if (lgefint(X) == 3) {
207 319278 : ulong m = uel(X,2), u = Fl_div(itou(x), itou(y), m);
208 319271 : set_avma((pari_sp)z); gel(z,2) = utoi(u);
209 : }
210 : else
211 22610 : gel(z,2) = gerepileuptoint((pari_sp)z, remii(mulii(x, Fp_inv(y,X)), X) );
212 341881 : gel(z,1) = icopy(X); return z;
213 : }
214 :
215 : /*******************************************************************/
216 : /* */
217 : /* REDUCTION to IRREDUCIBLE TERMS (t_FRAC/t_RFRAC) */
218 : /* */
219 : /* (static routines are not memory clean, but OK for gerepileupto) */
220 : /*******************************************************************/
221 : /* Compute the denominator of (1/y) * (n/d) = n/yd, y a "scalar".
222 : * Sanity check : avoid (1/2) / (Mod(1,2)*x + 1) "=" 1 / (0 * x + 1) */
223 : static GEN
224 9890974 : rfrac_denom_mul_scal(GEN d, GEN y)
225 : {
226 9890974 : GEN D = RgX_Rg_mul(d, y);
227 9890974 : if (lg(D) != lg(d))
228 : { /* try to generate a meaningful diagnostic */
229 0 : D = gdiv(leading_coeff(d), y); /* should fail */
230 0 : pari_err_INV("gred_rfrac", y); /* better than nothing */
231 : }
232 9890974 : return D;
233 : }
234 :
235 : static int
236 57847854 : Leading_is_neg(GEN x)
237 : {
238 122327224 : while (typ(x) == t_POL) x = leading_coeff(x);
239 57847854 : return is_real_t(typ(x))? gsigne(x) < 0: 0;
240 : }
241 :
242 : static int
243 154527242 : transtype(GEN x) { return x != gen_1 && typ(x) != t_PADIC; }
244 :
245 : /* d a t_POL, n a coprime t_POL of same var or "scalar". Not memory clean */
246 : GEN
247 57852013 : gred_rfrac_simple(GEN n, GEN d)
248 : {
249 : GEN _1n, _1d, c, cn, cd, z;
250 57852013 : long dd = degpol(d);
251 :
252 57852013 : if (dd <= 0)
253 : {
254 4159 : if (dd < 0) pari_err_INV("gred_rfrac_simple", d);
255 4159 : n = gdiv(n, gel(d,2));
256 4159 : if (typ(n) != t_POL || varn(n) != varn(d)) n = scalarpol(n, varn(d));
257 4159 : return n;
258 : }
259 57847854 : if (Leading_is_neg(d)) { d = gneg(d); n = gneg(n); }
260 57847854 : _1n = Rg_get_1(n);
261 57847854 : _1d = Rg_get_1(d);
262 57847854 : if (transtype(_1n) && !gidentical(_1n, _1d)) d = gmul(d, _1n);
263 57847854 : if (transtype(_1d) && !gidentical(_1n, _1d)) n = gmul(n, _1d);
264 57847847 : cd = content(d);
265 59719173 : while (typ(n) == t_POL && !degpol(n)) n = gel(n,2);
266 57847847 : cn = (typ(n) == t_POL && varn(n) == varn(d))? content(n): n;
267 57847847 : if (!gequal1(cd)) {
268 6582165 : d = RgX_Rg_div(d,cd);
269 6582165 : if (!gequal1(cn))
270 : {
271 1309822 : if (gequal0(cn)) {
272 49 : if (isexactzero(cn)) return scalarpol(cn, varn(d));
273 0 : n = (cn != n)? RgX_Rg_div(n,cd): gdiv(n, cd);
274 0 : c = gen_1;
275 : } else {
276 1309773 : n = (cn != n)? RgX_Rg_div(n,cn): gen_1;
277 1309773 : c = gdiv(cn,cd);
278 : }
279 : }
280 : else
281 5272343 : c = ginv(cd);
282 : } else {
283 51265682 : if (!gequal1(cn))
284 : {
285 3279489 : if (gequal0(cn)) {
286 1484 : if (isexactzero(cn)) return scalarpol(cn, varn(d));
287 21 : c = gen_1;
288 : } else {
289 3278005 : n = (cn != n)? RgX_Rg_div(n,cn): gen_1;
290 3278005 : c = cn;
291 : }
292 : } else {
293 47986193 : GEN y = cgetg(3,t_RFRAC);
294 47986193 : gel(y,1) = gcopy(n);
295 47986193 : gel(y,2) = RgX_copy(d); return y;
296 : }
297 : }
298 :
299 9860142 : if (typ(c) == t_POL)
300 : {
301 904062 : z = c;
302 943206 : do { z = content(z); } while (typ(z) == t_POL);
303 904062 : cd = denom_i(z);
304 904062 : cn = gmul(c, cd);
305 : }
306 : else
307 : {
308 8956080 : cn = numer_i(c);
309 8956080 : cd = denom_i(c);
310 : }
311 9860142 : z = cgetg(3,t_RFRAC);
312 9860142 : gel(z,1) = gmul(n, cn);
313 9860142 : gel(z,2) = d = rfrac_denom_mul_scal(d, cd);
314 : /* can happen: Pol(O(17^-1)) / Pol([Mod(9,23), O(23^-3)]) */
315 9860142 : if (!signe(d)) pari_err_INV("gred_rfrac_simple", d);
316 9860142 : return z;
317 : }
318 :
319 : /* in rare cases x may be a t_POL, after 0/x for instance -> pol_0() */
320 : static GEN
321 248290 : fix_rfrac(GEN x, long d)
322 : {
323 : GEN z, N, D;
324 248290 : if (!d || typ(x) == t_POL) return x;
325 171682 : z = cgetg(3, t_RFRAC);
326 171682 : N = gel(x,1);
327 171682 : D = gel(x,2);
328 171682 : if (d > 0) {
329 8694 : gel(z, 1) = (typ(N)==t_POL && varn(N)==varn(D))? RgX_shift(N,d)
330 165893 : : monomialcopy(N,d,varn(D));
331 165844 : gel(z, 2) = RgX_copy(D);
332 : } else {
333 5838 : gel(z, 1) = gcopy(N);
334 5838 : gel(z, 2) = RgX_shift(D, -d);
335 : }
336 171682 : return z;
337 : }
338 :
339 : /* assume d != 0 */
340 : static GEN
341 44775647 : gred_rfrac2(GEN n, GEN d)
342 : {
343 : GEN y, z, _1n, _1d;
344 : long v, vd, vn;
345 :
346 44775647 : n = simplify_shallow(n);
347 44775647 : if (isintzero(n)) return scalarpol(Rg_get_0(d), varn(d));
348 37944018 : d = simplify_shallow(d);
349 37944018 : if (typ(d) != t_POL) return gdiv(n,d);
350 36764201 : vd = varn(d);
351 36764201 : if (typ(n) != t_POL)
352 : {
353 20625635 : if (varncmp(vd, gvar(n)) >= 0) return gdiv(n,d);
354 20624228 : if (varncmp(vd, gvar2(n)) < 0) return gred_rfrac_simple(n,d);
355 0 : pari_err_BUG("gred_rfrac2 [incompatible variables]");
356 : }
357 16138566 : vn = varn(n);
358 16138566 : if (varncmp(vd, vn) < 0) return gred_rfrac_simple(n,d);
359 16000920 : if (varncmp(vd, vn) > 0) return RgX_Rg_div(n,d);
360 15841168 : _1n = Rg_get_1(n);
361 15841168 : _1d = Rg_get_1(d);
362 15841168 : if (transtype(_1n) && !gidentical(_1n, _1d)) d = gmul(d, _1n);
363 15841168 : if (transtype(_1d) && !gidentical(_1n, _1d)) n = gmul(n, _1d);
364 :
365 : /* now n and d are t_POLs in the same variable */
366 15841168 : v = RgX_valrem(n, &n) - RgX_valrem(d, &d);
367 15841168 : if (!degpol(d))
368 : {
369 12764081 : n = RgX_Rg_div(n,gel(d,2));
370 12764081 : return v? RgX_mulXn(n,v): n;
371 : }
372 :
373 : /* X does not divide gcd(n,d), deg(d) > 0 */
374 3077087 : if (!isinexact(n) && !isinexact(d))
375 : {
376 3076842 : y = RgX_divrem(n, d, &z);
377 3076842 : if (!signe(z)) { cgiv(z); return v? RgX_mulXn(y, v): y; }
378 248045 : z = RgX_gcd(d, z);
379 248045 : if (degpol(z)) { n = RgX_div(n,z); d = RgX_div(d,z); }
380 : }
381 248290 : return fix_rfrac(gred_rfrac_simple(n,d), v);
382 : }
383 :
384 : /* x,y t_INT, return x/y in reduced form */
385 : GEN
386 112801809 : Qdivii(GEN x, GEN y)
387 : {
388 112801809 : pari_sp av = avma;
389 : GEN r, q;
390 :
391 112801809 : if (lgefint(y) == 3)
392 : {
393 97659257 : q = Qdiviu(x, y[2]);
394 97655500 : if (signe(y) > 0) return q;
395 10671248 : if (typ(q) == t_INT) togglesign(q); else togglesign_safe(&gel(q,1));
396 10671472 : return q;
397 : }
398 15142552 : if (is_pm1(y)) return (signe(y) < 0)? negi(x): icopy(x);
399 15143810 : if (equali1(x))
400 : {
401 5177463 : if (!signe(y)) pari_err_INV("gdiv",y);
402 5177351 : retmkfrac(signe(y) < 0? gen_m1: gen_1, absi(y));
403 : }
404 9966358 : q = dvmdii(x,y,&r);
405 9966170 : if (r == gen_0) return q; /* gen_0 intended */
406 7085914 : r = gcdii(y, r);
407 7085872 : if (lgefint(r) == 3)
408 : {
409 6241976 : ulong t = r[2];
410 6241976 : set_avma(av);
411 6242004 : if (t == 1) q = mkfraccopy(x,y);
412 : else
413 : {
414 2355378 : q = cgetg(3,t_FRAC);
415 2355595 : gel(q,1) = diviuexact(x,t);
416 2355429 : gel(q,2) = diviuexact(y,t);
417 : }
418 : }
419 : else
420 : { /* rare: r and q left on stack for efficiency */
421 843896 : q = cgetg(3,t_FRAC);
422 843931 : gel(q,1) = diviiexact(x,r);
423 843939 : gel(q,2) = diviiexact(y,r);
424 : }
425 7085922 : normalize_frac(q); return q;
426 : }
427 :
428 : /* x t_INT, return x/y in reduced form */
429 : GEN
430 116260410 : Qdiviu(GEN x, ulong y)
431 : {
432 116260410 : pari_sp av = avma;
433 : ulong r, t;
434 : GEN q;
435 :
436 116260410 : if (y == 1) return icopy(x);
437 95210068 : if (!y) pari_err_INV("gdiv",gen_0);
438 95210068 : if (equali1(x)) retmkfrac(gen_1, utoipos(y));
439 89494056 : q = absdiviu_rem(x,y,&r);
440 89487270 : if (!r)
441 : {
442 49875961 : if (signe(x) < 0) togglesign(q);
443 49876492 : return q;
444 : }
445 39611309 : t = ugcd(y, r); set_avma(av);
446 39615721 : if (t == 1) retmkfrac(icopy(x), utoipos(y));
447 15238443 : retmkfrac(diviuexact(x,t), utoipos(y / t));
448 : }
449 :
450 : /* x t_INT, return x/y in reduced form */
451 : GEN
452 1460136 : Qdivis(GEN x, long y)
453 : {
454 1460136 : pari_sp av = avma;
455 : ulong r, t;
456 : long s;
457 : GEN q;
458 :
459 1460136 : if (y > 0) return Qdiviu(x, y);
460 124829 : if (!y) pari_err_INV("gdiv",gen_0);
461 124829 : s = signe(x);
462 124829 : if (!s) return gen_0;
463 95725 : if (y < 0) { y = -y; s = -s; }
464 95725 : if (y == 1) { x = icopy(x); setsigne(x,s); return x; }
465 95445 : if (equali1(x)) retmkfrac(s > 0? gen_1: gen_m1, utoipos(y));
466 93380 : q = absdiviu_rem(x,y,&r);
467 93380 : if (!r)
468 : {
469 46123 : if (s < 0) togglesign(q);
470 46123 : return q;
471 : }
472 47257 : t = ugcd(y, r); set_avma(av); q = cgetg(3, t_FRAC);
473 47257 : if (t != 1) { x = diviuexact(x,t); y /= t; } else x = icopy(x);
474 47257 : gel(q,1) = x; setsigne(x, s);
475 47257 : gel(q,2) = utoipos(y); return q;
476 : }
477 :
478 : /*******************************************************************/
479 : /* */
480 : /* CONJUGATION */
481 : /* */
482 : /*******************************************************************/
483 : /* lift( conj(Mod(x, y)) ), assuming degpol(y) = 2, degpol(x) < 2 */
484 : static GEN
485 18263 : quad_polmod_conj(GEN x, GEN y)
486 : {
487 : GEN z, u, v, a, b;
488 18263 : if (typ(x) != t_POL) return gcopy(x);
489 18263 : if (varn(x) != varn(y) || degpol(x) <= 0) return RgX_copy(x);
490 18263 : a = gel(y,4); u = gel(x,3); /*Mod(ux + v, ax^2 + bx + c)*/
491 18263 : b = gel(y,3); v = gel(x,2);
492 18263 : z = cgetg(4, t_POL); z[1] = x[1];
493 18263 : gel(z,2) = gsub(v, gdiv(gmul(u,b), a));
494 18263 : gel(z,3) = gneg(u); return z;
495 : }
496 : static GEN
497 18263 : quad_polmod_norm(GEN x, GEN y)
498 : {
499 : GEN z, u, v, a, b, c;
500 18263 : if (typ(x) != t_POL || varn(x) != varn(y) || degpol(x) <= 0) return gsqr(x);
501 18263 : a = gel(y,4); u = gel(x,3); /*Mod(ux + v, ax^2 + bx + c)*/
502 18263 : b = gel(y,3); v = gel(x,2);
503 18263 : c = gel(y,2);
504 18263 : z = gmul(u, gsub(gmul(c,u), gmul(b,v)));
505 18263 : if (!gequal1(a)) z = gdiv(z, a);
506 18263 : return gadd(z, gsqr(v));
507 : }
508 :
509 : GEN
510 17704100 : conj_i(GEN x)
511 : {
512 : long lx, i;
513 : GEN y;
514 :
515 17704100 : switch(typ(x))
516 : {
517 5790429 : case t_INT: case t_REAL: case t_INTMOD: case t_FRAC: case t_PADIC:
518 5790429 : return x;
519 :
520 11753264 : case t_COMPLEX: return mkcomplex(gel(x,1), gneg(gel(x,2)));
521 :
522 924 : case t_QUAD:
523 924 : y = cgetg(4,t_QUAD);
524 924 : gel(y,1) = gel(x,1);
525 924 : gel(y,2) = gequal0(gmael(x,1,3))? gel(x,2)
526 924 : : gadd(gel(x,2), gel(x,3));
527 924 : gel(y,3) = gneg(gel(x,3)); return y;
528 :
529 9135 : case t_POL: case t_SER:
530 9135 : y = cgetg_copy(x, &lx); y[1] = x[1];
531 30597 : for (i=2; i<lx; i++) gel(y,i) = conj_i(gel(x,i));
532 9135 : return y;
533 :
534 150379 : case t_RFRAC: case t_VEC: case t_COL: case t_MAT:
535 150379 : y = cgetg_copy(x, &lx);
536 542905 : for (i=1; i<lx; i++) gel(y,i) = conj_i(gel(x,i));
537 150380 : return y;
538 :
539 0 : case t_POLMOD:
540 : {
541 0 : GEN X = gel(x,1);
542 0 : long d = degpol(X);
543 0 : if (d < 2) return x;
544 0 : if (d == 2) return mkpolmod(quad_polmod_conj(gel(x,2), X), X);
545 : }
546 : }
547 0 : pari_err_TYPE("gconj",x);
548 : return NULL; /* LCOV_EXCL_LINE */
549 : }
550 : GEN
551 99233 : gconj(GEN x)
552 99233 : { pari_sp av = avma; return gerepilecopy(av, conj_i(x)); }
553 :
554 : GEN
555 84 : conjvec(GEN x,long prec)
556 : {
557 : long lx, s, i;
558 : GEN z;
559 :
560 84 : switch(typ(x))
561 : {
562 0 : case t_INT: case t_INTMOD: case t_FRAC:
563 0 : return mkcolcopy(x);
564 :
565 0 : case t_COMPLEX: case t_QUAD:
566 0 : z=cgetg(3,t_COL); gel(z,1) = gcopy(x); gel(z,2) = gconj(x); break;
567 :
568 28 : case t_FFELT:
569 28 : return FF_conjvec(x);
570 :
571 0 : case t_VEC: case t_COL:
572 0 : lx = lg(x); z = cgetg(lx,t_MAT);
573 0 : if (lx == 1) return z;
574 0 : gel(z,1) = conjvec(gel(x,1),prec);
575 0 : s = lgcols(z);
576 0 : for (i=2; i<lx; i++)
577 : {
578 0 : gel(z,i) = conjvec(gel(x,i),prec);
579 0 : if (lg(gel(z,i)) != s) pari_err_OP("conjvec", gel(z,1), gel(z,i));
580 : }
581 0 : break;
582 :
583 56 : case t_POLMOD: {
584 56 : GEN T = gel(x,1), r;
585 : pari_sp av;
586 :
587 56 : lx = lg(T);
588 56 : if (lx <= 3) return cgetg(1,t_COL);
589 56 : x = gel(x,2);
590 238 : for (i=2; i<lx; i++)
591 : {
592 189 : GEN c = gel(T,i);
593 189 : switch(typ(c)) {
594 7 : case t_INTMOD: {
595 7 : GEN p = gel(c,1);
596 : pari_sp av;
597 7 : if (typ(x) != t_POL) retconst_col(lx-3, Rg_to_Fp(x, p));
598 7 : av = avma;
599 7 : T = RgX_to_FpX(T,p);
600 7 : x = RgX_to_FpX(x, p);
601 7 : if (varn(x) != varn(T)) pari_err_VAR("conjvec",x,T);
602 7 : z = FpXQC_to_mod(FpXQ_conjvec(x, T , p), T, p);
603 7 : return gerepileupto(av, z);
604 : }
605 182 : case t_INT:
606 182 : case t_FRAC: break;
607 0 : default: pari_err_TYPE("conjvec [not a rational t_POL]",T);
608 : }
609 : }
610 49 : if (typ(x) != t_POL)
611 : {
612 0 : if (!is_rational_t(typ(x)))
613 0 : pari_err_TYPE("conjvec [not a rational t_POL]",x);
614 0 : retconst_col(lx-3, gcopy(x));
615 : }
616 49 : RgX_check_QX(x,"conjvec");
617 49 : av = avma;
618 49 : if (varn(x) != varn(T)) pari_err_VAR("conjvec",x,T);
619 49 : r = cleanroots(T,prec);
620 49 : z = cgetg(lx-2,t_COL);
621 182 : for (i=1; i<=lx-3; i++) gel(z,i) = poleval(x, gel(r,i));
622 49 : return gerepileupto(av, z);
623 : }
624 :
625 0 : default:
626 0 : pari_err_TYPE("conjvec",x);
627 : return NULL; /* LCOV_EXCL_LINE */
628 : }
629 0 : return z;
630 : }
631 :
632 : /********************************************************************/
633 : /** **/
634 : /** ADDITION **/
635 : /** **/
636 : /********************************************************************/
637 : /* x, y compatible PADIC, op = add or sub */
638 : static GEN
639 8054587 : addsub_pp(GEN x, GEN y, GEN (*op)(GEN,GEN))
640 : {
641 8054587 : pari_sp av = avma;
642 : long d,e,r,rx,ry;
643 8054587 : GEN u, z, mod, p = gel(x,2);
644 : int swap;
645 :
646 8054587 : (void)new_chunk(5 + lgefint(gel(x,3)) + lgefint(gel(y,3)));
647 8054269 : e = valp(x);
648 8054269 : r = valp(y); d = r-e;
649 8054269 : if (d < 0) { swap = 1; swap(x,y); e = r; d = -d; } else swap = 0;
650 8054269 : rx = precp(x);
651 8054269 : ry = precp(y);
652 8054269 : if (d) /* v(x) < v(y) */
653 : {
654 5545880 : r = d+ry; z = powiu(p,d);
655 5546038 : if (r < rx) mod = mulii(z,gel(y,3)); else { r = rx; mod = gel(x,3); }
656 5546061 : z = mulii(z,gel(y,4));
657 5545997 : u = swap? op(z, gel(x,4)): op(gel(x,4), z);
658 : }
659 : else
660 : {
661 : long c;
662 2508389 : if (ry < rx) { r=ry; mod = gel(y,3); } else { r=rx; mod = gel(x,3); }
663 2508389 : u = swap? op(gel(y,4), gel(x,4)): op(gel(x,4), gel(y,4));
664 2509179 : if (!signe(u) || (c = Z_pvalrem(u,p,&u)) >= r)
665 : {
666 137789 : set_avma(av); return zeropadic(p, e+r);
667 : }
668 2371116 : if (c)
669 : {
670 1340879 : mod = diviiexact(mod, powiu(p,c));
671 1340880 : r -= c;
672 1340880 : e += c;
673 : }
674 : }
675 7917075 : u = modii(u, mod);
676 7915778 : set_avma(av); z = cgetg(5,t_PADIC);
677 7915261 : z[1] = evalprecp(r) | evalvalp(e);
678 7915130 : gel(z,2) = icopy(p);
679 7915288 : gel(z,3) = icopy(mod);
680 7915332 : gel(z,4) = icopy(u); return z;
681 : }
682 : /* Rg_to_Fp(t_FRAC) without GC */
683 : static GEN
684 24003 : Q_to_Fp(GEN x, GEN p)
685 24003 : { return mulii(gel(x,1), Fp_inv(gel(x,2),p)); }
686 : /* return x + y, where y t_PADIC and x is a nonzero t_INT or t_FRAC */
687 : static GEN
688 2405462 : addQp(GEN x, GEN y)
689 : {
690 2405462 : pari_sp av = avma;
691 2405462 : long d, r, e, vy = valp(y), py = precp(y);
692 2405462 : GEN z, q, mod, u, p = gel(y,2);
693 :
694 2405462 : e = Q_pvalrem(x, p, &x);
695 2405468 : d = vy - e; r = d + py;
696 2405468 : if (r <= 0) { set_avma(av); return gcopy(y); }
697 2403508 : mod = gel(y,3);
698 2403508 : u = gel(y,4);
699 2403508 : (void)new_chunk(5 + ((lgefint(mod) + lgefint(p)*labs(d)) << 1));
700 :
701 2403487 : if (d > 0)
702 : {
703 622009 : q = powiu(p,d);
704 622095 : mod = mulii(mod, q);
705 622092 : if (typ(x) != t_INT) x = Q_to_Fp(x, mod);
706 622092 : u = addii(x, mulii(u, q));
707 : }
708 1781478 : else if (d < 0)
709 : {
710 245660 : q = powiu(p,-d);
711 245660 : if (typ(x) != t_INT) x = Q_to_Fp(x, mod);
712 245660 : u = addii(u, mulii(x, q));
713 245660 : r = py; e = vy;
714 : }
715 : else
716 : {
717 : long c;
718 1535818 : if (typ(x) != t_INT) x = Q_to_Fp(x, mod);
719 1535818 : u = addii(u, x);
720 1535818 : if (!signe(u) || (c = Z_pvalrem(u,p,&u)) >= r)
721 : {
722 1047 : set_avma(av); return zeropadic(p,e+r);
723 : }
724 1534767 : if (c)
725 : {
726 490449 : mod = diviiexact(mod, powiu(p,c));
727 490448 : r -= c;
728 490448 : e += c;
729 : }
730 : }
731 2402521 : u = modii(u, mod); set_avma(av);
732 2402454 : z = cgetg(5,t_PADIC);
733 2402408 : z[1] = evalprecp(r) | evalvalp(e);
734 2402396 : gel(z,2) = icopy(p);
735 2402405 : gel(z,3) = icopy(mod);
736 2402424 : gel(z,4) = icopy(u); return z;
737 : }
738 :
739 : /* Mod(x,X) + Mod(y,X) */
740 : #define addsub_polmod_same addsub_polmod_scal
741 : /* Mod(x,X) +/- Mod(y,Y) */
742 : static GEN
743 2142 : addsub_polmod(GEN X, GEN Y, GEN x, GEN y, GEN(*op)(GEN,GEN))
744 : {
745 2142 : long T[3] = { evaltyp(t_POLMOD) | _evallg(3),0,0 };
746 2142 : GEN z = cgetg(3,t_POLMOD);
747 2142 : long vx = varn(X), vy = varn(Y);
748 2142 : if (vx==vy) {
749 : pari_sp av;
750 14 : gel(z,1) = RgX_gcd(X,Y); av = avma;
751 14 : warn_coercion(X,Y,gel(z,1));
752 14 : gel(z,2) = gerepileupto(av, gmod(op(x, y), gel(z,1))); return z;
753 : }
754 2128 : if (varncmp(vx, vy) < 0)
755 2128 : { gel(z,1) = RgX_copy(X); gel(T,1) = Y; gel(T,2) = y; y = T; }
756 : else
757 0 : { gel(z,1) = RgX_copy(Y); gel(T,1) = X; gel(T,2) = x; x = T; }
758 2128 : gel(z,2) = op(x, y); return z;
759 : }
760 : /* Mod(y, Y) +/- x, x scalar or polynomial in same var and reduced degree */
761 : static GEN
762 12876279 : addsub_polmod_scal(GEN Y, GEN y, GEN x, GEN(*op)(GEN,GEN))
763 12876279 : { retmkpolmod(degpol(Y)? op(y, x): gen_0, RgX_copy(Y)); }
764 :
765 : /* typ(y) == t_SER, x "scalar" [e.g object in lower variable] */
766 : static GEN
767 396649 : add_ser_scal(GEN y, GEN x)
768 : {
769 : long i, v, ly, vy;
770 : GEN z;
771 :
772 396649 : if (isrationalzero(x)) return gcopy(y);
773 371330 : ly = lg(y);
774 371330 : v = valser(y);
775 371330 : if (v < 3-ly) return gcopy(y);
776 : /* v + ly >= 3 */
777 371106 : if (v < 0)
778 : {
779 1169 : z = cgetg(ly,t_SER); z[1] = y[1];
780 3304 : for (i = 2; i <= 1-v; i++) gel(z,i) = gcopy(gel(y,i));
781 1169 : gel(z,i) = gadd(x,gel(y,i)); i++;
782 3276 : for ( ; i < ly; i++) gel(z,i) = gcopy(gel(y,i));
783 1169 : return normalizeser(z);
784 : }
785 369937 : vy = varn(y);
786 369937 : if (v > 0)
787 : {
788 16450 : if (ser_isexactzero(y))
789 7770 : return scalarser(ly == 2? x: gadd(x,gel(y,2)), vy, v);
790 8680 : y -= v; ly += v;
791 8680 : z = cgetg(ly,t_SER);
792 8680 : x = gcopy(x);
793 19278 : for (i=3; i<=v+1; i++) gel(z,i) = gen_0;
794 : }
795 353487 : else if (ser_isexactzero(y)) return gcopy(y);
796 : else
797 : { /* v = 0, ly >= 3 */
798 353480 : z = cgetg(ly,t_SER);
799 353480 : x = gadd(x, gel(y,2));
800 353480 : i = 3;
801 : }
802 1588528 : for (; i<ly; i++) gel(z,i) = gcopy(gel(y,i));
803 362160 : gel(z,2) = x;
804 362160 : z[1] = evalsigne(1) | _evalvalser(0) | evalvarn(vy);
805 362160 : return gequal0(x)? normalizeser(z): z;
806 : }
807 : static long
808 7063586 : _serprec(GEN x) { return ser_isexactzero(x)? 2: lg(x); }
809 : /* x,y t_SER in the same variable: x+y */
810 : static GEN
811 3532192 : ser_add(GEN x, GEN y)
812 : {
813 3532192 : long i, lx,ly, n = valser(y) - valser(x);
814 : GEN z;
815 3532192 : if (n < 0) { n = -n; swap(x,y); }
816 : /* valser(x) <= valser(y) */
817 3532192 : lx = _serprec(x);
818 3532192 : if (lx == 2) /* don't lose type information */
819 : {
820 798 : z = scalarser(gadd(Rg_get_0(x), Rg_get_0(y)), varn(x), 1);
821 798 : setvalser(z, valser(x)); return z;
822 : }
823 3531394 : ly = _serprec(y) + n; if (lx < ly) ly = lx;
824 3531394 : if (n)
825 : {
826 107152 : if (n+2 > lx) return gcopy(x);
827 106578 : z = cgetg(ly,t_SER);
828 816715 : for (i=2; i<=n+1; i++) gel(z,i) = gcopy(gel(x,i));
829 505091 : for ( ; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i-n));
830 : } else {
831 3424242 : z = cgetg(ly,t_SER);
832 17326973 : for (i=2; i < ly; i++) gel(z,i) = gadd(gel(x,i),gel(y,i));
833 : }
834 3530820 : z[1] = x[1]; return normalizeser(z);
835 : }
836 : /* typ(y) == RFRAC, x polynomial in same variable or "scalar" */
837 : static GEN
838 8830973 : add_rfrac_scal(GEN y, GEN x)
839 : {
840 : pari_sp av;
841 : GEN n;
842 :
843 8830973 : if (isintzero(x)) return gcopy(y); /* frequent special case */
844 5157173 : av = avma; n = gadd(gmul(x, gel(y,2)), gel(y,1));
845 5157173 : return gerepileupto(av, gred_rfrac_simple(n, gel(y,2)));
846 : }
847 :
848 : /* x "scalar", ty != t_MAT and nonscalar */
849 : static GEN
850 22603410 : add_scal(GEN y, GEN x, long ty)
851 : {
852 22603410 : switch(ty)
853 : {
854 17707562 : case t_POL: return RgX_Rg_add(y, x);
855 396621 : case t_SER: return add_ser_scal(y, x);
856 4468806 : case t_RFRAC: return add_rfrac_scal(y, x);
857 0 : case t_COL: return RgC_Rg_add(y, x);
858 30414 : case t_VEC:
859 30414 : if (isintzero(x)) return gcopy(y);
860 182 : break;
861 : }
862 189 : pari_err_TYPE2("+",x,y);
863 : return NULL; /* LCOV_EXCL_LINE */
864 : }
865 :
866 : /* assumes z = cget(3, t_FRAC) comes first in stack, then a, then b */
867 : static GEN
868 13654496 : setfrac(GEN z, GEN a, GEN b)
869 : {
870 13654496 : gel(z,1) = icopy_avma(a, (pari_sp)z);
871 13654556 : gel(z,2) = icopy_avma(b, (pari_sp)gel(z,1));
872 13654619 : set_avma((pari_sp)gel(z,2)); return z;
873 : }
874 : /* z <- a / (b*Q), (Q,a) = 1 */
875 : static GEN
876 12599115 : addsub_frac_i(GEN z, GEN Q, GEN a, GEN b)
877 : {
878 12599115 : GEN q = Qdivii(a, b); /* != 0 */
879 12599245 : if (typ(q) == t_INT)
880 : {
881 1494238 : gel(z,1) = gerepileuptoint((pari_sp)Q, q);
882 1494238 : gel(z,2) = Q; return z;
883 : }
884 11105007 : return setfrac(z, gel(q,1), mulii(gel(q,2), Q));
885 : }
886 : static GEN
887 26104285 : addsub_frac(GEN x, GEN y, GEN (*op)(GEN,GEN))
888 : {
889 26104285 : GEN x1 = gel(x,1), x2 = gel(x,2);
890 26104285 : GEN y1 = gel(y,1), y2 = gel(y,2), z, Q, q, r, n, delta;
891 26104285 : int s = cmpii(x2, y2);
892 :
893 : /* common denominator: (x1 op y1) / x2 */
894 26104288 : if (!s)
895 : {
896 9412441 : pari_sp av = avma;
897 9412441 : return gerepileupto(av, Qdivii(op(x1, y1), x2));
898 : }
899 16691847 : z = cgetg(3, t_FRAC);
900 16691861 : if (s < 0)
901 : {
902 9424486 : Q = dvmdii(y2, x2, &r);
903 : /* y2 = Q x2: 1/x2 . (Q x1 op y1)/Q, where latter is in coprime form */
904 9424390 : if (r == gen_0) return addsub_frac_i(z, Q, op(mulii(Q,x1), y1), x2);
905 2737930 : delta = gcdii(x2,r);
906 : }
907 : else
908 : {
909 7267375 : Q = dvmdii(x2, y2, &r);
910 : /* x2 = Q y2: 1/y2 . (x1 op Q y1)/Q, where latter is in coprime form */
911 7267385 : if (r == gen_0) return addsub_frac_i(z, Q, op(x1, mulii(Q,y1)), y2);
912 1354636 : delta = gcdii(y2,r);
913 : }
914 : /* delta = gcd(x2,y2) */
915 4092605 : if (equali1(delta))
916 : { /* numerator is nonzero */
917 1542983 : gel(z,1) = gerepileuptoint((pari_sp)z, op(mulii(x1,y2), mulii(y1,x2)));
918 1542983 : gel(z,2) = mulii(x2,y2); return z;
919 : }
920 2549615 : x2 = diviiexact(x2,delta);
921 2549622 : y2 = diviiexact(y2,delta);
922 2549623 : n = op(mulii(x1,y2), mulii(y1,x2)); /* != 0 */
923 2549626 : q = dvmdii(n, delta, &r);
924 2549629 : if (r == gen_0) return setfrac(z, q, mulii(x2, y2));
925 2306445 : r = gcdii(delta, r);
926 2306445 : if (!equali1(r)) { n = diviiexact(n, r); delta = diviiexact(delta, r); }
927 2306445 : return setfrac(z, n, mulii(mulii(x2, y2), delta));
928 : }
929 :
930 : /* assume x2, y2 are t_POLs in the same variable */
931 : static GEN
932 3039474 : add_rfrac(GEN x, GEN y)
933 : {
934 3039474 : pari_sp av = avma;
935 3039474 : GEN x1 = gel(x,1), x2 = gel(x,2);
936 3039474 : GEN y1 = gel(y,1), y2 = gel(y,2), q, r, n, d, delta;
937 :
938 3039474 : delta = RgX_gcd(x2,y2);
939 3039474 : if (!degpol(delta))
940 : {
941 672 : n = simplify_shallow( gadd(gmul(x1,y2), gmul(y1,x2)) );
942 672 : d = RgX_mul(x2, y2);
943 672 : return gerepileupto(av, gred_rfrac_simple(n, d));
944 : }
945 3038802 : x2 = RgX_div(x2,delta);
946 3038802 : y2 = RgX_div(y2,delta);
947 3038802 : n = gadd(gmul(x1,y2), gmul(y1,x2));
948 3038802 : if (!signe(n))
949 : {
950 721425 : n = simplify_shallow(n);
951 721425 : if (isexactzero(n))
952 : {
953 721418 : if (isrationalzero(n)) { set_avma(av); return zeropol(varn(x2)); }
954 14 : return gerepileupto(av, scalarpol(n, varn(x2)));
955 : }
956 7 : return gerepilecopy(av, mkrfrac(n, RgX_mul(gel(x,2),y2)));
957 : }
958 2317377 : if (degpol(n) == 0)
959 1150596 : return gerepileupto(av, gred_rfrac_simple(gel(n,2), RgX_mul(gel(x,2),y2)));
960 1166781 : q = RgX_divrem(n, delta, &r); /* we want gcd(n,delta) */
961 1166781 : if (isexactzero(r))
962 : {
963 : GEN z;
964 228087 : d = RgX_mul(x2, y2);
965 : /* "constant" denominator ? */
966 228087 : z = lg(d) == 3? RgX_Rg_div(q, gel(d,2)): gred_rfrac_simple(q, d);
967 228087 : return gerepileupto(av, z);
968 : }
969 938694 : r = RgX_gcd(delta, r);
970 938694 : if (degpol(r))
971 : {
972 160726 : n = RgX_div(n, r);
973 160726 : d = RgX_mul(RgX_mul(x2,y2), RgX_div(delta, r));
974 : }
975 : else
976 777968 : d = RgX_mul(gel(x,2), y2);
977 938694 : return gerepileupto(av, gred_rfrac_simple(n, d));
978 : }
979 :
980 : GEN
981 5554058549 : gadd(GEN x, GEN y)
982 : {
983 5554058549 : long tx = typ(x), ty = typ(y), vx, vy, lx, i, l;
984 : pari_sp av, tetpil;
985 : GEN z, p1;
986 :
987 5554058549 : if (tx == ty) switch(tx) /* shortcut to generic case */
988 : {
989 2803029102 : case t_INT: return addii(x,y);
990 1520854755 : case t_REAL: return addrr(x,y);
991 1521968 : case t_INTMOD: { GEN X = gel(x,1), Y = gel(y,1);
992 1521968 : z = cgetg(3,t_INTMOD);
993 1521968 : if (X==Y || equalii(X,Y))
994 1521954 : return add_intmod_same(z, X, gel(x,2), gel(y,2));
995 14 : gel(z,1) = gcdii(X,Y);
996 14 : warn_coercion(X,Y,gel(z,1));
997 14 : av = avma; p1 = addii(gel(x,2),gel(y,2));
998 14 : gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z;
999 : }
1000 21077581 : case t_FRAC: return addsub_frac(x,y,addii);
1001 327358891 : case t_COMPLEX: z = cgetg(3,t_COMPLEX);
1002 327828847 : gel(z,2) = gadd(gel(x,2),gel(y,2));
1003 327466350 : if (isintzero(gel(z,2)))
1004 : {
1005 363258 : set_avma((pari_sp)(z+3));
1006 363258 : return gadd(gel(x,1),gel(y,1));
1007 : }
1008 326955918 : gel(z,1) = gadd(gel(x,1),gel(y,1));
1009 327129303 : return z;
1010 2655792 : case t_PADIC:
1011 2655792 : if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("+",x,y);
1012 2655492 : return addsub_pp(x,y, addii);
1013 672 : case t_QUAD: z = cgetg(4,t_QUAD);
1014 672 : if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("+",x,y);
1015 672 : gel(z,1) = ZX_copy(gel(x,1));
1016 672 : gel(z,2) = gadd(gel(x,2),gel(y,2));
1017 672 : gel(z,3) = gadd(gel(x,3),gel(y,3)); return z;
1018 9908934 : case t_POLMOD:
1019 9908934 : if (RgX_equal_var(gel(x,1), gel(y,1)))
1020 9906827 : return addsub_polmod_same(gel(x,1), gel(x,2), gel(y,2), &gadd);
1021 2107 : return addsub_polmod(gel(x,1), gel(y,1), gel(x,2), gel(y,2), &gadd);
1022 14006088 : case t_FFELT: return FF_add(x,y);
1023 65902323 : case t_POL:
1024 65902323 : vx = varn(x);
1025 65902323 : vy = varn(y);
1026 65902323 : if (vx != vy) {
1027 872102 : if (varncmp(vx, vy) < 0) return RgX_Rg_add(x, y);
1028 65742 : else return RgX_Rg_add(y, x);
1029 : }
1030 65030221 : return RgX_add(x, y);
1031 3526928 : case t_SER:
1032 3526928 : vx = varn(x);
1033 3526928 : vy = varn(y);
1034 3526928 : if (vx != vy) {
1035 28 : if (varncmp(vx, vy) < 0) return add_ser_scal(x, y);
1036 21 : else return add_ser_scal(y, x);
1037 : }
1038 3526900 : return ser_add(x, y);
1039 4331375 : case t_RFRAC:
1040 4331375 : vx = varn(gel(x,2));
1041 4331375 : vy = varn(gel(y,2));
1042 4331375 : if (vx != vy) {
1043 1291901 : if (varncmp(vx, vy) < 0) return add_rfrac_scal(x, y);
1044 538397 : else return add_rfrac_scal(y, x);
1045 : }
1046 3039474 : return add_rfrac(x,y);
1047 407308 : case t_VEC:
1048 407308 : if (lg(y) != lg(x)) pari_err_OP("+",x,y);
1049 407308 : return RgV_add(x,y);
1050 1098530 : case t_COL:
1051 1098530 : if (lg(y) != lg(x)) pari_err_OP("+",x,y);
1052 1098530 : return RgC_add(x,y);
1053 671307 : case t_MAT:
1054 671307 : lx = lg(x);
1055 671307 : if (lg(y) != lx) pari_err_OP("+",x,y);
1056 671307 : if (lx == 1) return cgetg(1, t_MAT);
1057 671307 : if (lgcols(y) != lgcols(x)) pari_err_OP("+",x,y);
1058 671300 : return RgM_add(x,y);
1059 :
1060 0 : default: pari_err_TYPE2("+",x,y);
1061 : }
1062 : /* tx != ty */
1063 783379618 : if (tx > ty) { swap(x,y); lswap(tx,ty); }
1064 :
1065 783379618 : if (is_const_t(ty)) switch(tx) /* tx < ty, is_const_t(tx) && is_const_t(ty) */
1066 : {
1067 697907872 : case t_INT:
1068 : switch(ty)
1069 : {
1070 408346628 : case t_REAL: return addir(x,y);
1071 2139174 : case t_INTMOD:
1072 2139174 : z = cgetg(3, t_INTMOD);
1073 2139174 : return add_intmod_same(z, gel(y,1), gel(y,2), modii(x, gel(y,1)));
1074 43814109 : case t_FRAC: z = cgetg(3,t_FRAC);
1075 43814101 : gel(z,1) = gerepileuptoint((pari_sp)z, addii(gel(y,1), mulii(gel(y,2),x)));
1076 43814090 : gel(z,2) = icopy(gel(y,2)); return z;
1077 239068122 : case t_COMPLEX: return addRc(x, y);
1078 3228295 : case t_PADIC:
1079 3228295 : if (!signe(x)) return gcopy(y);
1080 2379325 : return addQp(x,y);
1081 1113 : case t_QUAD: return addRq(x, y);
1082 1356574 : case t_FFELT: return FF_Z_add(y,x);
1083 : }
1084 :
1085 : case t_REAL:
1086 51517644 : switch(ty)
1087 : {
1088 13730328 : case t_FRAC:
1089 13730328 : if (!signe(gel(y,1))) return rcopy(x);
1090 13730328 : if (!signe(x))
1091 : {
1092 11714 : lx = expi(gel(y,1)) - expi(gel(y,2)) - expo(x);
1093 11714 : return lx <= 0? rcopy(x): fractor(y, nbits2prec(lx));
1094 : }
1095 13718614 : av=avma; z=addir(gel(y,1),mulir(gel(y,2),x)); tetpil=avma;
1096 13717076 : return gerepile(av,tetpil,divri(z,gel(y,2)));
1097 37787246 : case t_COMPLEX: return addRc(x, y);
1098 70 : case t_QUAD: return gequal0(y)? rcopy(x): addqf(y, x, lg(x));
1099 :
1100 0 : default: pari_err_TYPE2("+",x,y);
1101 : }
1102 :
1103 17640 : case t_INTMOD:
1104 : switch(ty)
1105 : {
1106 17507 : case t_FRAC: { GEN X = gel(x,1);
1107 17507 : z = cgetg(3, t_INTMOD);
1108 17507 : p1 = Fp_div(gel(y,1), gel(y,2), X);
1109 17507 : return add_intmod_same(z, X, p1, gel(x,2));
1110 : }
1111 14 : case t_FFELT:
1112 14 : if (!equalii(gel(x,1),FF_p_i(y)))
1113 0 : pari_err_OP("+",x,y);
1114 14 : return FF_Z_add(y,gel(x,2));
1115 91 : case t_COMPLEX: return addRc(x, y);
1116 0 : case t_PADIC: { GEN X = gel(x,1);
1117 0 : z = cgetg(3, t_INTMOD);
1118 0 : return add_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X));
1119 : }
1120 28 : case t_QUAD: return addRq(x, y);
1121 : }
1122 :
1123 : case t_FRAC:
1124 : switch (ty)
1125 : {
1126 10528264 : case t_COMPLEX: return addRc(x, y);
1127 26138 : case t_PADIC:
1128 26138 : if (!signe(gel(x,1))) return gcopy(y);
1129 26138 : return addQp(x,y);
1130 133 : case t_QUAD: return addRq(x, y);
1131 1337 : case t_FFELT: return FF_Q_add(y, x);
1132 : }
1133 :
1134 : case t_FFELT:
1135 0 : pari_err_TYPE2("+",x,y);
1136 :
1137 35 : case t_COMPLEX:
1138 : switch(ty)
1139 : {
1140 28 : case t_PADIC:
1141 28 : return Zp_nosquare_m1(gel(y,2))? addRc(y, x): addTp(x, y);
1142 7 : case t_QUAD:
1143 7 : lx = precision(x); if (!lx) pari_err_OP("+",x,y);
1144 7 : return gequal0(y)? gcopy(x): addqf(y, x, lx);
1145 : }
1146 :
1147 : case t_PADIC: /* ty == t_QUAD */
1148 0 : return (kro_quad(y,gel(x,2)) == -1)? addRq(x, y): addTp(y, x);
1149 : }
1150 : /* tx < ty, !is_const_t(y) */
1151 28064867 : switch(ty)
1152 : {
1153 8017 : case t_MAT:
1154 8017 : if (is_matvec_t(tx)) pari_err_TYPE2("+",x,y);
1155 8017 : if (isrationalzero(x)) return gcopy(y);
1156 7940 : return RgM_Rg_add(y, x);
1157 206611 : case t_COL:
1158 206611 : if (tx == t_VEC) pari_err_TYPE2("+",x,y);
1159 206611 : return RgC_Rg_add(y, x);
1160 2129857 : case t_POLMOD: /* is_const_t(tx) in this case */
1161 2129857 : return addsub_polmod_scal(gel(y,1), gel(y,2), x, &gadd);
1162 : }
1163 25720382 : if (is_scalar_t(tx)) {
1164 22621600 : if (tx == t_POLMOD)
1165 : {
1166 107322 : vx = varn(gel(x,1));
1167 107322 : vy = gvar(y);
1168 107322 : if (vx == vy) y = gmod(y, gel(x,1)); /* error if ty == t_SER */
1169 : else
1170 81485 : if (varncmp(vx,vy) > 0) return add_scal(y, x, ty);
1171 40880 : return addsub_polmod_scal(gel(x,1), gel(x,2), y, &gadd);
1172 : }
1173 22514278 : return add_scal(y, x, ty);
1174 : }
1175 : /* x and y are not scalars, ty != t_MAT */
1176 3098768 : vx = gvar(x);
1177 3098772 : vy = gvar(y);
1178 3098772 : if (vx != vy) { /* x or y is treated as a scalar */
1179 22703 : if (is_vec_t(tx) || is_vec_t(ty)) pari_err_TYPE2("+",x,y);
1180 32298 : return (varncmp(vx, vy) < 0)? add_scal(x, y, tx)
1181 32298 : : add_scal(y, x, ty);
1182 : }
1183 : /* vx = vy */
1184 3076069 : switch(tx)
1185 : {
1186 3075579 : case t_POL:
1187 : switch (ty)
1188 : {
1189 5313 : case t_SER:
1190 5313 : if (lg(x) == 2) return gcopy(y);
1191 5299 : i = RgX_val(x); if (i == LONG_MAX) i = 0; /* e.g. x = Mod(0,3)*x^0 */
1192 5299 : i = lg(y) + valser(y) - i;
1193 5299 : if (i < 3) return gcopy(y);
1194 5292 : p1 = RgX_to_ser(x,i); y = ser_add(p1,y);
1195 5292 : settyp(p1, t_VECSMALL); /* p1 left on stack */
1196 5292 : return y;
1197 :
1198 3070266 : case t_RFRAC: return add_rfrac_scal(y, x);
1199 : }
1200 0 : break;
1201 :
1202 490 : case t_SER:
1203 490 : if (ty == t_RFRAC)
1204 : {
1205 : long vn, vd;
1206 490 : av = avma;
1207 490 : vn = gval(gel(y,1), vy);
1208 490 : vd = RgX_valrem_inexact(gel(y,2), NULL);
1209 490 : if (vd == LONG_MAX) pari_err_INV("gadd", gel(y,2));
1210 :
1211 490 : l = lg(x) + valser(x) - (vn - vd);
1212 490 : if (l < 3) { set_avma(av); return gcopy(x); }
1213 490 : return gerepileupto(av, gadd(x, rfrac_to_ser_i(y, l)));
1214 : }
1215 0 : break;
1216 : }
1217 0 : pari_err_TYPE2("+",x,y);
1218 : return NULL; /* LCOV_EXCL_LINE */
1219 : }
1220 :
1221 : GEN
1222 287432931 : gaddsg(long x, GEN y)
1223 : {
1224 287432931 : long ty = typ(y);
1225 : GEN z;
1226 :
1227 287432931 : switch(ty)
1228 : {
1229 134413594 : case t_INT: return addsi(x,y);
1230 128773270 : case t_REAL: return addsr(x,y);
1231 11911 : case t_INTMOD:
1232 11911 : z = cgetg(3, t_INTMOD);
1233 11911 : return add_intmod_same(z, gel(y,1), gel(y,2), modsi(x, gel(y,1)));
1234 15254746 : case t_FRAC: z = cgetg(3,t_FRAC);
1235 15254746 : gel(z,1) = gerepileuptoint((pari_sp)z, addii(gel(y,1), mulis(gel(y,2),x)));
1236 15254746 : gel(z,2) = icopy(gel(y,2)); return z;
1237 8236344 : case t_COMPLEX:
1238 8236344 : z = cgetg(3, t_COMPLEX);
1239 8236344 : gel(z,1) = gaddsg(x, gel(y,1));
1240 8236344 : gel(z,2) = gcopy(gel(y,2)); return z;
1241 :
1242 743066 : default: return gadd(stoi(x), y);
1243 : }
1244 : }
1245 :
1246 : GEN
1247 3154922 : gsubsg(long x, GEN y)
1248 : {
1249 : GEN z, a, b;
1250 : pari_sp av;
1251 :
1252 3154922 : switch(typ(y))
1253 : {
1254 274953 : case t_INT: return subsi(x,y);
1255 1221984 : case t_REAL: return subsr(x,y);
1256 56 : case t_INTMOD:
1257 56 : z = cgetg(3, t_INTMOD); a = gel(y,1); b = gel(y,2);
1258 56 : return add_intmod_same(z, a, Fp_neg(b,a), modsi(x, a));
1259 729245 : case t_FRAC: z = cgetg(3,t_FRAC); a = gel(y,1); b = gel(y,2);
1260 729245 : gel(z,1) = gerepileuptoint((pari_sp)z, subii(mulis(b,x), a));
1261 729245 : gel(z,2) = icopy(gel(y,2)); return z;
1262 891802 : case t_COMPLEX:
1263 891802 : z = cgetg(3, t_COMPLEX);
1264 891802 : gel(z,1) = gsubsg(x, gel(y,1));
1265 891802 : gel(z,2) = gneg(gel(y,2)); return z;
1266 : }
1267 36882 : av = avma;
1268 36882 : return gerepileupto(av, gadd(stoi(x), gneg_i(y)));
1269 : }
1270 :
1271 : /********************************************************************/
1272 : /** **/
1273 : /** SUBTRACTION **/
1274 : /** **/
1275 : /********************************************************************/
1276 :
1277 : GEN
1278 2679976980 : gsub(GEN x, GEN y)
1279 : {
1280 2679976980 : long tx = typ(x), ty = typ(y);
1281 : pari_sp av;
1282 : GEN z;
1283 2679976980 : if (tx == ty) switch(tx) /* shortcut to generic case */
1284 : {
1285 2002845732 : case t_INT: return subii(x,y);
1286 508666619 : case t_REAL: return subrr(x,y);
1287 1158483 : case t_INTMOD: { GEN p1, X = gel(x,1), Y = gel(y,1);
1288 1158483 : z = cgetg(3,t_INTMOD);
1289 1158483 : if (X==Y || equalii(X,Y))
1290 1158469 : return sub_intmod_same(z, X, gel(x,2), gel(y,2));
1291 14 : gel(z,1) = gcdii(X,Y);
1292 14 : warn_coercion(X,Y,gel(z,1));
1293 14 : av = avma; p1 = subii(gel(x,2),gel(y,2));
1294 14 : gel(z,2) = gerepileuptoint(av, modii(p1, gel(z,1))); return z;
1295 : }
1296 5026712 : case t_FRAC: return addsub_frac(x,y, subii);
1297 93037834 : case t_COMPLEX: z = cgetg(3,t_COMPLEX);
1298 93075680 : gel(z,2) = gsub(gel(x,2),gel(y,2));
1299 92962874 : if (isintzero(gel(z,2)))
1300 : {
1301 21209 : set_avma((pari_sp)(z+3));
1302 21209 : return gsub(gel(x,1),gel(y,1));
1303 : }
1304 92947684 : gel(z,1) = gsub(gel(x,1),gel(y,1));
1305 92930621 : return z;
1306 5399144 : case t_PADIC:
1307 5399144 : if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("+",x,y);
1308 5399144 : return addsub_pp(x,y, subii);
1309 168 : case t_QUAD: z = cgetg(4,t_QUAD);
1310 168 : if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("+",x,y);
1311 168 : gel(z,1) = ZX_copy(gel(x,1));
1312 168 : gel(z,2) = gsub(gel(x,2),gel(y,2));
1313 168 : gel(z,3) = gsub(gel(x,3),gel(y,3)); return z;
1314 798750 : case t_POLMOD:
1315 798750 : if (RgX_equal_var(gel(x,1), gel(y,1)))
1316 798715 : return addsub_polmod_same(gel(x,1), gel(x,2), gel(y,2), &gsub);
1317 35 : return addsub_polmod(gel(x,1), gel(y,1), gel(x,2), gel(y,2), &gsub);
1318 203248 : case t_FFELT: return FF_sub(x,y);
1319 10252423 : case t_POL: {
1320 10252423 : long vx = varn(x);
1321 10252423 : long vy = varn(y);
1322 10252423 : if (vx != vy) {
1323 30217 : if (varncmp(vx, vy) < 0) return RgX_Rg_sub(x, y);
1324 5621 : else return Rg_RgX_sub(x, y);
1325 : }
1326 10222206 : return RgX_sub(x, y);
1327 : }
1328 297524 : case t_VEC:
1329 297524 : if (lg(y) != lg(x)) pari_err_OP("+",x,y);
1330 297524 : return RgV_sub(x,y);
1331 3296232 : case t_COL:
1332 3296232 : if (lg(y) != lg(x)) pari_err_OP("+",x,y);
1333 3296232 : return RgC_sub(x,y);
1334 223862 : case t_MAT: {
1335 223862 : long lx = lg(x);
1336 223862 : if (lg(y) != lx) pari_err_OP("+",x,y);
1337 223863 : if (lx == 1) return cgetg(1, t_MAT);
1338 144539 : if (lgcols(y) != lgcols(x)) pari_err_OP("+",x,y);
1339 144538 : return RgM_sub(x,y);
1340 : }
1341 2458152 : case t_RFRAC: case t_SER: break;
1342 :
1343 0 : default: pari_err_TYPE2("+",x,y);
1344 : }
1345 47936209 : av = avma;
1346 50394361 : return gerepileupto(av, gadd(x,gneg_i(y)));
1347 : }
1348 :
1349 : /********************************************************************/
1350 : /** **/
1351 : /** MULTIPLICATION **/
1352 : /** **/
1353 : /********************************************************************/
1354 : static GEN
1355 307237 : mul_ser_scal(GEN y, GEN x)
1356 : {
1357 : long l, i;
1358 : GEN z;
1359 307237 : if (isexactzero(x)) return gmul(Rg_get_0(y), x);
1360 303989 : if (ser_isexactzero(y))
1361 : {
1362 518 : z = scalarser(lg(y) == 2? Rg_get_0(x): gmul(gel(y,2), x), varn(y), 1);
1363 518 : setvalser(z, valser(y)); return z;
1364 : }
1365 303471 : z = cgetg_copy(y, &l); z[1] = y[1];
1366 4189451 : for (i = 2; i < l; i++) gel(z,i) = gmul(gel(y,i), x);
1367 303471 : return normalizeser(z);
1368 : }
1369 : /* (n/d) * x, x "scalar" or polynomial in the same variable as d
1370 : * [n/d a valid RFRAC] */
1371 : static GEN
1372 10456218 : mul_rfrac_scal(GEN n, GEN d, GEN x)
1373 : {
1374 10456218 : pari_sp av = avma;
1375 : GEN z;
1376 :
1377 10456218 : switch(typ(x))
1378 : {
1379 21 : case t_PADIC:
1380 21 : n = gmul(n, x);
1381 21 : d = gcvtop(d, gel(x,2), signe(gel(x,4))? precp(x): 1);
1382 21 : return gerepileupto(av, gdiv(n,d));
1383 :
1384 497 : case t_INTMOD: case t_POLMOD:
1385 497 : n = gmul(n, x);
1386 497 : d = gmul(d, gmodulo(gen_1, gel(x,1)));
1387 497 : return gerepileupto(av, gdiv(n,d));
1388 : }
1389 10455700 : z = gred_rfrac2(x, d);
1390 10455700 : n = simplify_shallow(n);
1391 10455700 : if (typ(z) == t_RFRAC)
1392 : {
1393 7936756 : n = gmul(gel(z,1), n);
1394 7936756 : d = gel(z,2);
1395 7936756 : if (typ(n) == t_POL && varncmp(varn(n), varn(d)) < 0)
1396 0 : z = RgX_Rg_div(n, d);
1397 : else
1398 7936756 : z = gred_rfrac_simple(n, d);
1399 : }
1400 : else
1401 2518944 : z = gmul(z, n);
1402 10455700 : return gerepileupto(av, z);
1403 : }
1404 : static GEN
1405 111433751 : mul_scal(GEN y, GEN x, long ty)
1406 : {
1407 111433751 : switch(ty)
1408 : {
1409 102547970 : case t_POL:
1410 102547970 : if (lg(y) == 2) return scalarpol(gmul(gen_0,x), varn(y));
1411 99389975 : return RgX_Rg_mul(y, x);
1412 299124 : case t_SER: return mul_ser_scal(y, x);
1413 8586662 : case t_RFRAC: return mul_rfrac_scal(gel(y,1),gel(y,2), x);
1414 14 : case t_QFB:
1415 14 : if (typ(x) == t_INT && gequal1(x)) return gcopy(y); /* fall through */
1416 : }
1417 12 : pari_err_TYPE2("*",x,y);
1418 : return NULL; /* LCOV_EXCL_LINE */
1419 : }
1420 :
1421 : static GEN
1422 160865 : mul_gen_rfrac(GEN X, GEN Y)
1423 : {
1424 160865 : GEN y1 = gel(Y,1), y2 = gel(Y,2);
1425 160865 : long vx = gvar(X), vy = varn(y2);
1426 166626 : return (varncmp(vx, vy) <= 0)? mul_scal(Y, X, typ(Y)):
1427 5761 : gred_rfrac_simple(gmul(y1,X), y2);
1428 : }
1429 : /* (x1/x2) * (y1/y2) */
1430 : static GEN
1431 7907114 : mul_rfrac(GEN x1, GEN x2, GEN y1, GEN y2)
1432 : {
1433 : GEN z, X, Y;
1434 7907114 : pari_sp av = avma;
1435 :
1436 7907114 : X = gred_rfrac2(x1, y2);
1437 7907114 : Y = gred_rfrac2(y1, x2);
1438 7907114 : if (typ(X) == t_RFRAC)
1439 : {
1440 6628032 : if (typ(Y) == t_RFRAC) {
1441 6562456 : x1 = gel(X,1);
1442 6562456 : x2 = gel(X,2);
1443 6562456 : y1 = gel(Y,1);
1444 6562456 : y2 = gel(Y,2);
1445 6562456 : z = gred_rfrac_simple(gmul(x1,y1), gmul(x2,y2));
1446 : } else
1447 65576 : z = mul_gen_rfrac(Y, X);
1448 : }
1449 1279082 : else if (typ(Y) == t_RFRAC)
1450 95289 : z = mul_gen_rfrac(X, Y);
1451 : else
1452 1183793 : z = gmul(X, Y);
1453 7907114 : return gerepileupto(av, z);
1454 : }
1455 : /* (x1/x2) /y2, x2 and y2 are t_POL in the same variable */
1456 : static GEN
1457 270821 : div_rfrac_pol(GEN x1, GEN x2, GEN y2)
1458 : {
1459 270821 : pari_sp av = avma;
1460 270821 : GEN X = gred_rfrac2(x1, y2);
1461 270821 : if (typ(X) == t_RFRAC && varn(gel(X,2)) == varn(x2))
1462 : {
1463 264255 : x2 = RgX_mul(gel(X,2), x2);
1464 264255 : x1 = gel(X,1);
1465 : }
1466 : else
1467 6566 : x1 = X;
1468 270821 : return gerepileupto(av, gred_rfrac_simple(x1, x2));
1469 : }
1470 :
1471 : /* Mod(y, Y) * x, assuming x scalar */
1472 : static GEN
1473 2633360 : mul_polmod_scal(GEN Y, GEN y, GEN x)
1474 2633360 : { retmkpolmod(gmul(x,y), RgX_copy(Y)); }
1475 :
1476 : /* cf mulqq */
1477 : static GEN
1478 5907724 : quad_polmod_mul(GEN P, GEN x, GEN y)
1479 : {
1480 5907724 : GEN T = cgetg(4, t_POL), b = gel(P,3), c = gel(P,2), p1, p2, p3, p4;
1481 5907724 : pari_sp tetpil, av = avma;
1482 5907724 : T[1] = x[1];
1483 5907724 : p2 = gmul(gel(x,2), gel(y,2));
1484 5907724 : p3 = gmul(gel(x,3), gel(y,3));
1485 5907724 : p1 = gmul(gneg_i(c),p3);
1486 : /* operands are usually small: gadd ~ gmul and Karatsuba is a waste */
1487 5907724 : if (typ(b) == t_INT)
1488 : {
1489 5907703 : if (signe(b))
1490 : {
1491 4335951 : p4 = gadd(gmul(gel(x,2), gel(y,3)), gmul(gel(x,3), gel(y,2)));
1492 4335951 : if (is_pm1(b))
1493 : {
1494 4335293 : if (signe(b) > 0) p3 = gneg(p3);
1495 : }
1496 : else
1497 658 : p3 = gmul(negi(b), p3);
1498 : }
1499 : else
1500 : {
1501 1571752 : p3 = gmul(gel(x,2),gel(y,3));
1502 1571752 : p4 = gmul(gel(x,3),gel(y,2));
1503 : }
1504 : }
1505 : else
1506 : {
1507 21 : p4 = gadd(gmul(gel(x,2), gel(y,3)), gmul(gel(x,3), gel(y,2)));
1508 21 : p3 = gmul(gneg_i(b), p3);
1509 : }
1510 5907724 : tetpil = avma;
1511 5907724 : gel(T,2) = gadd(p2, p1);
1512 5907724 : gel(T,3) = gadd(p4, p3);
1513 5907724 : gerepilecoeffssp(av,tetpil,T+2,2);
1514 5907724 : return normalizepol_lg(T,4);
1515 : }
1516 : /* Mod(x,T) * Mod(y,T) */
1517 : static GEN
1518 8072839 : mul_polmod_same(GEN T, GEN x, GEN y)
1519 : {
1520 8072839 : GEN z = cgetg(3,t_POLMOD), a;
1521 8072839 : long v = varn(T), lx = lg(x), ly = lg(y);
1522 8072839 : gel(z,1) = RgX_copy(T);
1523 : /* x * y mod T optimised */
1524 8072839 : if (typ(x) != t_POL || varn(x) != v || lx <= 3
1525 7440242 : || typ(y) != t_POL || varn(y) != v || ly <= 3)
1526 1503960 : a = gmul(x, y);
1527 : else
1528 : {
1529 6568879 : if (lg(T) == 5 && isint1(gel(T,4))) /* quadratic fields */
1530 5902488 : a = quad_polmod_mul(T, x, y);
1531 : else
1532 666391 : a = RgXQ_mul(x, y, gel(z,1));
1533 : }
1534 8072839 : gel(z,2) = a; return z;
1535 : }
1536 : static GEN
1537 67356 : sqr_polmod(GEN T, GEN x)
1538 : {
1539 67356 : GEN a, z = cgetg(3,t_POLMOD);
1540 67356 : gel(z,1) = RgX_copy(T);
1541 67356 : if (typ(x) != t_POL || varn(x) != varn(T) || lg(x) <= 3)
1542 14247 : a = gsqr(x);
1543 : else
1544 : {
1545 53109 : pari_sp av = avma;
1546 53109 : a = RgXQ_sqr(x, gel(z,1));
1547 53109 : a = gerepileupto(av, a);
1548 : }
1549 67356 : gel(z,2) = a; return z;
1550 : }
1551 : /* Mod(x,X) * Mod(y,Y) */
1552 : static GEN
1553 2678207 : mul_polmod(GEN X, GEN Y, GEN x, GEN y)
1554 : {
1555 2678207 : long T[3] = { evaltyp(t_POLMOD) | _evallg(3),0,0 };
1556 2678207 : long vx = varn(X), vy = varn(Y);
1557 2678207 : GEN z = cgetg(3,t_POLMOD);
1558 :
1559 2678207 : if (vx==vy) {
1560 : pari_sp av;
1561 14 : gel(z,1) = RgX_gcd(X,Y); av = avma;
1562 14 : warn_coercion(X,Y,gel(z,1));
1563 14 : gel(z,2) = gerepileupto(av, gmod(gmul(x, y), gel(z,1)));
1564 14 : return z;
1565 : }
1566 2678193 : if (varncmp(vx, vy) < 0)
1567 414316 : { gel(z,1) = RgX_copy(X); gel(T,1) = Y; gel(T,2) = y; y = T; }
1568 : else
1569 2263877 : { gel(z,1) = RgX_copy(Y); gel(T,1) = X; gel(T,2) = x; x = T; }
1570 2678193 : gel(z,2) = gmul(x, y); return z;
1571 : }
1572 :
1573 : #if 0 /* used by 3M only */
1574 : /* set z = x+y and return 1 if x,y have the same sign
1575 : * set z = x-y and return 0 otherwise */
1576 : static int
1577 : did_add(GEN x, GEN y, GEN *z)
1578 : {
1579 : long tx = typ(x), ty = typ(y);
1580 : if (tx == ty) switch(tx)
1581 : {
1582 : case t_INT: *z = addii(x,y); return 1;
1583 : case t_FRAC: *z = addsub_frac(x,y,addii); return 1;
1584 : case t_REAL:
1585 : if (signe(x) == -signe(y))
1586 : { *z = subrr(x,y); return 0; }
1587 : else
1588 : { *z = addrr(x,y); return 1; }
1589 : }
1590 : if (tx == t_REAL) switch(ty)
1591 : {
1592 : case t_INT:
1593 : if (signe(x) == -signe(y))
1594 : { *z = subri(x,y); return 0; }
1595 : else
1596 : { *z = addri(x,y); return 1; }
1597 : case t_FRAC:
1598 : if (signe(x) == -signe(gel(y,1)))
1599 : { *z = gsub(x,y); return 0; }
1600 : else
1601 : { *z = gadd(x,y); return 1; }
1602 : }
1603 : else if (ty == t_REAL) switch(tx)
1604 : {
1605 : case t_INT:
1606 : if (signe(x) == -signe(y))
1607 : { *z = subir(x,y); return 0; }
1608 : else
1609 : { *z = addir(x,y); return 1; }
1610 : case t_FRAC:
1611 : if (signe(gel(x,1)) == -signe(y))
1612 : { *z = gsub(x,y); return 0; }
1613 : else
1614 : { *z = gadd(x,y); return 1; }
1615 : }
1616 : *z = gadd(x,y); return 1;
1617 : }
1618 : #endif
1619 : /* x * I * y, x t_COMPLEX with non-intzero real part, y non-intzero "scalar" */
1620 : static GEN
1621 11033428 : mulcIR(GEN x, GEN y)
1622 : {
1623 11033428 : GEN z = cgetg(3,t_COMPLEX);
1624 11033615 : pari_sp av = avma;
1625 11033615 : gel(z,1) = gerepileupto(av, gneg(gmul(y,gel(x,2))));
1626 11033838 : gel(z,2) = gmul(y, gel(x,1));
1627 11033558 : return z;
1628 :
1629 : }
1630 : /* x,y COMPLEX */
1631 : static GEN
1632 249264937 : mulcc(GEN x, GEN y)
1633 : {
1634 249264937 : GEN xr = gel(x,1), xi = gel(x,2);
1635 249264937 : GEN yr = gel(y,1), yi = gel(y,2);
1636 : GEN p1, p2, p3, p4, z;
1637 : pari_sp tetpil, av;
1638 :
1639 249264937 : if (isintzero(xr))
1640 : {
1641 15349265 : if (isintzero(yr)) {
1642 7165548 : av = avma;
1643 7165548 : return gerepileupto(av, gneg(gmul(xi,yi)));
1644 : }
1645 8183516 : return mulcIR(y, xi);
1646 : }
1647 233914740 : if (isintzero(yr)) return mulcIR(x, yi);
1648 :
1649 231074728 : z = cgetg(3,t_COMPLEX); av = avma;
1650 : #if 0
1651 : /* 3M method avoiding catastrophic cancellation, BUT loses accuracy due to
1652 : * e.g. xr + xi if exponents differ */
1653 : if (did_add(xr, xi, &p3))
1654 : {
1655 : if (did_add(yr, yi, &p4)) {
1656 : /* R = xr*yr - xi*yi
1657 : * I = (xr+xi)(yr+yi) - xr*yr - xi*yi */
1658 : p1 = gmul(xr,yr);
1659 : p2 = gmul(xi,yi); p2 = gneg(p2);
1660 : p3 = gmul(p3, p4);
1661 : p4 = gsub(p2, p1);
1662 : } else {
1663 : /* R = (xr + xi) * (yr - yi) + (xr * yi - xi * yr)
1664 : * I = xr*yi + xi*yr */
1665 : p1 = gmul(p3,p4);
1666 : p3 = gmul(xr,yi);
1667 : p4 = gmul(xi,yr);
1668 : p2 = gsub(p3, p4);
1669 : }
1670 : } else {
1671 : if (did_add(yr, yi, &p4)) {
1672 : /* R = (xr - xi) * (yr + yi) + (xi * yr - xr * yi)
1673 : * I = xr*yi +xi*yr */
1674 : p1 = gmul(p3,p4);
1675 : p3 = gmul(xr,yi);
1676 : p4 = gmul(xi,yr);
1677 : p2 = gsub(p4, p3);
1678 : } else {
1679 : /* R = xr*yr - xi*yi
1680 : * I = -(xr-xi)(yr-yi) + xr*yr + xi*yi */
1681 : p3 = gneg( gmul(p3, p4) );
1682 : p1 = gmul(xr,yr);
1683 : p2 = gmul(xi,yi);
1684 : p4 = gadd(p1, p2);
1685 :
1686 : p2 = gneg(p2);
1687 : }
1688 : }
1689 : tetpil = avma;
1690 : gel(z,1) = gadd(p1,p2);
1691 : gel(z,2) = gadd(p3,p4);
1692 : #else
1693 231094171 : if (typ(xr)==t_INT && typ(yr)==t_INT && typ(xi)==t_INT && typ(yi)==t_INT)
1694 : { /* 3M formula */
1695 558849 : p3 = addii(xr,xi);
1696 558849 : p4 = addii(yr,yi);
1697 558849 : p1 = mulii(xr,yr);
1698 558849 : p2 = mulii(xi,yi);
1699 558849 : p3 = mulii(p3,p4);
1700 558849 : p4 = addii(p2,p1);
1701 558849 : tetpil = avma;
1702 558849 : gel(z,1) = subii(p1,p2);
1703 558849 : gel(z,2) = subii(p3,p4);
1704 558849 : if (!signe(gel(z,2)))
1705 113225 : return gerepileuptoint((pari_sp)(z+3), gel(z,1));
1706 : }
1707 : else
1708 : { /* naive 4M formula: avoid all loss of accuracy */
1709 230535322 : p1 = gmul(xr,yr);
1710 230472825 : p2 = gmul(xi,yi);
1711 230451580 : p3 = gmul(xr,yi);
1712 230452607 : p4 = gmul(xi,yr);
1713 230457985 : tetpil = avma;
1714 230457985 : gel(z,1) = gsub(p1,p2);
1715 230369605 : gel(z,2) = gadd(p3,p4);
1716 230352035 : if (isintzero(gel(z,2)))
1717 : {
1718 49063 : cgiv(gel(z,2));
1719 49063 : return gerepileupto((pari_sp)(z+3), gel(z,1));
1720 : }
1721 : }
1722 : #endif
1723 :
1724 230754848 : gerepilecoeffssp(av,tetpil, z+1,2); return z;
1725 : }
1726 : /* x,y PADIC */
1727 : static GEN
1728 12949430 : mulpp(GEN x, GEN y) {
1729 12949430 : long l = valp(x) + valp(y);
1730 : pari_sp av;
1731 : GEN z, t;
1732 12949430 : if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("*",x,y);
1733 12949349 : if (!signe(gel(x,4))) return zeropadic(gel(x,2), l);
1734 12732922 : if (!signe(gel(y,4))) return zeropadic(gel(x,2), l);
1735 :
1736 12398371 : t = (precp(x) > precp(y))? y: x;
1737 12398371 : z = cgetp(t); setvalp(z,l); av = avma;
1738 12398532 : affii(remii(mulii(gel(x,4),gel(y,4)), gel(t,3)), gel(z,4));
1739 12398344 : set_avma(av); return z;
1740 : }
1741 : /* x,y QUAD */
1742 : static GEN
1743 1106 : mulqq(GEN x, GEN y) {
1744 1106 : GEN z = cgetg(4,t_QUAD);
1745 1106 : GEN p1, p2, p3, p4, P = gel(x,1), b = gel(P,3), c = gel(P,2);
1746 : pari_sp av, tetpil;
1747 1106 : if (!ZX_equal(P, gel(y,1))) pari_err_OP("*",x,y);
1748 :
1749 1106 : gel(z,1) = ZX_copy(P); av = avma;
1750 1106 : p2 = gmul(gel(x,2),gel(y,2));
1751 1106 : p3 = gmul(gel(x,3),gel(y,3));
1752 1106 : p1 = gmul(gneg_i(c),p3);
1753 :
1754 1106 : if (signe(b))
1755 987 : p4 = gadd(gmul(gel(x,2),gel(y,3)), gmul(gel(x,3),gel(y,2)));
1756 : else
1757 : {
1758 119 : p3 = gmul(gel(x,2),gel(y,3));
1759 119 : p4 = gmul(gel(x,3),gel(y,2));
1760 : }
1761 1106 : tetpil = avma;
1762 1106 : gel(z,2) = gadd(p2,p1);
1763 1106 : gel(z,3) = gadd(p4,p3);
1764 1106 : gerepilecoeffssp(av,tetpil,z+2,2); return z;
1765 : }
1766 :
1767 : GEN
1768 10500623 : mulcxI(GEN x)
1769 : {
1770 : GEN z;
1771 10500623 : switch(typ(x))
1772 : {
1773 1582003 : case t_INT: case t_REAL: case t_FRAC:
1774 1582003 : return mkcomplex(gen_0, x);
1775 8919081 : case t_COMPLEX:
1776 8919081 : if (isintzero(gel(x,1))) return gneg(gel(x,2));
1777 8918552 : z = cgetg(3,t_COMPLEX);
1778 8919116 : gel(z,1) = gneg(gel(x,2));
1779 8919593 : gel(z,2) = gel(x,1); return z;
1780 48 : default:
1781 48 : return gmul(gen_I(), x);
1782 : }
1783 : }
1784 : GEN
1785 198167 : mulcxmI(GEN x)
1786 : {
1787 : GEN z;
1788 198167 : switch(typ(x))
1789 : {
1790 84926 : case t_INT: case t_REAL: case t_FRAC:
1791 84926 : return mkcomplex(gen_0, gneg(x));
1792 113178 : case t_COMPLEX:
1793 113178 : if (isintzero(gel(x,1))) return gel(x,2);
1794 110567 : z = cgetg(3,t_COMPLEX);
1795 110567 : gel(z,1) = gel(x,2);
1796 110567 : gel(z,2) = gneg(gel(x,1)); return z;
1797 63 : default:
1798 63 : return gmul(mkcomplex(gen_0, gen_m1), x);
1799 : }
1800 : }
1801 : /* x * I^k */
1802 : GEN
1803 268250 : mulcxpowIs(GEN x, long k)
1804 : {
1805 268250 : switch (k & 3)
1806 : {
1807 50426 : case 1: return mulcxI(x);
1808 47646 : case 2: return gneg(x);
1809 52054 : case 3: return mulcxmI(x);
1810 : }
1811 118124 : return x;
1812 : }
1813 :
1814 : static GEN
1815 5626078 : init_ser(long l, long v, long e)
1816 : {
1817 5626078 : GEN z = cgetg(l, t_SER);
1818 5626078 : z[1] = evalvalser(e) | evalvarn(v) | evalsigne(1); return z;
1819 : }
1820 :
1821 : /* fill in coefficients of t_SER z from coeffs of t_POL y */
1822 : static GEN
1823 5614613 : fill_ser(GEN z, GEN y)
1824 : {
1825 5614613 : long i, lx = lg(z), ly = lg(y);
1826 5614613 : if (ly >= lx) {
1827 25192844 : for (i = 2; i < lx; i++) gel(z,i) = gel(y,i);
1828 : } else {
1829 332846 : for (i = 2; i < ly; i++) gel(z,i) = gel(y,i);
1830 237865 : for ( ; i < lx; i++) gel(z,i) = gen_0;
1831 : }
1832 5614613 : return normalizeser(z);
1833 : }
1834 : /* assume typ(x) = t_VEC */
1835 : static int
1836 84 : is_ext_qfr(GEN x)
1837 84 : { return lg(x) == 3 && typ(gel(x,1)) == t_QFB && !qfb_is_qfi(gel(x,1))
1838 168 : && typ(gel(x,2)) == t_REAL; }
1839 :
1840 : GEN
1841 8013385099 : gmul(GEN x, GEN y)
1842 : {
1843 : long tx, ty, lx, ly, vx, vy, i, l;
1844 : pari_sp av, tetpil;
1845 : GEN z, p1;
1846 :
1847 8013385099 : if (x == y) return gsqr(x);
1848 7135984725 : tx = typ(x); ty = typ(y);
1849 7135984725 : if (tx == ty) switch(tx)
1850 : {
1851 3476877390 : case t_INT: return mulii(x,y);
1852 1671327932 : case t_REAL: return mulrr(x,y);
1853 1779429 : case t_INTMOD: { GEN X = gel(x,1), Y = gel(y,1);
1854 1779429 : z = cgetg(3,t_INTMOD);
1855 1779429 : if (X==Y || equalii(X,Y))
1856 1779394 : return mul_intmod_same(z, X, gel(x,2), gel(y,2));
1857 35 : gel(z,1) = gcdii(X,Y);
1858 35 : warn_coercion(X,Y,gel(z,1));
1859 35 : av = avma; p1 = mulii(gel(x,2),gel(y,2));
1860 35 : gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z;
1861 : }
1862 21611044 : case t_FRAC:
1863 : {
1864 21611044 : GEN x1 = gel(x,1), x2 = gel(x,2);
1865 21611044 : GEN y1 = gel(y,1), y2 = gel(y,2);
1866 21611044 : z=cgetg(3,t_FRAC);
1867 21611044 : p1 = gcdii(x1, y2);
1868 21611033 : if (!equali1(p1)) { x1 = diviiexact(x1,p1); y2 = diviiexact(y2,p1); }
1869 21611033 : p1 = gcdii(x2, y1);
1870 21611037 : if (!equali1(p1)) { x2 = diviiexact(x2,p1); y1 = diviiexact(y1,p1); }
1871 21611037 : tetpil = avma;
1872 21611037 : gel(z,2) = mulii(x2,y2);
1873 21611030 : gel(z,1) = mulii(x1,y1);
1874 21611037 : fix_frac_if_int_GC(z,tetpil); return z;
1875 : }
1876 241148989 : case t_COMPLEX: return mulcc(x, y);
1877 8051785 : case t_PADIC: return mulpp(x, y);
1878 882 : case t_QUAD: return mulqq(x, y);
1879 14533923 : case t_FFELT: return FF_mul(x, y);
1880 10503106 : case t_POLMOD:
1881 10503106 : if (RgX_equal_var(gel(x,1), gel(y,1)))
1882 7824899 : return mul_polmod_same(gel(x,1), gel(x,2), gel(y,2));
1883 2678207 : return mul_polmod(gel(x,1), gel(y,1), gel(x,2), gel(y,2));
1884 45085140 : case t_POL:
1885 45085140 : vx = varn(x);
1886 45085140 : vy = varn(y);
1887 45085140 : if (vx != vy) {
1888 4868046 : if (varncmp(vx, vy) < 0) return RgX_Rg_mul(x, y);
1889 2082740 : else return RgX_Rg_mul(y, x);
1890 : }
1891 40217094 : return RgX_mul(x, y);
1892 :
1893 4347482 : case t_SER: {
1894 4347482 : vx = varn(x);
1895 4347482 : vy = varn(y);
1896 4347482 : if (vx != vy) {
1897 3675 : if (varncmp(vx, vy) < 0) return mul_ser_scal(x, y);
1898 3675 : return mul_ser_scal(y, x);
1899 : }
1900 4343807 : lx = minss(lg(x), lg(y));
1901 4343807 : if (lx == 2) return zeroser(vx, valser(x)+valser(y));
1902 4343793 : av = avma; z = init_ser(lx, vx, valser(x)+valser(y));
1903 4343793 : x = ser2pol_i(x, lx);
1904 4343793 : y = ser2pol_i(y, lx);
1905 4343793 : y = RgXn_mul(x, y, lx-2);
1906 4343793 : return gerepilecopy(av, fill_ser(z,y));
1907 : }
1908 42 : case t_VEC:
1909 42 : if (!is_ext_qfr(x) || !is_ext_qfr(y)) pari_err_TYPE2("*",x,y);
1910 : /* fall through, handle extended t_QFB */
1911 47804 : case t_QFB: return qfbcomp(x,y);
1912 6720458 : case t_RFRAC: return mul_rfrac(gel(x,1),gel(x,2), gel(y,1),gel(y,2));
1913 2737407 : case t_MAT: return RgM_mul(x, y);
1914 :
1915 1631 : case t_VECSMALL: /* multiply as permutation. cf perm_mul */
1916 1631 : z = cgetg_copy(x, &l);
1917 1631 : if (l != lg(y)) break;
1918 17325 : for (i=1; i<l; i++)
1919 : {
1920 15694 : long yi = y[i];
1921 15694 : if (yi < 1 || yi >= l) pari_err_TYPE2("*",x,y);
1922 15694 : z[i] = x[yi];
1923 : }
1924 1631 : return z;
1925 :
1926 0 : default:
1927 0 : pari_err_TYPE2("*",x,y);
1928 : }
1929 : /* tx != ty */
1930 1631856037 : if (is_const_t(ty) && is_const_t(tx)) {
1931 1513504005 : if (tx > ty) { swap(x,y); lswap(tx,ty); }
1932 1513504005 : switch(tx) {
1933 1406273701 : case t_INT:
1934 : switch(ty)
1935 : {
1936 927790065 : case t_REAL: return signe(x)? mulir(x,y): gen_0;
1937 1322519 : case t_INTMOD:
1938 1322519 : z = cgetg(3, t_INTMOD);
1939 1322522 : return mul_intmod_same(z, gel(y,1), gel(y,2), modii(x, gel(y,1)));
1940 63547025 : case t_FRAC:
1941 63547025 : if (!signe(x)) return gen_0;
1942 46562830 : z=cgetg(3,t_FRAC);
1943 46563011 : p1 = gcdii(x,gel(y,2));
1944 46561842 : if (equali1(p1))
1945 : {
1946 27989491 : set_avma((pari_sp)z);
1947 27989503 : gel(z,2) = icopy(gel(y,2));
1948 27989665 : gel(z,1) = mulii(gel(y,1), x);
1949 : }
1950 : else
1951 : {
1952 18572689 : x = diviiexact(x,p1); tetpil = avma;
1953 18572308 : gel(z,2) = diviiexact(gel(y,2), p1);
1954 18572195 : gel(z,1) = mulii(gel(y,1), x);
1955 18572416 : fix_frac_if_int_GC(z,tetpil);
1956 : }
1957 46562568 : return z;
1958 410729639 : case t_COMPLEX: return signe(x)? mulRc(x, y): gen_0;
1959 4118587 : case t_PADIC: return signe(x)? mulTp(x, y): gen_0;
1960 1701 : case t_QUAD: return mulRq(x,y);
1961 1626085 : case t_FFELT: return FF_Z_mul(y,x);
1962 : }
1963 :
1964 : case t_REAL:
1965 100408905 : switch(ty)
1966 : {
1967 30144067 : case t_FRAC: return mulrfrac(x, y);
1968 70264796 : case t_COMPLEX: return mulRc(x, y);
1969 21 : case t_QUAD: return mulqf(y, x, realprec(x));
1970 21 : default: pari_err_TYPE2("*",x,y);
1971 : }
1972 :
1973 8022 : case t_INTMOD:
1974 : switch(ty)
1975 : {
1976 7133 : case t_FRAC: { GEN X = gel(x,1);
1977 7133 : z = cgetg(3, t_INTMOD); p1 = Fp_mul(gel(y,1), gel(x,2), X);
1978 7133 : return div_intmod_same(z, X, p1, remii(gel(y,2), X));
1979 : }
1980 49 : case t_COMPLEX: return mulRc_direct(x,y);
1981 427 : case t_PADIC: { GEN X = gel(x,1);
1982 427 : z = cgetg(3, t_INTMOD);
1983 427 : return mul_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X));
1984 : }
1985 63 : case t_QUAD: return mulRq(x, y);
1986 350 : case t_FFELT:
1987 350 : if (!equalii(gel(x,1),FF_p_i(y)))
1988 0 : pari_err_OP("*",x,y);
1989 350 : return FF_Z_mul(y,gel(x,2));
1990 : }
1991 :
1992 : case t_FRAC:
1993 : switch(ty)
1994 : {
1995 5206421 : case t_COMPLEX: return mulRc(x, y);
1996 2555600 : case t_PADIC: return signe(gel(x,1))? mulTp(x, y): gen_0;
1997 343 : case t_QUAD: return mulRq(x, y);
1998 2051 : case t_FFELT: return FF_Z_Z_muldiv(y, gel(x,1),gel(x,2));
1999 : }
2000 :
2001 : case t_FFELT:
2002 35 : pari_err_TYPE2("*",x,y);
2003 :
2004 21 : case t_COMPLEX:
2005 : switch(ty)
2006 : {
2007 14 : case t_PADIC:
2008 14 : return Zp_nosquare_m1(gel(y,2))? mulRc(y, x): mulTp(x, y);
2009 7 : case t_QUAD:
2010 7 : lx = precision(x); if (!lx) pari_err_OP("*",x,y);
2011 7 : return mulqf(y, x, lx);
2012 : }
2013 :
2014 : case t_PADIC: /* ty == t_QUAD */
2015 28 : return (kro_quad(y,gel(x,2))== -1)? mulRq(x, y): mulTp(y, x);
2016 : }
2017 : }
2018 :
2019 121317581 : if (is_matvec_t(ty))
2020 : {
2021 7625133 : if (!is_matvec_t(tx))
2022 : {
2023 6670647 : if (is_noncalc_t(tx)) pari_err_TYPE2( "*",x,y); /* necessary if ly = 1 */
2024 6670649 : z = cgetg_copy(y, &ly);
2025 622468540 : for (i=1; i<ly; i++) gel(z,i) = gmul(x,gel(y,i));
2026 6670281 : return z;
2027 : }
2028 954480 : switch(tx)
2029 : {
2030 121764 : case t_VEC:
2031 : switch(ty) {
2032 15540 : case t_COL: return RgV_RgC_mul(x,y);
2033 106224 : case t_MAT: return RgV_RgM_mul(x,y);
2034 : }
2035 0 : break;
2036 1687 : case t_COL:
2037 : switch(ty) {
2038 1687 : case t_VEC: return RgC_RgV_mul(x,y);
2039 0 : case t_MAT: return RgC_RgM_mul(x,y);
2040 : }
2041 0 : break;
2042 831041 : case t_MAT:
2043 : switch(ty) {
2044 0 : case t_VEC: return RgM_RgV_mul(x,y);
2045 831041 : case t_COL: return RgM_RgC_mul(x,y);
2046 : }
2047 : }
2048 : }
2049 117875495 : if (is_matvec_t(tx))
2050 : {
2051 1839819 : if (is_noncalc_t(ty)) pari_err_TYPE2( "*",x,y); /* necessary if lx = 1 */
2052 1840039 : z = cgetg_copy(x, &lx);
2053 7621511 : for (i=1; i<lx; i++) gel(z,i) = gmul(y,gel(x,i));
2054 1839850 : return z;
2055 : }
2056 116035720 : if (tx > ty) { swap(x,y); lswap(tx,ty); }
2057 : /* tx < ty, !ismatvec(x and y) */
2058 :
2059 116035720 : if (ty == t_POLMOD) /* is_const_t(tx) in this case */
2060 2585977 : return mul_polmod_scal(gel(y,1), gel(y,2), x);
2061 113449743 : if (is_scalar_t(tx)) {
2062 110154498 : if (tx == t_POLMOD) {
2063 3139965 : vx = varn(gel(x,1));
2064 3139965 : vy = gvar(y);
2065 3139965 : if (vx != vy) {
2066 2892585 : if (varncmp(vx,vy) > 0) return mul_scal(y, x, ty);
2067 47383 : return mul_polmod_scal(gel(x,1), gel(x,2), y);
2068 : }
2069 : /* error if ty == t_SER */
2070 247380 : av = avma; y = gmod(y, gel(x,1));
2071 247373 : return gerepileupto(av, mul_polmod_same(gel(x,1), gel(x,2), y));
2072 : }
2073 107014533 : return mul_scal(y, x, ty);
2074 : }
2075 :
2076 : /* x and y are not scalars, nor matvec */
2077 3295096 : vx = gvar(x);
2078 3295122 : vy = gvar(y);
2079 3295122 : if (vx != vy) /* x or y is treated as a scalar */
2080 2780201 : return (varncmp(vx, vy) < 0)? mul_scal(x, y, tx)
2081 2780201 : : mul_scal(y, x, ty);
2082 : /* vx = vy */
2083 1876241 : switch(tx)
2084 : {
2085 1876213 : case t_POL:
2086 : switch (ty)
2087 : {
2088 6713 : case t_SER:
2089 : {
2090 : long v;
2091 6713 : av = avma; v = RgX_valrem(x, &x);
2092 6713 : if (v == LONG_MAX) return gerepileupto(av, Rg_get_0(x));
2093 6699 : v += valser(y); ly = lg(y);
2094 6699 : if (ly == 2) { set_avma(av); return zeroser(vx, v); }
2095 6468 : if (degpol(x))
2096 : {
2097 2030 : z = init_ser(ly, vx, v);
2098 2030 : x = RgXn_mul(x, ser2pol_i(y, ly), ly-2);
2099 2030 : return gerepilecopy(av, fill_ser(z, x));
2100 : }
2101 : /* take advantage of x = c*t^v */
2102 4438 : set_avma(av); y = mul_ser_scal(y, gel(x,2));
2103 4438 : setvalser(y, v); return y;
2104 : }
2105 :
2106 1869500 : case t_RFRAC: return mul_rfrac_scal(gel(y,1),gel(y,2), x);
2107 : }
2108 0 : break;
2109 :
2110 28 : case t_SER:
2111 : switch (ty)
2112 : {
2113 28 : case t_RFRAC:
2114 28 : av = avma;
2115 28 : return gerepileupto(av, gdiv(gmul(gel(y,1),x), gel(y,2)));
2116 : }
2117 0 : break;
2118 : }
2119 0 : pari_err_TYPE2("*",x,y);
2120 : return NULL; /* LCOV_EXCL_LINE */
2121 : }
2122 :
2123 : /* return a nonnormalized result */
2124 : GEN
2125 104170 : sqr_ser_part(GEN x, long l1, long l2)
2126 : {
2127 : long i, j, l;
2128 : pari_sp av;
2129 : GEN Z, z, p1, p2;
2130 : long mi;
2131 104170 : if (l2 < l1) return zeroser(varn(x), 2*valser(x));
2132 104156 : p2 = cgetg(l2+2, t_VECSMALL)+1; /* left on stack on exit */
2133 104156 : Z = cgetg(l2-l1+3, t_SER);
2134 104156 : Z[1] = evalvalser(2*valser(x)) | evalvarn(varn(x));
2135 104156 : z = Z + 2-l1;
2136 104156 : x += 2; mi = 0;
2137 415814 : for (i=0; i<l1; i++)
2138 : {
2139 311658 : p2[i] = !isrationalzero(gel(x,i)); if (p2[i]) mi = i;
2140 : }
2141 :
2142 684449 : for (i=l1; i<=l2; i++)
2143 : {
2144 580293 : p2[i] = !isrationalzero(gel(x,i)); if (p2[i]) mi = i;
2145 580293 : p1=gen_0; av=avma; l=((i+1)>>1) - 1;
2146 1217606 : for (j=i-mi; j<=minss(l,mi); j++)
2147 637313 : if (p2[j] && p2[i-j]) p1 = gadd(p1, gmul(gel(x,j),gel(x,i-j)));
2148 580293 : p1 = gshift(p1,1);
2149 580293 : if ((i&1) == 0 && p2[i>>1])
2150 81097 : p1 = gadd(p1, gsqr(gel(x,i>>1)));
2151 580293 : gel(z,i) = gerepileupto(av,p1);
2152 : }
2153 104156 : return Z;
2154 : }
2155 :
2156 : GEN
2157 1079667498 : gsqr(GEN x)
2158 : {
2159 : long i, lx;
2160 : pari_sp av, tetpil;
2161 : GEN z, p1, p2, p3, p4;
2162 :
2163 1079667498 : switch(typ(x))
2164 : {
2165 886846207 : case t_INT: return sqri(x);
2166 178546706 : case t_REAL: return sqrr(x);
2167 142677 : case t_INTMOD: { GEN X = gel(x,1);
2168 142677 : z = cgetg(3,t_INTMOD);
2169 142677 : gel(z,2) = gerepileuptoint((pari_sp)z, remii(sqri(gel(x,2)), X));
2170 142677 : gel(z,1) = icopy(X); return z;
2171 : }
2172 3046710 : case t_FRAC: return sqrfrac(x);
2173 :
2174 6869180 : case t_COMPLEX:
2175 6869180 : if (isintzero(gel(x,1))) {
2176 212354 : av = avma;
2177 212354 : return gerepileupto(av, gneg(gsqr(gel(x,2))));
2178 : }
2179 6656823 : z = cgetg(3,t_COMPLEX); av = avma;
2180 6656795 : p1 = gadd(gel(x,1),gel(x,2));
2181 6656647 : p2 = gsub(gel(x,1), gel(x,2));
2182 6656566 : p3 = gmul(gel(x,1),gel(x,2));
2183 6656708 : tetpil = avma;
2184 6656708 : gel(z,1) = gmul(p1,p2);
2185 6656743 : gel(z,2) = gshift(p3,1); gerepilecoeffssp(av,tetpil,z+1,2); return z;
2186 :
2187 2611 : case t_PADIC:
2188 2611 : z = cgetg(5,t_PADIC);
2189 2611 : i = (absequaliu(gel(x,2), 2) && signe(gel(x,4)))? 1: 0;
2190 2611 : if (i && precp(x) == 1) i = 2; /* (1 + O(2))^2 = 1 + O(2^3) */
2191 2611 : z[1] = evalprecp(precp(x)+i) | evalvalp(valp(x)*2);
2192 2611 : gel(z,2) = icopy(gel(x,2));
2193 2611 : gel(z,3) = shifti(gel(x,3), i); av = avma;
2194 2611 : gel(z,4) = gerepileuptoint(av, remii(sqri(gel(x,4)), gel(z,3)));
2195 2611 : return z;
2196 :
2197 70 : case t_QUAD: z = cgetg(4,t_QUAD);
2198 70 : p1 = gel(x,1);
2199 70 : gel(z,1) = ZX_copy(p1); av = avma;
2200 70 : p2 = gsqr(gel(x,2));
2201 70 : p3 = gsqr(gel(x,3));
2202 70 : p4 = gmul(gneg_i(gel(p1,2)),p3);
2203 :
2204 70 : if (gequal0(gel(p1,3)))
2205 : {
2206 7 : tetpil = avma;
2207 7 : gel(z,2) = gerepile(av,tetpil,gadd(p4,p2));
2208 7 : av = avma;
2209 7 : p2 = gmul(gel(x,2),gel(x,3)); tetpil = avma;
2210 7 : gel(z,3) = gerepile(av,tetpil,gmul2n(p2,1)); return z;
2211 : }
2212 :
2213 63 : p1 = gmul2n(gmul(gel(x,2),gel(x,3)), 1);
2214 63 : tetpil = avma;
2215 63 : gel(z,2) = gadd(p2,p4);
2216 63 : gel(z,3) = gadd(p1,p3);
2217 63 : gerepilecoeffssp(av,tetpil,z+2,2); return z;
2218 :
2219 67356 : case t_POLMOD:
2220 67356 : return sqr_polmod(gel(x,1), gel(x,2));
2221 :
2222 2940297 : case t_FFELT: return FF_sqr(x);
2223 :
2224 1108385 : case t_POL: return RgX_sqr(x);
2225 :
2226 26698 : case t_SER:
2227 26698 : lx = lg(x);
2228 26698 : if (ser_isexactzero(x)) {
2229 21 : GEN z = gcopy(x);
2230 21 : setvalser(z, 2*valser(x));
2231 21 : return z;
2232 : }
2233 26677 : if (lx < 40)
2234 26418 : return normalizeser( sqr_ser_part(x, 0, lx-3) );
2235 : else
2236 : {
2237 259 : pari_sp av = avma;
2238 259 : GEN z = init_ser(lx, varn(x), 2*valser(x));
2239 259 : x = ser2pol_i(x, lx);
2240 259 : x = RgXn_sqr(x, lx-2);
2241 259 : return gerepilecopy(av, fill_ser(z,x));
2242 : }
2243 :
2244 7 : case t_RFRAC: z = cgetg(3,t_RFRAC);
2245 7 : gel(z,1) = gsqr(gel(x,1));
2246 7 : gel(z,2) = gsqr(gel(x,2)); return z;
2247 :
2248 1099 : case t_MAT: return RgM_sqr(x);
2249 14 : case t_VEC: if (!is_ext_qfr(x)) pari_err_TYPE2("*",x,x);
2250 : /* fall through handle extended t_QFB */
2251 81901 : case t_QFB: return qfbsqr(x);
2252 658 : case t_VECSMALL:
2253 658 : z = cgetg_copy(x, &lx);
2254 16289 : for (i=1; i<lx; i++)
2255 : {
2256 15631 : long xi = x[i];
2257 15631 : if (xi < 1 || xi >= lx) pari_err_TYPE2("*",x,x);
2258 15631 : z[i] = x[xi];
2259 : }
2260 658 : return z;
2261 : }
2262 7 : pari_err_TYPE2("*",x,x);
2263 : return NULL; /* LCOV_EXCL_LINE */
2264 : }
2265 :
2266 : /********************************************************************/
2267 : /** **/
2268 : /** DIVISION **/
2269 : /** **/
2270 : /********************************************************************/
2271 : static GEN
2272 30832 : div_rfrac_scal(GEN x, GEN y)
2273 : {
2274 30832 : pari_sp av = avma;
2275 30832 : GEN d = rfrac_denom_mul_scal(gel(x,2), y);
2276 30832 : return gerepileupto(av, gred_rfrac_simple(gel(x,1), d));
2277 : }
2278 : static GEN
2279 37466 : div_scal_rfrac(GEN x, GEN y)
2280 : {
2281 37466 : GEN y1 = gel(y,1), y2 = gel(y,2);
2282 37466 : if (typ(y1) == t_POL && varn(y2) == varn(y1))
2283 : {
2284 14 : if (degpol(y1))
2285 : {
2286 14 : pari_sp av = avma;
2287 14 : GEN _1 = Rg_get_1(x);
2288 14 : if (transtype(_1)) y1 = gmul(y1, _1);
2289 14 : return gerepileupto(av, gred_rfrac_simple(gmul(x, y2), y1));
2290 : }
2291 0 : y1 = gel(y1,2);
2292 : }
2293 37452 : return RgX_Rg_mul(y2, gdiv(x,y1));
2294 : }
2295 : static GEN
2296 1186656 : div_rfrac(GEN x, GEN y)
2297 1186656 : { return mul_rfrac(gel(x,1),gel(x,2), gel(y,2),gel(y,1)); }
2298 :
2299 : /* x != 0 */
2300 : static GEN
2301 1321422 : div_ser_scal(GEN y, GEN x)
2302 : {
2303 : long i, l;
2304 : GEN z;
2305 1321422 : if (ser_isexactzero(y))
2306 : {
2307 28 : z = scalarser(lg(y) == 2? Rg_get_0(x): gdiv(gel(y,2), x), varn(y), 1);
2308 28 : setvalser(z, valser(y)); return z;
2309 : }
2310 1321394 : z = cgetg_copy(y, &l); z[1] = y[1];
2311 6108824 : for (i = 2; i < l; i++) gel(z,i) = gdiv(gel(y,i), x);
2312 1321394 : return normalizeser(z);
2313 : }
2314 : GEN
2315 7553 : ser_normalize(GEN x)
2316 : {
2317 7553 : long i, lx = lg(x);
2318 : GEN c, z;
2319 7553 : if (lx == 2) return x;
2320 7553 : c = gel(x,2); if (gequal1(c)) return x;
2321 7476 : z = cgetg(lx, t_SER); z[1] = x[1]; gel(z,2) = gen_1;
2322 107835 : for (i=3; i<lx; i++) gel(z,i) = gdiv(gel(x,i),c);
2323 7476 : return z;
2324 : }
2325 :
2326 : /* y != 0 */
2327 : static GEN
2328 5354934 : div_T_scal(GEN x, GEN y, long tx) {
2329 5354934 : switch(tx)
2330 : {
2331 4006556 : case t_POL: return RgX_Rg_div(x, y);
2332 1321415 : case t_SER: return div_ser_scal(x, y);
2333 26968 : case t_RFRAC: return div_rfrac_scal(x,y);
2334 : }
2335 0 : pari_err_TYPE2("/",x,y);
2336 : return NULL; /* LCOV_EXCL_LINE */
2337 : }
2338 :
2339 : static GEN
2340 9258919 : div_scal_pol(GEN x, GEN y) {
2341 9258919 : long ly = lg(y);
2342 : pari_sp av;
2343 : GEN _1;
2344 9258919 : if (ly == 3) return scalarpol(gdiv(x,gel(y,2)), varn(y));
2345 9180651 : if (isrationalzero(x)) return zeropol(varn(y));
2346 7130795 : av = avma;
2347 7130795 : _1 = Rg_get_1(x); if (transtype(_1)) y = gmul(y, _1);
2348 7130795 : return gerepileupto(av, gred_rfrac_simple(x,y));
2349 : }
2350 : static GEN
2351 18389 : div_scal_ser(GEN x, GEN y)
2352 : {
2353 18389 : pari_sp av = avma;
2354 18389 : GEN _1 = Rg_get_1(x);
2355 18389 : if (transtype(_1)) y = gmul(y, _1);
2356 18389 : return gerepileupto(av, gmul(x, ser_inv(y)));
2357 : }
2358 : static GEN
2359 9267552 : div_scal_T(GEN x, GEN y, long ty) {
2360 9267552 : switch(ty)
2361 : {
2362 9212460 : case t_POL: return div_scal_pol(x, y);
2363 18382 : case t_SER: return div_scal_ser(x, y);
2364 36710 : case t_RFRAC: return div_scal_rfrac(x, y);
2365 : }
2366 0 : pari_err_TYPE2("/",x,y);
2367 : return NULL; /* LCOV_EXCL_LINE */
2368 : }
2369 :
2370 : /* assume tx = ty = t_SER, same variable vx */
2371 : static GEN
2372 761864 : div_ser(GEN x, GEN y, long vx)
2373 : {
2374 761864 : long e, v = valser(x) - valser(y), lx = lg(x), ly = lg(y);
2375 761864 : GEN y0 = y, z;
2376 761864 : pari_sp av = avma;
2377 :
2378 761864 : if (!signe(y)) pari_err_INV("div_ser", y);
2379 761857 : if (ser_isexactzero(x))
2380 : {
2381 59892 : if (lx == 2) return zeroser(vx, v);
2382 147 : z = scalarser(gmul(gel(x,2),Rg_get_0(y)), varn(x), 1);
2383 147 : setvalser(z, v); return z;
2384 : }
2385 701965 : if (lx < ly) ly = lx;
2386 701965 : y = ser2pol_i_normalize(y, ly, &e);
2387 701965 : if (e)
2388 : {
2389 7 : pari_warn(warner,"normalizing a series with 0 leading term");
2390 7 : ly -= e; v -= e; if (ly <= 2) pari_err_INV("div_ser", y0);
2391 : }
2392 701965 : z = init_ser(ly, vx, v);
2393 701965 : if (ly == 3)
2394 : {
2395 11465 : gel(z,2) = gdiv(gel(x,2), gel(y,2));
2396 11465 : if (gequal0(gel(z,2))) setsigne(z, 0); /* can happen: Mod(1,2)/Mod(1,3) */
2397 11465 : return gerepileupto(av, z);
2398 : }
2399 690500 : x = ser2pol_i(x, ly);
2400 690500 : y = RgXn_div_i(x, y, ly-2);
2401 690500 : return gerepilecopy(av, fill_ser(z,y));
2402 : }
2403 : /* x,y compatible PADIC */
2404 : static GEN
2405 2499791 : divpp(GEN x, GEN y) {
2406 : pari_sp av;
2407 : long a, b;
2408 : GEN z, M;
2409 :
2410 2499791 : if (!signe(gel(y,4))) pari_err_INV("divpp",y);
2411 2499791 : if (!signe(gel(x,4))) return zeropadic(gel(x,2), valp(x)-valp(y));
2412 2499471 : a = precp(x);
2413 2499471 : b = precp(y); if (a > b) { M = gel(y,3); } else { M = gel(x,3); b = a; }
2414 2499471 : z = cgetg(5, t_PADIC);
2415 2499338 : z[1] = _evalprecp(b) | evalvalp(valp(x) - valp(y));
2416 2499287 : gel(z,2) = icopy(gel(x,2));
2417 2499467 : gel(z,3) = icopy(M); av = avma;
2418 2499308 : gel(z,4) = gerepileuptoint(av, remii(mulii(gel(x,4), Fp_inv(gel(y,4), M)), M) );
2419 2499705 : return z;
2420 : }
2421 : static GEN
2422 35867 : div_polmod_same(GEN T, GEN x, GEN y)
2423 : {
2424 35867 : long v = varn(T);
2425 35867 : GEN a, z = cgetg(3, t_POLMOD);
2426 35867 : gel(z,1) = RgX_copy(T);
2427 35867 : if (typ(y) != t_POL || varn(y) != v || lg(y) <= 3)
2428 10276 : a = gdiv(x, y);
2429 25591 : else if (typ(x) != t_POL || varn(x) != v || lg(x) <= 3)
2430 119 : {
2431 119 : pari_sp av = avma;
2432 119 : a = gerepileupto(av, gmul(x, RgXQ_inv(y, T)));
2433 : }
2434 25472 : else if (degpol(T) == 2 && isint1(gel(T,4))) /* quadratic fields */
2435 5236 : {
2436 5236 : pari_sp av = avma;
2437 5236 : a = quad_polmod_mul(T, x, quad_polmod_conj(y, T));
2438 5236 : a = RgX_Rg_div(a, quad_polmod_norm(y, T));
2439 5236 : a = gerepileupto(av, a);
2440 : }
2441 : else
2442 : {
2443 20236 : pari_sp av = avma;
2444 20236 : a = RgXQ_mul(x, ginvmod(y, gel(z,1)), gel(z,1));
2445 20236 : a = gerepileupto(av, a);
2446 : }
2447 35867 : gel(z,2) = a; return z;
2448 : }
2449 : GEN
2450 412210112 : gdiv(GEN x, GEN y)
2451 : {
2452 412210112 : long tx = typ(x), ty = typ(y), lx, ly, vx, vy, i;
2453 : pari_sp av, tetpil;
2454 : GEN z, p1, p2;
2455 :
2456 412210112 : if (tx == ty) switch(tx)
2457 : {
2458 79276499 : case t_INT:
2459 79276499 : return Qdivii(x,y);
2460 :
2461 78805286 : case t_REAL: return divrr(x,y);
2462 25670 : case t_INTMOD: { GEN X = gel(x,1), Y = gel(y,1);
2463 25670 : z = cgetg(3,t_INTMOD);
2464 25670 : if (X==Y || equalii(X,Y))
2465 25656 : return div_intmod_same(z, X, gel(x,2), gel(y,2));
2466 14 : gel(z,1) = gcdii(X,Y);
2467 14 : warn_coercion(X,Y,gel(z,1));
2468 14 : av = avma; p1 = mulii(gel(x,2), Fp_inv(gel(y,2), gel(z,1)));
2469 14 : gel(z,2) = gerepileuptoint(av, remii(p1, gel(z,1))); return z;
2470 : }
2471 3761784 : case t_FRAC: {
2472 3761784 : GEN x1 = gel(x,1), x2 = gel(x,2);
2473 3761784 : GEN y1 = gel(y,1), y2 = gel(y,2);
2474 3761784 : z = cgetg(3, t_FRAC);
2475 3761783 : p1 = gcdii(x1, y1);
2476 3761781 : if (!equali1(p1)) { x1 = diviiexact(x1,p1); y1 = diviiexact(y1,p1); }
2477 3761781 : p1 = gcdii(x2, y2);
2478 3761780 : if (!equali1(p1)) { x2 = diviiexact(x2,p1); y2 = diviiexact(y2,p1); }
2479 3761781 : tetpil = avma;
2480 3761781 : gel(z,2) = mulii(x2,y1);
2481 3761783 : gel(z,1) = mulii(x1,y2);
2482 3761781 : normalize_frac(z);
2483 3761781 : fix_frac_if_int_GC(z,tetpil);
2484 3761784 : return z;
2485 : }
2486 8225184 : case t_COMPLEX:
2487 8225184 : if (isintzero(gel(y,1)))
2488 : {
2489 110481 : y = gel(y,2);
2490 110481 : if (isintzero(gel(x,1))) return gdiv(gel(x,2), y);
2491 93415 : z = cgetg(3,t_COMPLEX);
2492 93415 : gel(z,1) = gdiv(gel(x,2), y);
2493 93415 : av = avma;
2494 93415 : gel(z,2) = gerepileupto(av, gneg(gdiv(gel(x,1), y)));
2495 93415 : return z;
2496 : }
2497 8114682 : av = avma; p1 = cxnorm(y); p2 = mulcc(x, conj_i(y)); tetpil = avma;
2498 8114739 : return gerepile(av, tetpil, gdiv(p2,p1));
2499 :
2500 575539 : case t_PADIC:
2501 575539 : if (!equalii(gel(x,2),gel(y,2))) pari_err_OP("/",x,y);
2502 575539 : return divpp(x, y);
2503 :
2504 238 : case t_QUAD:
2505 238 : if (!ZX_equal(gel(x,1),gel(y,1))) pari_err_OP("/",x,y);
2506 224 : av = avma; p1 = quadnorm(y); p2 = mulqq(x, conj_i(y)); tetpil = avma;
2507 224 : return gerepile(av, tetpil, gdiv(p2,p1));
2508 :
2509 236961 : case t_FFELT: return FF_div(x,y);
2510 :
2511 40242 : case t_POLMOD:
2512 40242 : if (RgX_equal_var(gel(x,1), gel(y,1)))
2513 35867 : z = div_polmod_same(gel(x,1), gel(x,2), gel(y,2));
2514 : else {
2515 4375 : av = avma;
2516 4375 : z = gerepileupto(av, gmul(x, ginv(y)));
2517 : }
2518 40242 : return z;
2519 :
2520 18461273 : case t_POL:
2521 18461273 : vx = varn(x);
2522 18461273 : vy = varn(y);
2523 18461273 : if (vx != vy) {
2524 102767 : if (varncmp(vx, vy) < 0) return RgX_Rg_div(x, y);
2525 46459 : else return div_scal_pol(x, y);
2526 : }
2527 18358506 : if (!signe(y)) pari_err_INV("gdiv",y);
2528 18358506 : if (lg(y) == 3) return RgX_Rg_div(x,gel(y,2));
2529 18234898 : av = avma;
2530 18234898 : return gerepileupto(av, gred_rfrac2(x,y));
2531 :
2532 761885 : case t_SER:
2533 761885 : vx = varn(x);
2534 761885 : vy = varn(y);
2535 761885 : if (vx != vy) {
2536 21 : if (varncmp(vx, vy) < 0)
2537 : {
2538 14 : if (!signe(y)) pari_err_INV("gdiv",y);
2539 7 : return div_ser_scal(x, y);
2540 : }
2541 7 : return div_scal_ser(x, y);
2542 : }
2543 761864 : return div_ser(x, y, vx);
2544 1191136 : case t_RFRAC:
2545 1191136 : vx = varn(gel(x,2));
2546 1191136 : vy = varn(gel(y,2));
2547 1191136 : if (vx != vy) {
2548 4480 : if (varncmp(vx, vy) < 0) return div_rfrac_scal(x, y);
2549 756 : else return div_scal_rfrac(x, y);
2550 : }
2551 1186656 : return div_rfrac(x,y);
2552 :
2553 21 : case t_VEC: /* handle extended t_QFB */
2554 21 : case t_QFB: av = avma; return gerepileupto(av, qfbcomp(x, ginv(y)));
2555 :
2556 14 : case t_MAT:
2557 14 : av = avma; p1 = RgM_inv(y);
2558 14 : if (!p1) pari_err_INV("gdiv",y);
2559 14 : return gerepileupto(av, RgM_mul(x, p1));
2560 :
2561 0 : default: pari_err_TYPE2("/",x,y);
2562 : }
2563 :
2564 220853341 : if (tx==t_INT && is_const_t(ty)) /* optimized for speed */
2565 : {
2566 3446408 : long s = signe(x);
2567 3446408 : if (!s) {
2568 482727 : if (gequal0(y)) pari_err_INV("gdiv",y);
2569 482727 : switch (ty)
2570 : {
2571 479563 : default: return gen_0;
2572 28 : case t_INTMOD:
2573 28 : z = cgetg(3,t_INTMOD);
2574 28 : gel(z,1) = icopy(gel(y,1));
2575 28 : gel(z,2) = gen_0; return z;
2576 3136 : case t_FFELT: return FF_zero(y);
2577 : }
2578 : }
2579 2963681 : if (is_pm1(x)) {
2580 1092787 : if (s > 0) return ginv(y);
2581 181637 : av = avma; return gerepileupto(av, ginv(gneg(y)));
2582 : }
2583 1870893 : switch(ty)
2584 : {
2585 603015 : case t_REAL: return divir(x,y);
2586 21 : case t_INTMOD:
2587 21 : z = cgetg(3, t_INTMOD);
2588 21 : return div_intmod_same(z, gel(y,1), modii(x, gel(y,1)), gel(y,2));
2589 775827 : case t_FRAC:
2590 775827 : z = cgetg(3,t_FRAC); p1 = gcdii(x,gel(y,1));
2591 775827 : if (equali1(p1))
2592 : {
2593 247468 : set_avma((pari_sp)z);
2594 247468 : gel(z,2) = icopy(gel(y,1));
2595 247468 : gel(z,1) = mulii(gel(y,2), x);
2596 247468 : normalize_frac(z);
2597 247468 : fix_frac_if_int(z);
2598 : }
2599 : else
2600 : {
2601 528359 : x = diviiexact(x,p1); tetpil = avma;
2602 528359 : gel(z,2) = diviiexact(gel(y,1), p1);
2603 528359 : gel(z,1) = mulii(gel(y,2), x);
2604 528359 : normalize_frac(z);
2605 528359 : fix_frac_if_int_GC(z,tetpil);
2606 : }
2607 775827 : return z;
2608 :
2609 469 : case t_FFELT: return Z_FF_div(x,y);
2610 489830 : case t_COMPLEX: return divRc(x,y);
2611 1505 : case t_PADIC: return divTp(x, y);
2612 231 : case t_QUAD:
2613 231 : av = avma; p1 = quadnorm(y); p2 = mulRq(x, conj_i(y)); tetpil = avma;
2614 231 : return gerepile(av, tetpil, gdiv(p2,p1));
2615 : }
2616 : }
2617 217406930 : if (gequal0(y))
2618 : {
2619 49 : if (is_matvec_t(tx) && lg(x) == 1) return gcopy(x);
2620 28 : if (ty != t_MAT) pari_err_INV("gdiv",y);
2621 : }
2622 :
2623 217416387 : if (is_const_t(tx) && is_const_t(ty)) switch(tx)
2624 : {
2625 181311045 : case t_REAL:
2626 181311045 : switch(ty)
2627 : {
2628 179118078 : case t_INT: return divri(x,y);
2629 519593 : case t_FRAC:
2630 519593 : av = avma; z = divri(mulri(x,gel(y,2)), gel(y,1));
2631 519593 : return gerepileuptoleaf(av, z);
2632 1673419 : case t_COMPLEX: return divRc(x, y);
2633 42 : case t_QUAD: return divfq(x, y, realprec(x));
2634 18 : default: pari_err_TYPE2("/",x,y);
2635 : }
2636 :
2637 280 : case t_INTMOD:
2638 : switch(ty)
2639 : {
2640 196 : case t_INT:
2641 196 : z = cgetg(3, t_INTMOD);
2642 196 : return div_intmod_same(z, gel(x,1), gel(x,2), modii(y, gel(x,1)));
2643 28 : case t_FRAC: { GEN X = gel(x,1);
2644 28 : z = cgetg(3,t_INTMOD); p1 = remii(mulii(gel(y,2), gel(x,2)), X);
2645 28 : return div_intmod_same(z, X, p1, modii(gel(y,1), X));
2646 : }
2647 7 : case t_FFELT:
2648 7 : if (!equalii(gel(x,1),FF_p_i(y)))
2649 0 : pari_err_OP("/",x,y);
2650 7 : return Z_FF_div(gel(x,2),y);
2651 :
2652 0 : case t_COMPLEX:
2653 0 : av = avma;
2654 0 : return gerepileupto(av, mulRc_direct(gdiv(x,cxnorm(y)), conj_i(y)));
2655 :
2656 14 : case t_QUAD:
2657 14 : av = avma; p1 = quadnorm(y); p2 = gmul(x,conj_i(y)); tetpil = avma;
2658 14 : return gerepile(av,tetpil, gdiv(p2,p1));
2659 :
2660 7 : case t_PADIC: { GEN X = gel(x,1);
2661 7 : z = cgetg(3, t_INTMOD);
2662 7 : return div_intmod_same(z, X, gel(x,2), padic_to_Fp(y, X));
2663 : }
2664 28 : case t_REAL: pari_err_TYPE2("/",x,y);
2665 : }
2666 :
2667 : case t_FRAC:
2668 : switch(ty)
2669 : {
2670 2055175 : case t_INT: z = cgetg(3, t_FRAC);
2671 2055175 : p1 = gcdii(y,gel(x,1));
2672 2055175 : if (equali1(p1))
2673 : {
2674 796206 : set_avma((pari_sp)z); tetpil = 0;
2675 796206 : gel(z,1) = icopy(gel(x,1));
2676 : }
2677 : else
2678 : {
2679 1258969 : y = diviiexact(y,p1); tetpil = avma;
2680 1258969 : gel(z,1) = diviiexact(gel(x,1), p1);
2681 : }
2682 2055175 : gel(z,2) = mulii(gel(x,2),y);
2683 2055175 : normalize_frac(z);
2684 2055175 : if (tetpil) fix_frac_if_int_GC(z,tetpil);
2685 2055175 : return z;
2686 :
2687 57714 : case t_REAL:
2688 57714 : av=avma; p1=mulri(y,gel(x,2)); tetpil=avma;
2689 57714 : return gerepile(av, tetpil, divir(gel(x,1), p1));
2690 :
2691 7 : case t_INTMOD: { GEN Y = gel(y,1);
2692 7 : z = cgetg(3,t_INTMOD); p1 = remii(mulii(gel(y,2),gel(x,2)), Y);
2693 7 : return div_intmod_same(z, Y, modii(gel(x,1), Y), p1);
2694 : }
2695 :
2696 28 : case t_FFELT: av=avma;
2697 28 : return gerepileupto(av,Z_FF_div(gel(x,1),FF_Z_mul(y,gel(x,2))));
2698 :
2699 483 : case t_COMPLEX: return divRc(x, y);
2700 :
2701 2162 : case t_PADIC:
2702 2162 : if (!signe(gel(x,1))) return gen_0;
2703 2162 : return divTp(x, y);
2704 :
2705 42 : case t_QUAD:
2706 42 : av=avma; p1=quadnorm(y); p2=gmul(x,conj_i(y)); tetpil=avma;
2707 42 : return gerepile(av,tetpil,gdiv(p2,p1));
2708 : }
2709 :
2710 : case t_FFELT:
2711 133 : switch (ty)
2712 : {
2713 49 : case t_INT: return FF_Z_Z_muldiv(x,gen_1,y);
2714 28 : case t_FRAC: return FF_Z_Z_muldiv(x,gel(y,2),gel(y,1));
2715 7 : case t_INTMOD:
2716 7 : if (!equalii(gel(y,1),FF_p_i(x)))
2717 0 : pari_err_OP("/",x,y);
2718 7 : return FF_Z_Z_muldiv(x,gen_1,gel(y,2));
2719 49 : default:
2720 49 : pari_err_TYPE2("/",x,y);
2721 : }
2722 0 : break;
2723 :
2724 12490088 : case t_COMPLEX:
2725 : switch(ty)
2726 : {
2727 12490078 : case t_INT: case t_REAL: case t_FRAC: return divcR(x,y);
2728 0 : case t_INTMOD: return mulRc_direct(ginv(y), x);
2729 0 : case t_PADIC:
2730 0 : return Zp_nosquare_m1(gel(y,2))? divcR(x,y): divTp(x, y);
2731 0 : case t_QUAD:
2732 0 : lx = precision(x); if (!lx) pari_err_OP("/",x,y);
2733 0 : return divfq(x, y, lx);
2734 : }
2735 :
2736 : case t_PADIC:
2737 : switch(ty)
2738 : {
2739 1201823 : case t_INT: case t_FRAC: { GEN p = gel(x,2);
2740 1201732 : return signe(gel(x,4))? divpT(x, y)
2741 2403555 : : zeropadic(p, valp(x) - Q_pval(y,p));
2742 : }
2743 7 : case t_INTMOD: { GEN Y = gel(y,1);
2744 7 : z = cgetg(3, t_INTMOD);
2745 7 : return div_intmod_same(z, Y, padic_to_Fp(x, Y), gel(y,2));
2746 : }
2747 14 : case t_COMPLEX: case t_QUAD:
2748 14 : av=avma; p1=gmul(x,conj_i(y)); p2=gnorm(y); tetpil=avma;
2749 14 : return gerepile(av,tetpil,gdiv(p1,p2));
2750 :
2751 28 : case t_REAL: pari_err_TYPE2("/",x,y);
2752 : }
2753 :
2754 : case t_QUAD:
2755 : switch (ty)
2756 : {
2757 1190 : case t_INT: case t_INTMOD: case t_FRAC:
2758 1190 : z = cgetg(4,t_QUAD);
2759 1190 : gel(z,1) = ZX_copy(gel(x,1));
2760 1190 : gel(z,2) = gdiv(gel(x,2), y);
2761 1190 : gel(z,3) = gdiv(gel(x,3), y); return z;
2762 63 : case t_REAL: return divqf(x, y, realprec(y));
2763 14 : case t_PADIC: return divTp(x, y);
2764 0 : case t_COMPLEX:
2765 0 : ly = precision(y); if (!ly) pari_err_OP("/",x,y);
2766 0 : return divqf(x, y, ly);
2767 : }
2768 : }
2769 20295944 : switch(ty) {
2770 376856 : case t_REAL: case t_INTMOD: case t_PADIC: case t_POLMOD:
2771 376856 : return gmul(x, ginv(y)); /* missing gerepile, for speed */
2772 42 : case t_MAT:
2773 42 : av = avma; p1 = RgM_inv(y);
2774 35 : if (!p1) pari_err_INV("gdiv",y);
2775 28 : return gerepileupto(av, gmul(x, p1));
2776 0 : case t_VEC: case t_COL:
2777 : case t_LIST: case t_STR: case t_VECSMALL: case t_CLOSURE:
2778 0 : pari_err_TYPE2("/",x,y);
2779 : }
2780 19919046 : switch(tx) {
2781 3193635 : case t_VEC: case t_COL: case t_MAT:
2782 3193635 : z = cgetg_copy(x, &lx);
2783 11202609 : for (i=1; i<lx; i++) gel(z,i) = gdiv(gel(x,i),y);
2784 3193584 : return z;
2785 0 : case t_LIST: case t_STR: case t_VECSMALL: case t_CLOSURE:
2786 0 : pari_err_TYPE2("/",x,y);
2787 : }
2788 :
2789 16725411 : vy = gvar(y);
2790 16726136 : if (tx == t_POLMOD) { GEN X = gel(x,1);
2791 208824 : vx = varn(X);
2792 208824 : if (vx != vy) {
2793 208250 : if (varncmp(vx, vy) > 0) return div_scal_T(x, y, ty);
2794 207921 : retmkpolmod(gdiv(gel(x,2), y), RgX_copy(X));
2795 : }
2796 : /* y is POL, SER or RFRAC */
2797 574 : av = avma;
2798 574 : switch(ty)
2799 : {
2800 0 : case t_RFRAC: y = gmod(ginv(y), X); break;
2801 574 : default: y = ginvmod(gmod(y,X), X);
2802 : }
2803 567 : return gerepileupto(av, mul_polmod_same(X, gel(x,2), y));
2804 : }
2805 : /* x and y are not both is_scalar_t. If one of them is scalar, it's not a
2806 : * POLMOD (done already), hence its variable is NO_VARIABLE. If the other has
2807 : * variable NO_VARIABLE, then the operation is incorrect */
2808 16517312 : vx = gvar(x);
2809 16517309 : if (vx != vy) { /* includes cases where one is scalar */
2810 14622159 : if (varncmp(vx, vy) < 0) return div_T_scal(x, y, tx);
2811 9267221 : else return div_scal_T(x, y, ty);
2812 : }
2813 1895150 : switch(tx)
2814 : {
2815 1046164 : case t_POL:
2816 : switch(ty)
2817 : {
2818 28 : case t_SER:
2819 : {
2820 28 : GEN y0 = y;
2821 : long v;
2822 28 : av = avma; v = RgX_valrem(x, &x);
2823 28 : if (v == LONG_MAX) return gerepileupto(av, Rg_get_0(x));
2824 14 : v -= valser(y); ly = lg(y); /* > 2 */
2825 14 : y = ser2pol_i_normalize(y, ly, &i);
2826 14 : if (i)
2827 : {
2828 7 : pari_warn(warner,"normalizing a series with 0 leading term");
2829 7 : ly -= i; v -= i; if (ly <= 2) pari_err_INV("gdiv", y0);
2830 : }
2831 7 : z = init_ser(ly, vx, v);
2832 7 : return gerepilecopy(av, fill_ser(z, RgXn_div(x, y, ly-2)));
2833 : }
2834 :
2835 1046136 : case t_RFRAC:
2836 : {
2837 1046136 : GEN y1 = gel(y,1), y2 = gel(y,2);
2838 1046136 : if (typ(y1) == t_POL && varn(y1) == vx)
2839 35 : return mul_rfrac_scal(y2, y1, x);
2840 1046101 : av = avma;
2841 1046101 : return gerepileupto(av, RgX_Rg_div(RgX_mul(y2, x), y1));
2842 : }
2843 : }
2844 0 : break;
2845 :
2846 578143 : case t_SER:
2847 : switch(ty)
2848 : {
2849 578129 : case t_POL:
2850 : {
2851 578129 : long v = valser(x);
2852 578129 : lx = lg(x);
2853 578129 : if (lx == 2) return zeroser(vx, v - RgX_val(y));
2854 578024 : av = avma;
2855 578024 : x = ser2pol_i(x, lx); v -= RgX_valrem_inexact(y, &y);
2856 578024 : z = init_ser(lx, vx, v);
2857 578024 : if (!signe(x)) setsigne(z,0);
2858 578024 : return gerepilecopy(av, fill_ser(z, RgXn_div(x, y, lx - 2)));
2859 : }
2860 14 : case t_RFRAC:
2861 14 : av = avma;
2862 14 : return gerepileupto(av, gdiv(gmul(x,gel(y,2)), gel(y,1)));
2863 : }
2864 0 : break;
2865 :
2866 270821 : case t_RFRAC:
2867 : switch(ty)
2868 : {
2869 270821 : case t_POL: return div_rfrac_pol(gel(x,1),gel(x,2), y);
2870 0 : case t_SER:
2871 0 : av = avma;
2872 0 : return gerepileupto(av, gdiv(gel(x,1), gmul(gel(x,2), y)));
2873 : }
2874 0 : break;
2875 : }
2876 22 : pari_err_TYPE2("/",x,y);
2877 : return NULL; /* LCOV_EXCL_LINE */
2878 : }
2879 :
2880 : /********************************************************************/
2881 : /** **/
2882 : /** SIMPLE MULTIPLICATION **/
2883 : /** **/
2884 : /********************************************************************/
2885 : GEN
2886 235458010 : gmulsg(long s, GEN y)
2887 : {
2888 : long ly, i;
2889 : pari_sp av;
2890 : GEN z;
2891 :
2892 235458010 : switch(typ(y))
2893 : {
2894 144172421 : case t_INT: return mulsi(s,y);
2895 69959877 : case t_REAL: return s? mulsr(s,y): gen_0; /* gmul semantic */
2896 174400 : case t_INTMOD: { GEN p = gel(y,1);
2897 174400 : z = cgetg(3,t_INTMOD);
2898 174401 : gel(z,2) = gerepileuptoint((pari_sp)z, modii(mulsi(s,gel(y,2)), p));
2899 174399 : gel(z,1) = icopy(p); return z;
2900 : }
2901 548301 : case t_FFELT: return FF_Z_mul(y,stoi(s));
2902 5796425 : case t_FRAC:
2903 5796425 : if (!s) return gen_0;
2904 5791469 : z = cgetg(3,t_FRAC);
2905 5791469 : i = labs(s); i = ugcd(i, umodiu(gel(y,2), i));
2906 5791469 : if (i == 1)
2907 : {
2908 2217236 : gel(z,2) = icopy(gel(y,2));
2909 2217236 : gel(z,1) = mulis(gel(y,1), s);
2910 : }
2911 : else
2912 : {
2913 3574233 : gel(z,2) = diviuexact(gel(y,2), (ulong)i);
2914 3574233 : gel(z,1) = mulis(gel(y,1), s/i);
2915 3574233 : fix_frac_if_int(z);
2916 : }
2917 5791469 : return z;
2918 :
2919 13231035 : case t_COMPLEX:
2920 13231035 : if (!s) return gen_0;
2921 13156687 : z = cgetg(3, t_COMPLEX);
2922 13156602 : gel(z,1) = gmulsg(s,gel(y,1));
2923 13155292 : gel(z,2) = gmulsg(s,gel(y,2)); return z;
2924 :
2925 1435 : case t_PADIC:
2926 1435 : if (!s) return gen_0;
2927 1435 : av = avma; return gerepileupto(av, mulpp(cvtop2(stoi(s),y), y));
2928 :
2929 7 : case t_QUAD: z = cgetg(4, t_QUAD);
2930 7 : gel(z,1) = ZX_copy(gel(y,1));
2931 7 : gel(z,2) = gmulsg(s,gel(y,2));
2932 7 : gel(z,3) = gmulsg(s,gel(y,3)); return z;
2933 :
2934 105315 : case t_POLMOD:
2935 105315 : retmkpolmod(gmulsg(s,gel(y,2)), RgX_copy(gel(y,1)));
2936 :
2937 649308 : case t_POL:
2938 649308 : if (!signe(y)) return RgX_copy(y);
2939 634727 : if (!s) return scalarpol(Rg_get_0(y), varn(y));
2940 631514 : z = cgetg_copy(y, &ly); z[1]=y[1];
2941 2701644 : for (i=2; i<ly; i++) gel(z,i) = gmulsg(s,gel(y,i));
2942 631514 : return normalizepol_lg(z, ly);
2943 :
2944 182 : case t_SER:
2945 182 : if (ser_isexactzero(y)) return gcopy(y);
2946 182 : if (!s) return Rg_get_0(y);
2947 182 : z = cgetg_copy(y, &ly); z[1]=y[1];
2948 3864 : for (i=2; i<ly; i++) gel(z,i) = gmulsg(s,gel(y,i));
2949 182 : return normalizeser(z);
2950 :
2951 0 : case t_RFRAC:
2952 0 : if (!s) return zeropol(varn(gel(y,2)));
2953 0 : if (s == 1) return gcopy(y);
2954 0 : if (s == -1) return gneg(y);
2955 0 : return mul_rfrac_scal(gel(y,1), gel(y,2), stoi(s));
2956 :
2957 829383 : case t_VEC: case t_COL: case t_MAT:
2958 829383 : z = cgetg_copy(y, &ly);
2959 2262222 : for (i=1; i<ly; i++) gel(z,i) = gmulsg(s,gel(y,i));
2960 829381 : return z;
2961 : }
2962 0 : pari_err_TYPE("gmulsg",y);
2963 : return NULL; /* LCOV_EXCL_LINE */
2964 : }
2965 :
2966 : GEN
2967 133776217 : gmulug(ulong s, GEN y)
2968 : {
2969 : long ly, i;
2970 : pari_sp av;
2971 : GEN z;
2972 :
2973 133776217 : switch(typ(y))
2974 : {
2975 131708147 : case t_INT: return mului(s,y);
2976 1054628 : case t_REAL: return s? mulur(s,y): gen_0; /* gmul semantic */
2977 364 : case t_INTMOD: { GEN p = gel(y,1);
2978 364 : z = cgetg(3,t_INTMOD);
2979 364 : gel(z,2) = gerepileuptoint((pari_sp)z, modii(mului(s,gel(y,2)), p));
2980 364 : gel(z,1) = icopy(p); return z;
2981 : }
2982 413 : case t_FFELT: return FF_Z_mul(y,utoi(s));
2983 946697 : case t_FRAC:
2984 946697 : if (!s) return gen_0;
2985 946683 : z = cgetg(3,t_FRAC);
2986 946683 : i = ugcd(s, umodiu(gel(y,2), s));
2987 946683 : if (i == 1)
2988 : {
2989 794293 : gel(z,2) = icopy(gel(y,2));
2990 794293 : gel(z,1) = muliu(gel(y,1), s);
2991 : }
2992 : else
2993 : {
2994 152390 : gel(z,2) = diviuexact(gel(y,2), i);
2995 152390 : gel(z,1) = muliu(gel(y,1), s/i);
2996 152390 : fix_frac_if_int(z);
2997 : }
2998 946683 : return z;
2999 :
3000 24799 : case t_COMPLEX:
3001 24799 : if (!s) return gen_0;
3002 24799 : z = cgetg(3, t_COMPLEX);
3003 24799 : gel(z,1) = gmulug(s,gel(y,1));
3004 24799 : gel(z,2) = gmulug(s,gel(y,2)); return z;
3005 :
3006 3898 : case t_PADIC:
3007 3898 : if (!s) return gen_0;
3008 3898 : av = avma; return gerepileupto(av, mulpp(cvtop2(utoi(s),y), y));
3009 :
3010 0 : case t_QUAD: z = cgetg(4, t_QUAD);
3011 0 : gel(z,1) = ZX_copy(gel(y,1));
3012 0 : gel(z,2) = gmulug(s,gel(y,2));
3013 0 : gel(z,3) = gmulug(s,gel(y,3)); return z;
3014 :
3015 6783 : case t_POLMOD:
3016 6783 : retmkpolmod(gmulug(s,gel(y,2)), RgX_copy(gel(y,1)));
3017 :
3018 16226 : case t_POL:
3019 16226 : if (!signe(y)) return RgX_copy(y);
3020 15449 : if (!s) return scalarpol(Rg_get_0(y), varn(y));
3021 15449 : z = cgetg_copy(y, &ly); z[1]=y[1];
3022 52843 : for (i=2; i<ly; i++) gel(z,i) = gmulug(s,gel(y,i));
3023 15449 : return normalizepol_lg(z, ly);
3024 :
3025 0 : case t_SER:
3026 0 : if (ser_isexactzero(y)) return gcopy(y);
3027 0 : if (!s) return Rg_get_0(y);
3028 0 : z = cgetg_copy(y, &ly); z[1]=y[1];
3029 0 : for (i=2; i<ly; i++) gel(z,i) = gmulug(s,gel(y,i));
3030 0 : return normalizeser(z);
3031 :
3032 0 : case t_RFRAC:
3033 0 : if (!s) return zeropol(varn(gel(y,2)));
3034 0 : if (s == 1) return gcopy(y);
3035 0 : return mul_rfrac_scal(gel(y,1), gel(y,2), utoi(s));
3036 :
3037 14266 : case t_VEC: case t_COL: case t_MAT:
3038 14266 : z = cgetg_copy(y, &ly);
3039 74267 : for (i=1; i<ly; i++) gel(z,i) = gmulug(s,gel(y,i));
3040 14267 : return z;
3041 : }
3042 0 : pari_err_TYPE("gmulsg",y);
3043 : return NULL; /* LCOV_EXCL_LINE */
3044 : }
3045 :
3046 : /********************************************************************/
3047 : /** **/
3048 : /** SIMPLE DIVISION **/
3049 : /** **/
3050 : /********************************************************************/
3051 :
3052 : GEN
3053 8696287 : gdivgs(GEN x, long s)
3054 : {
3055 8696287 : long tx = typ(x), lx, i;
3056 : pari_sp av;
3057 : GEN z;
3058 :
3059 8696287 : if (!s)
3060 : {
3061 0 : if (is_matvec_t(tx) && lg(x) == 1) return gcopy(x);
3062 0 : pari_err_INV("gdivgs",gen_0);
3063 : }
3064 8696292 : switch(tx)
3065 : {
3066 1460136 : case t_INT: return Qdivis(x, s);
3067 5890405 : case t_REAL: return divrs(x,s);
3068 :
3069 357 : case t_INTMOD:
3070 357 : z = cgetg(3, t_INTMOD);
3071 357 : return div_intmod_same(z, gel(x,1), gel(x,2), modsi(s, gel(x,1)));
3072 :
3073 735 : case t_FFELT: return FF_Z_Z_muldiv(x,gen_1,stoi(s));
3074 :
3075 505513 : case t_FRAC: z = cgetg(3, t_FRAC);
3076 505513 : i = labs(s); i = ugcd(i, umodiu(gel(x,1), i));
3077 505513 : if (i == 1)
3078 : {
3079 376712 : gel(z,2) = mulsi(s, gel(x,2));
3080 376712 : gel(z,1) = icopy(gel(x,1));
3081 : }
3082 : else
3083 : {
3084 128801 : gel(z,2) = mulsi(s/i, gel(x,2));
3085 128801 : gel(z,1) = divis(gel(x,1), i);
3086 : }
3087 505513 : normalize_frac(z);
3088 505513 : fix_frac_if_int(z); return z;
3089 :
3090 761852 : case t_COMPLEX: z = cgetg(3, t_COMPLEX);
3091 761852 : gel(z,1) = gdivgs(gel(x,1),s);
3092 761847 : gel(z,2) = gdivgs(gel(x,2),s); return z;
3093 :
3094 133 : case t_PADIC: /* divpT */
3095 : {
3096 133 : GEN p = gel(x,2);
3097 133 : if (!signe(gel(x,4))) return zeropadic(p, valp(x) - u_pval(s,p));
3098 133 : av = avma;
3099 133 : return gerepileupto(av, divpp(x, cvtop2(stoi(s),x)));
3100 : }
3101 :
3102 28 : case t_QUAD: z = cgetg(4, t_QUAD);
3103 28 : gel(z,1) = ZX_copy(gel(x,1));
3104 28 : gel(z,2) = gdivgs(gel(x,2),s);
3105 28 : gel(z,3) = gdivgs(gel(x,3),s); return z;
3106 :
3107 37702 : case t_POLMOD:
3108 37702 : retmkpolmod(gdivgs(gel(x,2),s), RgX_copy(gel(x,1)));
3109 :
3110 91 : case t_RFRAC:
3111 91 : if (s == 1) return gcopy(x);
3112 84 : else if (s == -1) return gneg(x);
3113 84 : return div_rfrac_scal(x, stoi(s));
3114 :
3115 37499 : case t_POL: case t_SER:
3116 37499 : z = cgetg_copy(x, &lx); z[1] = x[1];
3117 157247 : for (i=2; i<lx; i++) gel(z,i) = gdivgs(gel(x,i),s);
3118 37499 : return z;
3119 1841 : case t_VEC: case t_COL: case t_MAT:
3120 1841 : z = cgetg_copy(x, &lx);
3121 41335 : for (i=1; i<lx; i++) gel(z,i) = gdivgs(gel(x,i),s);
3122 1841 : return z;
3123 :
3124 : }
3125 0 : pari_err_TYPE2("/",x, stoi(s));
3126 : return NULL; /* LCOV_EXCL_LINE */
3127 : }
3128 :
3129 : GEN
3130 43477312 : gdivgu(GEN x, ulong s)
3131 : {
3132 43477312 : long tx = typ(x), lx, i;
3133 : pari_sp av;
3134 : GEN z;
3135 :
3136 43477312 : if (!s)
3137 : {
3138 0 : if (is_matvec_t(tx) && lg(x) == 1) return gcopy(x);
3139 0 : pari_err_INV("gdivgu",gen_0);
3140 : }
3141 43477323 : switch(tx)
3142 : {
3143 17264706 : case t_INT: return Qdiviu(x, s);
3144 12899820 : case t_REAL: return divru(x,s);
3145 :
3146 210315 : case t_INTMOD:
3147 210315 : z = cgetg(3, t_INTMOD); s = umodui(s, gel(x,1));
3148 210315 : return div_intmod_same(z, gel(x,1), gel(x,2), utoi(s));
3149 :
3150 308 : case t_FFELT: return FF_Z_Z_muldiv(x,gen_1,utoi(s));
3151 :
3152 636732 : case t_FRAC: z = cgetg(3, t_FRAC);
3153 636732 : i = ugcd(s, umodiu(gel(x,1), s));
3154 636732 : if (i == 1)
3155 : {
3156 457367 : gel(z,2) = mului(s, gel(x,2));
3157 457367 : gel(z,1) = icopy(gel(x,1));
3158 : }
3159 : else
3160 : {
3161 179365 : gel(z,2) = mului(s/i, gel(x,2));
3162 179365 : gel(z,1) = divis(gel(x,1), i);
3163 : }
3164 636732 : normalize_frac(z);
3165 636732 : fix_frac_if_int(z); return z;
3166 :
3167 11558917 : case t_COMPLEX: z = cgetg(3, t_COMPLEX);
3168 11558919 : gel(z,1) = gdivgu(gel(x,1),s);
3169 11558917 : gel(z,2) = gdivgu(gel(x,2),s); return z;
3170 :
3171 853031 : case t_PADIC: /* divpT */
3172 : {
3173 853031 : GEN p = gel(x,2);
3174 853031 : if (!signe(gel(x,4))) return zeropadic(p, valp(x) - u_pval(s,p));
3175 718958 : av = avma;
3176 718958 : return gerepileupto(av, divpp(x, cvtop2(utoi(s),x)));
3177 : }
3178 :
3179 0 : case t_QUAD: z = cgetg(4, t_QUAD);
3180 0 : gel(z,1) = ZX_copy(gel(x,1));
3181 0 : gel(z,2) = gdivgu(gel(x,2),s);
3182 0 : gel(z,3) = gdivgu(gel(x,3),s); return z;
3183 :
3184 1456 : case t_POLMOD:
3185 1456 : retmkpolmod(gdivgu(gel(x,2),s), RgX_copy(gel(x,1)));
3186 :
3187 56 : case t_RFRAC:
3188 56 : if (s == 1) return gcopy(x);
3189 56 : return div_rfrac_scal(x, utoi(s));
3190 :
3191 51681 : case t_POL: case t_SER:
3192 51681 : z = cgetg_copy(x, &lx); z[1] = x[1];
3193 219268 : for (i=2; i<lx; i++) gel(z,i) = gdivgu(gel(x,i),s);
3194 51681 : return z;
3195 301 : case t_VEC: case t_COL: case t_MAT:
3196 301 : z = cgetg_copy(x, &lx);
3197 1092 : for (i=1; i<lx; i++) gel(z,i) = gdivgu(gel(x,i),s);
3198 301 : return z;
3199 : }
3200 0 : pari_err_TYPE2("/",x, utoi(s));
3201 : return NULL; /* LCOV_EXCL_LINE */
3202 : }
3203 :
3204 : /* x / (i*(i+1)) */
3205 : GEN
3206 106663958 : divrunextu(GEN x, ulong i)
3207 : {
3208 106663958 : if (i & HIGHMASK) /* i(i+1) >= 2^BITS_IN_LONG*/
3209 0 : return divri(x, muluu(i , i+1));
3210 : else
3211 106663958 : return divru(x, i*(i+1));
3212 : }
3213 : /* x / (i*(i+1)) */
3214 : GEN
3215 804801 : gdivgunextu(GEN x, ulong i)
3216 : {
3217 804801 : if (i & HIGHMASK) /* i(i+1) >= 2^BITS_IN_LONG*/
3218 0 : return gdivgu(x, i*(i+1));
3219 : else
3220 804801 : return gdiv(x, muluu(i, i+1));
3221 : }
3222 :
3223 : /* True shift (exact multiplication by 2^n) */
3224 : GEN
3225 76203415 : gmul2n(GEN x, long n)
3226 : {
3227 : long lx, i, k, l;
3228 : GEN z, a, b;
3229 :
3230 76203415 : switch(typ(x))
3231 : {
3232 20425287 : case t_INT:
3233 20425287 : if (n>=0) return shifti(x,n);
3234 3392737 : if (!signe(x)) return gen_0;
3235 3296773 : l = vali(x); n = -n;
3236 3296817 : if (n<=l) return shifti(x,-n);
3237 376708 : z = cgetg(3,t_FRAC);
3238 376708 : gel(z,1) = shifti(x,-l);
3239 376708 : gel(z,2) = int2n(n-l); return z;
3240 :
3241 39919394 : case t_REAL:
3242 39919394 : return shiftr(x,n);
3243 :
3244 181101 : case t_INTMOD: b = gel(x,1); a = gel(x,2);
3245 181101 : z = cgetg(3,t_INTMOD);
3246 181100 : if (n <= 0) return div_intmod_same(z, b, a, modii(int2n(-n), b));
3247 82939 : gel(z,2) = gerepileuptoint((pari_sp)z, modii(shifti(a,n), b));
3248 82940 : gel(z,1) = icopy(b); return z;
3249 :
3250 217445 : case t_FFELT: return FF_mul2n(x,n);
3251 :
3252 871311 : case t_FRAC: a = gel(x,1); b = gel(x,2);
3253 871311 : l = vali(a);
3254 871311 : k = vali(b);
3255 871311 : if (n+l >= k)
3256 : {
3257 327558 : if (expi(b) == k) return shifti(a,n-k); /* b power of 2 */
3258 264794 : l = n-k; k = -k;
3259 : }
3260 : else
3261 : {
3262 543753 : k = -(l+n); l = -l;
3263 : }
3264 808547 : z = cgetg(3,t_FRAC);
3265 808547 : gel(z,1) = shifti(a,l);
3266 808547 : gel(z,2) = shifti(b,k); return z;
3267 :
3268 8319074 : case t_COMPLEX: z = cgetg(3,t_COMPLEX);
3269 8319069 : gel(z,1) = gmul2n(gel(x,1),n);
3270 8319099 : gel(z,2) = gmul2n(gel(x,2),n); return z;
3271 :
3272 105 : case t_QUAD: z = cgetg(4,t_QUAD);
3273 105 : gel(z,1) = ZX_copy(gel(x,1));
3274 105 : gel(z,2) = gmul2n(gel(x,2),n);
3275 105 : gel(z,3) = gmul2n(gel(x,3),n); return z;
3276 :
3277 55041 : case t_POLMOD:
3278 55041 : retmkpolmod(gmul2n(gel(x,2),n), RgX_copy(gel(x,1)));
3279 :
3280 1594748 : case t_POL:
3281 1594748 : z = cgetg_copy(x, &lx); z[1] = x[1];
3282 8665318 : for (i=2; i<lx; i++) gel(z,i) = gmul2n(gel(x,i),n);
3283 1594644 : return normalizepol_lg(z, lx); /* needed if char = 2 */
3284 98899 : case t_SER:
3285 98899 : if (ser_isexactzero(x)) return gcopy(x);
3286 98871 : z = cgetg_copy(x, &lx); z[1] = x[1];
3287 619311 : for (i=2; i<lx; i++) gel(z,i) = gmul2n(gel(x,i),n);
3288 98871 : return normalizeser(z); /* needed if char = 2 */
3289 4517828 : case t_VEC: case t_COL: case t_MAT:
3290 4517828 : z = cgetg_copy(x, &lx);
3291 17681630 : for (i=1; i<lx; i++) gel(z,i) = gmul2n(gel(x,i),n);
3292 4517789 : return z;
3293 :
3294 21 : case t_RFRAC: /* int2n wrong if n < 0 */
3295 21 : return mul_rfrac_scal(gel(x,1),gel(x,2), gmul2n(gen_1,n));
3296 :
3297 4536 : case t_PADIC: /* int2n wrong if n < 0 */
3298 4536 : return gmul(gmul2n(gen_1,n),x);
3299 : }
3300 0 : pari_err_TYPE("gmul2n",x);
3301 : return NULL; /* LCOV_EXCL_LINE */
3302 : }
3303 :
3304 : /*******************************************************************/
3305 : /* */
3306 : /* INVERSE */
3307 : /* */
3308 : /*******************************************************************/
3309 : static GEN
3310 79889 : inv_polmod(GEN T, GEN x)
3311 : {
3312 79889 : GEN z = cgetg(3,t_POLMOD), a;
3313 79888 : gel(z,1) = RgX_copy(T);
3314 79888 : if (typ(x) != t_POL || varn(x) != varn(T) || lg(x) <= 3)
3315 62665 : a = ginv(x);
3316 : else
3317 : {
3318 17223 : if (lg(T) == 5) /* quadratic fields */
3319 13027 : a = RgX_Rg_div(quad_polmod_conj(x,T), quad_polmod_norm(x,T));
3320 : else
3321 4196 : a = RgXQ_inv(x, T);
3322 : }
3323 79889 : gel(z,2) = a; return z;
3324 : }
3325 :
3326 : GEN
3327 23352127 : ginv(GEN x)
3328 : {
3329 : long s;
3330 : pari_sp av, tetpil;
3331 : GEN z, y, p1, p2;
3332 :
3333 23352127 : switch(typ(x))
3334 : {
3335 4111269 : case t_INT:
3336 4111269 : if (is_pm1(x)) return icopy(x);
3337 2584254 : s = signe(x); if (!s) pari_err_INV("ginv",gen_0);
3338 2584240 : z = cgetg(3,t_FRAC);
3339 2584263 : gel(z,1) = s<0? gen_m1: gen_1;
3340 2584263 : gel(z,2) = absi(x); return z;
3341 :
3342 5968352 : case t_REAL: return invr(x);
3343 :
3344 12754 : case t_INTMOD: z=cgetg(3,t_INTMOD);
3345 12754 : gel(z,1) = icopy(gel(x,1));
3346 12754 : gel(z,2) = Fp_inv(gel(x,2),gel(x,1)); return z;
3347 :
3348 425750 : case t_FRAC: {
3349 425750 : GEN a = gel(x,1), b = gel(x,2);
3350 425750 : s = signe(a);
3351 425750 : if (is_pm1(a)) return s > 0? icopy(b): negi(b);
3352 243384 : z = cgetg(3,t_FRAC);
3353 243384 : gel(z,1) = icopy(b);
3354 243384 : gel(z,2) = icopy(a);
3355 243384 : normalize_frac(z); return z;
3356 : }
3357 6915966 : case t_COMPLEX:
3358 6915966 : av=avma;
3359 6915966 : p1=cxnorm(x);
3360 6915085 : p2=mkcomplex(gel(x,1), gneg(gel(x,2)));
3361 6915827 : tetpil=avma;
3362 6915827 : return gerepile(av,tetpil,divcR(p2,p1));
3363 :
3364 273 : case t_QUAD:
3365 273 : av=avma; p1=quadnorm(x); p2=conj_i(x); tetpil=avma;
3366 273 : return gerepile(av,tetpil,gdiv(p2,p1));
3367 :
3368 346227 : case t_PADIC: z = cgetg(5,t_PADIC);
3369 346227 : if (!signe(gel(x,4))) pari_err_INV("ginv",x);
3370 346220 : z[1] = _evalprecp(precp(x)) | evalvalp(-valp(x));
3371 346220 : gel(z,2) = icopy(gel(x,2));
3372 346220 : gel(z,3) = icopy(gel(x,3));
3373 346220 : gel(z,4) = Zp_inv(gel(x,4),gel(z,2),precp(x)); return z;
3374 :
3375 79889 : case t_POLMOD: return inv_polmod(gel(x,1), gel(x,2));
3376 14249 : case t_FFELT: return FF_inv(x);
3377 5321022 : case t_POL: return gred_rfrac_simple(gen_1,x);
3378 19418 : case t_SER: return ser_inv(x);
3379 2926 : case t_RFRAC:
3380 : {
3381 2926 : GEN n = gel(x,1), d = gel(x,2);
3382 2926 : pari_sp av = avma, ltop;
3383 2926 : if (gequal0(n)) pari_err_INV("ginv",x);
3384 :
3385 2926 : n = simplify_shallow(n);
3386 2926 : if (typ(n) != t_POL || varn(n) != varn(d))
3387 : {
3388 2926 : if (gequal1(n)) { set_avma(av); return RgX_copy(d); }
3389 679 : ltop = avma;
3390 679 : z = RgX_Rg_div(d,n);
3391 : } else {
3392 0 : ltop = avma;
3393 0 : z = cgetg(3,t_RFRAC);
3394 0 : gel(z,1) = RgX_copy(d);
3395 0 : gel(z,2) = RgX_copy(n);
3396 : }
3397 679 : stackdummy(av, ltop);
3398 679 : return z;
3399 : }
3400 :
3401 21 : case t_VEC: if (!is_ext_qfr(x)) break;
3402 : case t_QFB:
3403 99476 : return qfbpow(x, gen_m1);
3404 34667 : case t_MAT:
3405 34667 : y = RgM_inv(x);
3406 34660 : if (!y) pari_err_INV("ginv",x);
3407 34590 : return y;
3408 28 : case t_VECSMALL:
3409 : {
3410 28 : long i, lx = lg(x)-1;
3411 28 : y = zero_zv(lx);
3412 112 : for (i=1; i<=lx; i++)
3413 : {
3414 84 : long xi = x[i];
3415 84 : if (xi<1 || xi>lx || y[xi])
3416 0 : pari_err_TYPE("ginv [not a permutation]", x);
3417 84 : y[xi] = i;
3418 : }
3419 28 : return y;
3420 : }
3421 : }
3422 6 : pari_err_TYPE("inverse",x);
3423 : return NULL; /* LCOV_EXCL_LINE */
3424 : }
|