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 : #include "pari.h"
16 : #include "paripriv.h"
17 :
18 : int
19 1243905 : RgM_is_ZM(GEN x)
20 : {
21 1243905 : long i, j, h, l = lg(x);
22 1243905 : if (l == 1) return 1;
23 1243240 : h = lgcols(x);
24 1243235 : if (h == 1) return 1;
25 4698412 : for (j = l-1; j > 0; j--)
26 22380496 : for (i = h-1; i > 0; i--)
27 18925158 : if (typ(gcoeff(x,i,j)) != t_INT) return 0;
28 1082893 : return 1;
29 : }
30 :
31 : int
32 203 : RgM_is_QM(GEN x)
33 : {
34 203 : long i, j, h, l = lg(x);
35 203 : if (l == 1) return 1;
36 189 : h = lgcols(x);
37 189 : if (h == 1) return 1;
38 1218 : for (j = l-1; j > 0; j--)
39 15057 : for (i = h-1; i > 0; i--)
40 14028 : if (!is_rational_t(typ(gcoeff(x,i,j)))) return 0;
41 175 : return 1;
42 : }
43 :
44 : int
45 49 : RgV_is_ZMV(GEN V)
46 : {
47 49 : long i, l = lg(V);
48 399 : for (i=1; i<l; i++)
49 350 : if (typ(gel(V,i))!=t_MAT || !RgM_is_ZM(gel(V,i)))
50 0 : return 0;
51 49 : return 1;
52 : }
53 :
54 : /********************************************************************/
55 : /** **/
56 : /** GENERIC LINEAR ALGEBRA **/
57 : /** **/
58 : /********************************************************************/
59 : /* GENERIC MULTIPLICATION involving zc/zm */
60 :
61 : /* x[i,] * y */
62 : static GEN
63 8289346 : RgMrow_zc_mul_i(GEN x, GEN y, long c, long i)
64 : {
65 8289346 : pari_sp av = avma;
66 8289346 : GEN s = NULL;
67 : long j;
68 828977485 : for (j=1; j<c; j++)
69 : {
70 820691825 : long t = y[j];
71 820691825 : if (!t) continue;
72 28444369 : if (!s) { s = gmulgs(gcoeff(x,i,j),t); continue; }
73 20368359 : switch(t)
74 : {
75 14793180 : case 1: s = gadd(s, gcoeff(x,i,j)); break;
76 239856 : case -1: s = gsub(s, gcoeff(x,i,j)); break;
77 5335323 : default: s = gadd(s, gmulgs(gcoeff(x,i,j), t)); break;
78 : }
79 : }
80 8285660 : return s? gerepileupto(av, s): gc_const(av, gen_0);
81 : }
82 : GEN
83 70028 : RgMrow_zc_mul(GEN x, GEN y, long i) { return RgMrow_zc_mul_i(x,y,lg(y),i); }
84 : /* x nonempty t_MAT, y a compatible zc (dimension > 0). */
85 : static GEN
86 239051 : RgM_zc_mul_i(GEN x, GEN y, long c, long l)
87 : {
88 239051 : GEN z = cgetg(l,t_COL);
89 : long i;
90 8458353 : for (i = 1; i < l; i++) gel(z,i) = RgMrow_zc_mul_i(x,y,c,i);
91 239048 : return z;
92 : }
93 : GEN
94 71967 : RgM_zc_mul(GEN x, GEN y) { return RgM_zc_mul_i(x,y, lg(x), lgcols(x)); }
95 : /* x t_MAT, y a compatible zm (dimension > 0). */
96 : GEN
97 56782 : RgM_zm_mul(GEN x, GEN y)
98 : {
99 56782 : long j, c, l = lg(x), ly = lg(y);
100 56782 : GEN z = cgetg(ly, t_MAT);
101 56782 : if (l == 1) return z;
102 56782 : c = lgcols(x);
103 223866 : for (j = 1; j < ly; j++) gel(z,j) = RgM_zc_mul_i(x, gel(y,j), l,c);
104 56782 : return z;
105 : }
106 :
107 : /* x[i,]*y, l = lg(y) > 1 */
108 : static GEN
109 32308077 : RgMrow_ZC_mul_i(GEN x, GEN y, long i, long l)
110 : {
111 32308077 : pari_sp av = avma;
112 32308077 : GEN t = gmul(gcoeff(x,i,1), gel(y,1)); /* l > 1 ! */
113 : long j;
114 5020877189 : for (j=2; j<l; j++)
115 4988703837 : if (signe(gel(y,j))) t = gadd(t, gmul(gcoeff(x,i,j), gel(y,j)));
116 32173352 : return gerepileupto(av,t);
117 : }
118 :
119 : /* compatible t_MAT * t_COL, lx = lg(x) = lg(y) > 1, l = lgcols(x) */
120 : static GEN
121 1927610 : RgM_ZC_mul_i(GEN x, GEN y, long lx, long l)
122 : {
123 1927610 : GEN z = cgetg(l,t_COL);
124 : long i;
125 34239279 : for (i=1; i<l; i++) gel(z,i) = RgMrow_ZC_mul_i(x,y,i,lx);
126 1925118 : return z;
127 : }
128 :
129 : GEN
130 1927640 : RgM_ZM_mul_worker(GEN y, GEN x)
131 1927640 : { return RgM_ZC_mul_i(x, y, lg(x), lgcols(x)); }
132 :
133 : /* mostly useful when y is sparse */
134 : GEN
135 354666 : RgM_ZM_mul(GEN x, GEN y)
136 : {
137 354666 : pari_sp av = avma;
138 : GEN worker;
139 354666 : if (lg(x) == 1) return cgetg(lg(y), t_MAT);
140 354666 : worker = snm_closure(is_entry("_RgM_ZM_mul_worker"),mkvec(x));
141 354671 : return gerepileupto(av, gen_parapply(worker, y));
142 : }
143 :
144 : static GEN
145 209918 : RgV_zc_mul_i(GEN x, GEN y, long l)
146 : {
147 : long i;
148 209918 : GEN z = gen_0;
149 209918 : pari_sp av = avma;
150 8212225 : for (i = 1; i < l; i++) z = gadd(z, gmulgs(gel(x,i), y[i]));
151 209915 : return gerepileupto(av, z);
152 : }
153 : GEN
154 83384 : RgV_zc_mul(GEN x, GEN y) { return RgV_zc_mul_i(x, y, lg(x)); }
155 :
156 : GEN
157 34193 : RgV_zm_mul(GEN x, GEN y)
158 : {
159 34193 : long j, l = lg(x), ly = lg(y);
160 34193 : GEN z = cgetg(ly, t_VEC);
161 160727 : for (j = 1; j < ly; j++) gel(z,j) = RgV_zc_mul_i(x, gel(y,j), l);
162 34193 : return z;
163 : }
164 :
165 : /* scalar product x.x */
166 : GEN
167 9441206 : RgV_dotsquare(GEN x)
168 : {
169 9441206 : long i, lx = lg(x);
170 9441206 : pari_sp av = avma;
171 : GEN z;
172 9441206 : if (lx == 1) return gen_0;
173 9441206 : z = gsqr(gel(x,1));
174 21152077 : for (i=2; i<lx; i++)
175 : {
176 11711103 : z = gadd(z, gsqr(gel(x,i)));
177 11711023 : if (gc_needed(av,3))
178 : {
179 0 : if(DEBUGMEM>1) pari_warn(warnmem,"RgV_dotsquare, i = %ld",i);
180 0 : z = gerepileupto(av, z);
181 : }
182 : }
183 9440974 : return gerepileupto(av,z);
184 : }
185 :
186 : /* scalar product x.y, lx = lg(x) = lg(y) */
187 : static GEN
188 13591694 : RgV_dotproduct_i(GEN x, GEN y, long lx)
189 : {
190 13591694 : pari_sp av = avma;
191 : long i;
192 : GEN z;
193 13591694 : if (lx == 1) return gen_0;
194 13591295 : z = gmul(gel(x,1),gel(y,1));
195 218970672 : for (i=2; i<lx; i++)
196 : {
197 205382026 : z = gadd(z, gmul(gel(x,i), gel(y,i)));
198 205382044 : if (gc_needed(av,3))
199 : {
200 0 : if(DEBUGMEM>1) pari_warn(warnmem,"RgV_dotproduct, i = %ld",i);
201 0 : z = gerepileupto(av, z);
202 : }
203 : }
204 13588646 : return gerepileupto(av,z);
205 : }
206 : GEN
207 1009450 : RgV_dotproduct(GEN x,GEN y)
208 : {
209 1009450 : if (x == y) return RgV_dotsquare(x);
210 1009450 : return RgV_dotproduct_i(x, y, lg(x));
211 : }
212 : /* v[1] + ... + v[lg(v)-1] */
213 : GEN
214 3032228 : RgV_sum(GEN v)
215 : {
216 : GEN p;
217 3032228 : long i, l = lg(v);
218 3032228 : if (l == 1) return gen_0;
219 7379527 : p = gel(v,1); for (i=2; i<l; i++) p = gadd(p, gel(v,i));
220 3032188 : return p;
221 : }
222 : /* v[1] + ... + v[n]. Assume lg(v) > n. */
223 : GEN
224 0 : RgV_sumpart(GEN v, long n)
225 : {
226 : GEN p;
227 : long i;
228 0 : if (!n) return gen_0;
229 0 : p = gel(v,1); for (i=2; i<=n; i++) p = gadd(p, gel(v,i));
230 0 : return p;
231 : }
232 : /* v[m] + ... + v[n]. Assume lg(v) > n, m > 0. */
233 : GEN
234 0 : RgV_sumpart2(GEN v, long m, long n)
235 : {
236 : GEN p;
237 : long i;
238 0 : if (n < m) return gen_0;
239 0 : p = gel(v,m); for (i=m+1; i<=n; i++) p = gadd(p, gel(v,i));
240 0 : return p;
241 : }
242 : GEN
243 400 : RgM_sumcol(GEN A)
244 : {
245 400 : long i,j,m,l = lg(A);
246 : GEN v;
247 :
248 400 : if (l == 1) return cgetg(1,t_MAT);
249 400 : if (l == 2) return gcopy(gel(A,1));
250 216 : m = lgcols(A);
251 216 : v = cgetg(m, t_COL);
252 718 : for (i = 1; i < m; i++)
253 : {
254 502 : pari_sp av = avma;
255 502 : GEN s = gcoeff(A,i,1);
256 1214 : for (j = 2; j < l; j++) s = gadd(s, gcoeff(A,i,j));
257 502 : gel(v, i) = gerepileupto(av, s);
258 : }
259 216 : return v;
260 : }
261 :
262 : static GEN
263 3335131 : _gmul(void *data, GEN x, GEN y)
264 3335131 : { (void)data; return gmul(x,y); }
265 :
266 : GEN
267 451819 : RgV_prod(GEN x)
268 : {
269 451819 : return gen_product(x, NULL, _gmul);
270 : }
271 :
272 : /* ADDITION SCALAR + MATRIX */
273 : /* x square matrix, y scalar; create the square matrix x + y*Id */
274 : GEN
275 7874 : RgM_Rg_add(GEN x, GEN y)
276 : {
277 7874 : long l = lg(x), i, j;
278 7874 : GEN z = cgetg(l,t_MAT);
279 :
280 7874 : if (l==1) return z;
281 7874 : if (l != lgcols(x)) pari_err_OP("+", x, y);
282 58132 : for (i=1; i<l; i++)
283 : {
284 50258 : GEN zi = cgetg(l,t_COL), xi = gel(x,i);
285 50258 : gel(z,i) = zi;
286 2058760 : for (j=1; j<l; j++)
287 2008502 : gel(zi,j) = i==j? gadd(y,gel(xi,j)): gcopy(gel(xi,j));
288 : }
289 7874 : return z;
290 : }
291 : GEN
292 0 : RgM_Rg_sub(GEN x, GEN y)
293 : {
294 0 : long l = lg(x), i, j;
295 0 : GEN z = cgetg(l,t_MAT);
296 :
297 0 : if (l==1) return z;
298 0 : if (l != lgcols(x)) pari_err_OP("-", x, y);
299 0 : for (i=1; i<l; i++)
300 : {
301 0 : GEN zi = cgetg(l,t_COL), xi = gel(x,i);
302 0 : gel(z,i) = zi;
303 0 : for (j=1; j<l; j++)
304 0 : gel(zi,j) = i==j? gsub(gel(xi,j), y): gcopy(gel(xi,j));
305 : }
306 0 : return z;
307 : }
308 : GEN
309 739 : RgM_Rg_add_shallow(GEN x, GEN y)
310 : {
311 739 : long l = lg(x), i, j;
312 739 : GEN z = cgetg(l,t_MAT);
313 :
314 739 : if (l==1) return z;
315 739 : if (l != lgcols(x)) pari_err_OP( "+", x, y);
316 2384 : for (i=1; i<l; i++)
317 : {
318 1645 : GEN zi = cgetg(l,t_COL), xi = gel(x,i);
319 1645 : gel(z,i) = zi;
320 9456 : for (j=1; j<l; j++) gel(zi,j) = gel(xi,j);
321 1645 : gel(zi,i) = gadd(gel(zi,i), y);
322 : }
323 739 : return z;
324 : }
325 : GEN
326 312562 : RgM_Rg_sub_shallow(GEN x, GEN y)
327 : {
328 312562 : long l = lg(x), i, j;
329 312562 : GEN z = cgetg(l,t_MAT);
330 :
331 312562 : if (l==1) return z;
332 312562 : if (l != lgcols(x)) pari_err_OP( "-", x, y);
333 2015179 : for (i=1; i<l; i++)
334 : {
335 1702636 : GEN zi = cgetg(l,t_COL), xi = gel(x,i);
336 1702636 : gel(z,i) = zi;
337 27145064 : for (j=1; j<l; j++) gel(zi,j) = gel(xi,j);
338 1702636 : gel(zi,i) = gsub(gel(zi,i), y);
339 : }
340 312543 : return z;
341 : }
342 :
343 : GEN
344 5182680 : RgC_Rg_add(GEN x, GEN y)
345 : {
346 5182680 : long k, lx = lg(x);
347 5182680 : GEN z = cgetg(lx, t_COL);
348 5182681 : if (lx == 1)
349 : {
350 0 : if (isintzero(y)) return z;
351 0 : pari_err_TYPE2("+",x,y);
352 : }
353 5182681 : gel(z,1) = gadd(y,gel(x,1));
354 13028189 : for (k = 2; k < lx; k++) gel(z,k) = gcopy(gel(x,k));
355 5182680 : return z;
356 : }
357 : GEN
358 42043 : RgC_Rg_sub(GEN x, GEN y)
359 : {
360 42043 : long k, lx = lg(x);
361 42043 : GEN z = cgetg(lx, t_COL);
362 42043 : if (lx == 1)
363 : {
364 0 : if (isintzero(y)) return z;
365 0 : pari_err_TYPE2("-",x,y);
366 : }
367 42043 : gel(z,1) = gsub(gel(x,1), y);
368 108421 : for (k = 2; k < lx; k++) gel(z,k) = gcopy(gel(x,k));
369 42043 : return z;
370 : }
371 : /* a - x */
372 : GEN
373 135442 : Rg_RgC_sub(GEN a, GEN x)
374 : {
375 135442 : long k, lx = lg(x);
376 135442 : GEN z = cgetg(lx,t_COL);
377 135442 : if (lx == 1)
378 : {
379 0 : if (isintzero(a)) return z;
380 0 : pari_err_TYPE2("-",a,x);
381 : }
382 135442 : gel(z,1) = gsub(a, gel(x,1));
383 305962 : for (k = 2; k < lx; k++) gel(z,k) = gneg(gel(x,k));
384 135442 : return z;
385 : }
386 :
387 : static GEN
388 19432101 : RgC_add_i(GEN x, GEN y, long lx)
389 : {
390 19432101 : GEN A = cgetg(lx, t_COL);
391 : long i;
392 144445644 : for (i=1; i<lx; i++) gel(A,i) = gadd(gel(x,i), gel(y,i));
393 19431856 : return A;
394 : }
395 : GEN
396 16166082 : RgC_add(GEN x, GEN y) { return RgC_add_i(x, y, lg(x)); }
397 : GEN
398 2521465 : RgV_add(GEN x, GEN y)
399 10384543 : { pari_APPLY_type(t_VEC, gadd(gel(x,i), gel(y,i))) }
400 :
401 : static GEN
402 5995906 : RgC_sub_i(GEN x, GEN y, long lx)
403 : {
404 : long i;
405 5995906 : GEN A = cgetg(lx, t_COL);
406 635036903 : for (i=1; i<lx; i++) gel(A,i) = gsub(gel(x,i), gel(y,i));
407 5994721 : return A;
408 : }
409 : GEN
410 5095323 : RgC_sub(GEN x, GEN y) { return RgC_sub_i(x, y, lg(x)); }
411 : GEN
412 356260 : RgV_sub(GEN x, GEN y)
413 3020572 : { pari_APPLY_type(t_VEC, gsub(gel(x,i), gel(y,i))) }
414 :
415 : GEN
416 690732 : RgM_add(GEN x, GEN y)
417 : {
418 690732 : long lx = lg(x), l, j;
419 : GEN z;
420 690732 : if (lx == 1) return cgetg(1, t_MAT);
421 690732 : z = cgetg(lx, t_MAT); l = lgcols(x);
422 3956750 : for (j = 1; j < lx; j++) gel(z,j) = RgC_add_i(gel(x,j), gel(y,j), l);
423 690732 : return z;
424 : }
425 : GEN
426 172349 : RgM_sub(GEN x, GEN y)
427 : {
428 172349 : long lx = lg(x), l, j;
429 : GEN z;
430 172349 : if (lx == 1) return cgetg(1, t_MAT);
431 172349 : z = cgetg(lx, t_MAT); l = lgcols(x);
432 1072964 : for (j = 1; j < lx; j++) gel(z,j) = RgC_sub_i(gel(x,j), gel(y,j), l);
433 172350 : return z;
434 : }
435 :
436 : static GEN
437 3974467 : RgC_neg_i(GEN x, long lx)
438 : {
439 : long i;
440 3974467 : GEN y = cgetg(lx, t_COL);
441 30152972 : for (i=1; i<lx; i++) gel(y,i) = gneg(gel(x,i));
442 3974463 : return y;
443 : }
444 : GEN
445 990229 : RgC_neg(GEN x) { return RgC_neg_i(x, lg(x)); }
446 : GEN
447 4515 : RgV_neg(GEN x)
448 60473 : { pari_APPLY_type(t_VEC, gneg(gel(x,i))) }
449 : GEN
450 541274 : RgM_neg(GEN x)
451 : {
452 541274 : long i, hx, lx = lg(x);
453 541274 : GEN y = cgetg(lx, t_MAT);
454 541274 : if (lx == 1) return y;
455 541267 : hx = lgcols(x);
456 3525504 : for (i=1; i<lx; i++) gel(y,i) = RgC_neg_i(gel(x,i), hx);
457 541267 : return y;
458 : }
459 :
460 : GEN
461 4717187 : RgV_RgC_mul(GEN x, GEN y)
462 : {
463 4717187 : long lx = lg(x);
464 4717187 : if (lx != lg(y)) pari_err_OP("operation 'RgV_RgC_mul'", x, y);
465 4717103 : return RgV_dotproduct_i(x, y, lx);
466 : }
467 : GEN
468 1687 : RgC_RgV_mul(GEN x, GEN y)
469 : {
470 1687 : long i, ly = lg(y);
471 1687 : GEN z = cgetg(ly,t_MAT);
472 5061 : for (i=1; i<ly; i++) gel(z,i) = RgC_Rg_mul(x, gel(y,i));
473 1687 : return z;
474 : }
475 : GEN
476 0 : RgC_RgM_mul(GEN x, GEN y)
477 : {
478 0 : long i, ly = lg(y);
479 0 : GEN z = cgetg(ly,t_MAT);
480 0 : if (ly != 1 && lgcols(y) != 2) pari_err_OP("operation 'RgC_RgM_mul'",x,y);
481 0 : for (i=1; i<ly; i++) gel(z,i) = RgC_Rg_mul(x, gcoeff(y,1,i));
482 0 : return z;
483 : }
484 : GEN
485 0 : RgM_RgV_mul(GEN x, GEN y)
486 : {
487 0 : if (lg(x) != 2) pari_err_OP("operation 'RgM_RgV_mul'", x,y);
488 0 : return RgC_RgV_mul(gel(x,1), y);
489 : }
490 :
491 : /* x[i,]*y, l = lg(y) > 1 */
492 : static GEN
493 115762749 : RgMrow_RgC_mul_i(GEN x, GEN y, long i, long l)
494 : {
495 115762749 : pari_sp av = avma;
496 115762749 : GEN t = gmul(gcoeff(x,i,1), gel(y,1)); /* l > 1 ! */
497 : long j;
498 985195097 : for (j=2; j<l; j++)
499 : {
500 869435997 : GEN c = gcoeff(x,i,j);
501 869435997 : if (!isintzero(c)) t = gadd(t, gmul(c, gel(y,j)));
502 : }
503 115759100 : return gerepileupto(av,t);
504 : }
505 : GEN
506 4641 : RgMrow_RgC_mul(GEN x, GEN y, long i)
507 4641 : { return RgMrow_RgC_mul_i(x, y, i, lg(x)); }
508 :
509 : static GEN
510 28 : RgM_RgC_mul_FpM(GEN x, GEN y, GEN p)
511 : {
512 28 : pari_sp av = avma;
513 : GEN r;
514 28 : if (lgefint(p) == 3)
515 : {
516 14 : ulong pp = uel(p, 2);
517 14 : r = Flm_Flc_mul(RgM_to_Flm(x, pp), RgV_to_Flv(y, pp), pp);
518 14 : r = Flc_to_ZC_inplace(r);
519 : }
520 : else
521 14 : r = FpM_FpC_mul(RgM_to_FpM(x, p), RgC_to_FpC(y, p), p);
522 28 : return gerepileupto(av, FpC_to_mod(r, p));
523 : }
524 :
525 : static GEN
526 28 : RgM_RgC_mul_FqM(GEN x, GEN y, GEN pol, GEN p)
527 : {
528 28 : pari_sp av = avma;
529 28 : GEN b, T = RgX_to_FpX(pol, p);
530 28 : if (signe(T) == 0) pari_err_OP("*", x, y);
531 28 : b = FqM_FqC_mul(RgM_to_FqM(x, T, p), RgC_to_FqC(y, T, p), T, p);
532 28 : return gerepileupto(av, FqC_to_mod(b, T, p));
533 : }
534 :
535 : #define code(t1,t2) ((t1 << 6) | t2)
536 : static GEN
537 31178915 : RgM_RgC_mul_fast(GEN x, GEN y)
538 : {
539 : GEN p, pol;
540 : long pa;
541 31178915 : long t = RgM_RgC_type(x,y, &p,&pol,&pa);
542 31179187 : switch(t)
543 : {
544 8823484 : case t_INT: return ZM_ZC_mul(x,y);
545 142572 : case t_FRAC: return QM_QC_mul(x,y);
546 91 : case t_FFELT: return FFM_FFC_mul(x, y, pol);
547 28 : case t_INTMOD: return RgM_RgC_mul_FpM(x, y, p);
548 26 : case code(t_POLMOD, t_INTMOD):
549 26 : return RgM_RgC_mul_FqM(x, y, pol, p);
550 22212986 : default: return NULL;
551 : }
552 : }
553 : #undef code
554 :
555 : /* compatible t_MAT * t_COL, lx = lg(x) = lg(y) > 1, l = lgcols(x) */
556 : static GEN
557 33991527 : RgM_RgC_mul_i(GEN x, GEN y, long lx, long l)
558 : {
559 33991527 : GEN z = cgetg(l,t_COL);
560 : long i;
561 149744898 : for (i=1; i<l; i++) gel(z,i) = RgMrow_RgC_mul_i(x,y,i,lx);
562 33987355 : return z;
563 : }
564 :
565 : GEN
566 31178912 : RgM_RgC_mul(GEN x, GEN y)
567 : {
568 31178912 : long lx = lg(x);
569 : GEN z;
570 31178912 : if (lx != lg(y)) pari_err_OP("operation 'RgM_RgC_mul'", x,y);
571 31178916 : if (lx == 1) return cgetg(1,t_COL);
572 31178916 : z = RgM_RgC_mul_fast(x, y);
573 31179177 : if (z) return z;
574 22212974 : return RgM_RgC_mul_i(x, y, lx, lgcols(x));
575 : }
576 :
577 : GEN
578 295172 : RgV_RgM_mul(GEN x, GEN y)
579 : {
580 295172 : long i, lx, ly = lg(y);
581 : GEN z;
582 295172 : if (ly == 1) return cgetg(1,t_VEC);
583 295165 : lx = lg(x);
584 295165 : if (lx != lgcols(y)) pari_err_OP("operation 'RgV_RgM_mul'", x,y);
585 295158 : z = cgetg(ly, t_VEC);
586 3421476 : for (i=1; i<ly; i++) gel(z,i) = RgV_dotproduct_i(x, gel(y,i), lx);
587 295097 : return z;
588 : }
589 :
590 : static GEN
591 57148 : RgM_mul_FpM_i(GEN x, GEN y, GEN p)
592 : {
593 57148 : if (lgefint(p) == 3)
594 : {
595 57076 : ulong pp = uel(p, 2);
596 57076 : if (pp==2) return F2m_to_mod(F2m_mul(RgM_to_F2m(x), RgM_to_F2m(y)));
597 57027 : if (pp==3) return F3m_to_mod(F3m_mul(RgM_to_F3m(x), RgM_to_F3m(y)));
598 56873 : return Flm_to_mod(Flm_mul(RgM_to_Flm(x, pp), RgM_to_Flm(y, pp), pp), pp);
599 : }
600 72 : return FpM_to_mod(FpM_mul(RgM_to_FpM(x,p), RgM_to_FpM(y,p), p), p);
601 : }
602 : static GEN
603 57148 : RgM_mul_FpM(GEN x, GEN y, GEN p)
604 57148 : { pari_sp av = avma; return gerepileupto(av, RgM_mul_FpM_i(x, y, p)); }
605 :
606 : static GEN
607 26005 : RgM_mul_FqM(GEN x, GEN y, GEN pol, GEN p)
608 : {
609 26005 : pari_sp av = avma;
610 26005 : GEN b, T = RgX_to_FpX(pol, p);
611 26005 : if (signe(T) == 0) pari_err_OP("*", x, y);
612 26005 : b = FqM_mul(RgM_to_FqM(x, T, p), RgM_to_FqM(y, T, p), T, p);
613 26005 : return gerepileupto(av, FqM_to_mod(b, T, p));
614 : }
615 :
616 : static GEN
617 11956 : RgM_liftred(GEN x, GEN T)
618 11956 : { return RgXQM_red(liftpol_shallow(x), T); }
619 :
620 : static GEN
621 1442 : RgM_mul_ZXQM(GEN x, GEN y, GEN T)
622 : {
623 1442 : pari_sp av = avma;
624 1442 : GEN b = ZXQM_mul(RgM_liftred(x,T), RgM_liftred(y, T), T);
625 1442 : return gerepilecopy(av, QXQM_to_mod_shallow(b,T));
626 : }
627 :
628 : static GEN
629 133 : RgM_sqr_ZXQM(GEN x, GEN T)
630 : {
631 133 : pari_sp av = avma;
632 133 : GEN b = ZXQM_sqr(RgM_liftred(x, T), T);
633 133 : return gerepilecopy(av, QXQM_to_mod_shallow(b,T));
634 : }
635 :
636 : static GEN
637 4466 : RgM_mul_QXQM(GEN x, GEN y, GEN T)
638 : {
639 4466 : pari_sp av = avma;
640 4466 : GEN b = QXQM_mul(RgM_liftred(x, T), RgM_liftred(y, T), T);
641 4466 : return gerepilecopy(av, QXQM_to_mod_shallow(b,T));
642 : }
643 :
644 : static GEN
645 7 : RgM_sqr_QXQM(GEN x, GEN T)
646 : {
647 7 : pari_sp av = avma;
648 7 : GEN b = QXQM_sqr(RgM_liftred(x, T), T);
649 7 : return gerepilecopy(av, QXQM_to_mod_shallow(b,T));
650 : }
651 :
652 : INLINE int
653 4515 : RgX_is_monic_ZX(GEN pol)
654 4515 : { return RgX_is_ZX(pol) && ZX_is_monic(pol); }
655 :
656 : #define code(t1,t2) ((t1 << 6) | t2)
657 : static GEN
658 7568181 : RgM_mul_fast(GEN x, GEN y)
659 : {
660 : GEN p, pol;
661 : long pa;
662 7568181 : long t = RgM_type2(x,y, &p,&pol,&pa);
663 7568223 : switch(t)
664 : {
665 2689290 : case t_INT: return ZM_mul(x,y);
666 117117 : case t_FRAC: return QM_mul(x,y);
667 4403 : case t_FFELT: return FFM_mul(x, y, pol);
668 57085 : case t_INTMOD: return RgM_mul_FpM(x, y, p);
669 1449 : case code(t_POLMOD, t_INT):
670 1449 : return ZX_is_monic(pol)? RgM_mul_ZXQM(x, y, pol): NULL;
671 4487 : case code(t_POLMOD, t_FRAC):
672 4487 : return RgX_is_monic_ZX(pol)? RgM_mul_QXQM(x, y, pol): NULL;
673 26003 : case code(t_POLMOD, t_INTMOD):
674 26003 : return RgM_mul_FqM(x, y, pol, p);
675 4668389 : default: return NULL;
676 : }
677 : }
678 :
679 : static GEN
680 1316 : RgM_sqr_fast(GEN x)
681 : {
682 : GEN p, pol;
683 : long pa;
684 1316 : long t = RgM_type(x, &p,&pol,&pa);
685 1316 : switch(t)
686 : {
687 175 : case t_INT: return ZM_sqr(x);
688 700 : case t_FRAC: return QM_sqr(x);
689 112 : case t_FFELT: return FFM_mul(x, x, pol);
690 63 : case t_INTMOD: return RgM_mul_FpM(x, x, p);
691 140 : case code(t_POLMOD, t_INT):
692 140 : return ZX_is_monic(pol)? RgM_sqr_ZXQM(x, pol): NULL;
693 28 : case code(t_POLMOD, t_FRAC):
694 28 : return RgX_is_monic_ZX(pol)? RgM_sqr_QXQM(x, pol): NULL;
695 0 : case code(t_POLMOD, t_INTMOD):
696 0 : return RgM_mul_FqM(x, x, pol, p);
697 98 : default: return NULL;
698 : }
699 : }
700 :
701 : #undef code
702 :
703 : /* lx, ly > 1 */
704 : static GEN
705 4668415 : RgM_mul_i(GEN x, GEN y, long lx, long ly)
706 : {
707 4668415 : GEN z = cgetg(ly, t_MAT);
708 4668412 : long j, l = lgcols(x);
709 16446757 : for (j = 1; j < ly; j++) gel(z,j) = RgM_RgC_mul_i(x, gel(y,j), lx, l);
710 4668381 : return z;
711 : }
712 : GEN
713 7583962 : RgM_mul(GEN x, GEN y)
714 : {
715 7583962 : long lx, ly = lg(y);
716 : GEN z;
717 7583962 : if (ly == 1) return cgetg(1,t_MAT);
718 7568212 : lx = lg(x);
719 7568212 : if (lx != lgcols(y)) pari_err_OP("operation 'RgM_mul'", x,y);
720 7568211 : if (lx == 1) return zeromat(0,ly-1);
721 7568183 : z = RgM_mul_fast(x, y);
722 7568224 : if (z) return z;
723 4668417 : return RgM_mul_i(x, y, lx, ly);
724 : }
725 :
726 : GEN
727 1351 : RgM_sqr(GEN x)
728 : {
729 1351 : long j, lx = lg(x);
730 : GEN z;
731 1351 : if (lx == 1) return cgetg(1, t_MAT);
732 1316 : if (lx != lgcols(x)) pari_err_OP("operation 'RgM_mul'", x,x);
733 1316 : z = RgM_sqr_fast(x);
734 1316 : if (z) return z;
735 126 : z = cgetg(lx, t_MAT);
736 497 : for (j=1; j<lx; j++) gel(z,j) = RgM_RgC_mul_i(x, gel(x,j), lx, lx);
737 126 : return z;
738 : }
739 :
740 : /* assume result is symmetric */
741 : GEN
742 0 : RgM_multosym(GEN x, GEN y)
743 : {
744 0 : long j, lx, ly = lg(y);
745 : GEN M;
746 0 : if (ly == 1) return cgetg(1,t_MAT);
747 0 : lx = lg(x);
748 0 : if (lx != lgcols(y)) pari_err_OP("operation 'RgM_multosym'", x,y);
749 0 : if (lx == 1) return cgetg(1,t_MAT);
750 0 : if (ly != lgcols(x)) pari_err_OP("operation 'RgM_multosym'", x,y);
751 0 : M = cgetg(ly, t_MAT);
752 0 : for (j=1; j<ly; j++)
753 : {
754 0 : GEN z = cgetg(ly,t_COL), yj = gel(y,j);
755 : long i;
756 0 : for (i=1; i<j; i++) gel(z,i) = gcoeff(M,j,i);
757 0 : for (i=j; i<ly; i++)gel(z,i) = RgMrow_RgC_mul_i(x,yj,i,lx);
758 0 : gel(M,j) = z;
759 : }
760 0 : return M;
761 : }
762 : /* x~ * y, assuming result is symmetric */
763 : GEN
764 7663 : RgM_transmultosym(GEN x, GEN y)
765 : {
766 7663 : long i, j, l, ly = lg(y);
767 : GEN M;
768 7663 : if (ly == 1) return cgetg(1,t_MAT);
769 7663 : if (lg(x) != ly) pari_err_OP("operation 'RgM_transmultosym'", x,y);
770 7663 : l = lgcols(y);
771 7663 : if (lgcols(x) != l) pari_err_OP("operation 'RgM_transmultosym'", x,y);
772 7663 : M = cgetg(ly, t_MAT);
773 30820 : for (i=1; i<ly; i++)
774 : {
775 23157 : GEN xi = gel(x,i), c = cgetg(ly,t_COL);
776 23157 : gel(M,i) = c;
777 47490 : for (j=1; j<i; j++)
778 24333 : gcoeff(M,i,j) = gel(c,j) = RgV_dotproduct_i(xi,gel(y,j),l);
779 23157 : gel(c,i) = RgV_dotproduct_i(xi,gel(y,i),l);
780 : }
781 7663 : return M;
782 : }
783 : /* x~ * y */
784 : GEN
785 0 : RgM_transmul(GEN x, GEN y)
786 : {
787 0 : long i, j, l, lx, ly = lg(y);
788 : GEN M;
789 0 : if (ly == 1) return cgetg(1,t_MAT);
790 0 : lx = lg(x);
791 0 : l = lgcols(y);
792 0 : if (lgcols(x) != l) pari_err_OP("operation 'RgM_transmul'", x,y);
793 0 : M = cgetg(ly, t_MAT);
794 0 : for (i=1; i<ly; i++)
795 : {
796 0 : GEN yi = gel(y,i), c = cgetg(lx,t_COL);
797 0 : gel(M,i) = c;
798 0 : for (j=1; j<lx; j++) gel(c,j) = RgV_dotproduct_i(yi,gel(x,j),l);
799 : }
800 0 : return M;
801 : }
802 :
803 : GEN
804 4691373 : gram_matrix(GEN x)
805 : {
806 4691373 : long i,j, l, lx = lg(x);
807 : GEN M;
808 4691373 : if (!is_matvec_t(typ(x))) pari_err_TYPE("gram",x);
809 4691372 : if (lx == 1) return cgetg(1,t_MAT);
810 4691358 : l = lgcols(x);
811 4691357 : M = cgetg(lx,t_MAT);
812 14073997 : for (i=1; i<lx; i++)
813 : {
814 9382657 : GEN xi = gel(x,i), c = cgetg(lx,t_COL);
815 9382656 : gel(M,i) = c;
816 14073974 : for (j=1; j<i; j++)
817 4691326 : gcoeff(M,i,j) = gel(c,j) = RgV_dotproduct_i(xi,gel(x,j),l);
818 9382648 : gel(c,i) = RgV_dotsquare(xi);
819 : }
820 4691340 : return M;
821 : }
822 :
823 : static GEN
824 3801 : _RgM_add(void *E, GEN x, GEN y) { (void)E; return RgM_add(x, y); }
825 :
826 : static GEN
827 0 : _RgM_sub(void *E, GEN x, GEN y) { (void)E; return RgM_sub(x, y); }
828 :
829 : static GEN
830 5684 : _RgM_cmul(void *E, GEN P, long a, GEN x) { (void)E; return RgM_Rg_mul(x,gel(P,a+2)); }
831 :
832 : static GEN
833 238 : _RgM_sqr(void *E, GEN x) { (void) E; return RgM_sqr(x); }
834 :
835 : static GEN
836 749 : _RgM_mul(void *E, GEN x, GEN y) { (void) E; return RgM_mul(x, y); }
837 :
838 : static GEN
839 4046 : _RgM_one(void *E) { long *n = (long*) E; return matid(*n); }
840 :
841 : static GEN
842 0 : _RgM_zero(void *E) { long *n = (long*) E; return zeromat(*n,*n); }
843 :
844 : static GEN
845 2828 : _RgM_red(void *E, GEN x) { (void)E; return x; }
846 :
847 : static struct bb_algebra RgM_algebra = { _RgM_red, _RgM_add, _RgM_sub,
848 : _RgM_mul, _RgM_sqr, _RgM_one, _RgM_zero };
849 :
850 : /* generates the list of powers of x of degree 0,1,2,...,l*/
851 : GEN
852 168 : RgM_powers(GEN x, long l)
853 : {
854 168 : long n = lg(x)-1;
855 168 : return gen_powers(x,l,1,(void *) &n, &_RgM_sqr, &_RgM_mul, &_RgM_one);
856 : }
857 :
858 : GEN
859 490 : RgX_RgMV_eval(GEN Q, GEN x)
860 : {
861 490 : long n = lg(x)>1 ? lg(gel(x,1))-1:0;
862 490 : return gen_bkeval_powers(Q,degpol(Q),x,(void*)&n,&RgM_algebra,&_RgM_cmul);
863 : }
864 :
865 : GEN
866 1393 : RgX_RgM_eval(GEN Q, GEN x)
867 : {
868 1393 : long n = lg(x)-1;
869 1393 : return gen_bkeval(Q,degpol(Q),x,1,(void*)&n,&RgM_algebra,&_RgM_cmul);
870 : }
871 :
872 : GEN
873 4455931 : RgC_Rg_div(GEN x, GEN y)
874 19188214 : { pari_APPLY_type(t_COL, gdiv(gel(x,i),y)) }
875 :
876 : GEN
877 13153535 : RgC_Rg_mul(GEN x, GEN y)
878 79214232 : { pari_APPLY_type(t_COL, gmul(gel(x,i),y)) }
879 :
880 : GEN
881 30954 : RgV_Rg_mul(GEN x, GEN y)
882 1172220 : { pari_APPLY_type(t_VEC, gmul(gel(x,i),y)) }
883 :
884 : GEN
885 608985 : RgM_Rg_div(GEN X, GEN c) {
886 608985 : long i, j, h, l = lg(X);
887 608985 : GEN A = cgetg(l, t_MAT);
888 608983 : if (l == 1) return A;
889 608983 : h = lgcols(X);
890 2789321 : for (j=1; j<l; j++)
891 : {
892 2180354 : GEN a = cgetg(h, t_COL), x = gel(X, j);
893 17262237 : for (i = 1; i < h; i++) gel(a,i) = gdiv(gel(x,i), c);
894 2180337 : gel(A,j) = a;
895 : }
896 608967 : return A;
897 : }
898 : GEN
899 247151 : RgM_Rg_mul(GEN X, GEN c) {
900 247151 : long i, j, h, l = lg(X);
901 247151 : GEN A = cgetg(l, t_MAT);
902 247150 : if (l == 1) return A;
903 247150 : h = lgcols(X);
904 1086831 : for (j=1; j<l; j++)
905 : {
906 839702 : GEN a = cgetg(h, t_COL), x = gel(X, j);
907 7062918 : for (i = 1; i < h; i++) gel(a,i) = gmul(gel(x,i), c);
908 839677 : gel(A,j) = a;
909 : }
910 247129 : return A;
911 : }
912 :
913 : /********************************************************************/
914 : /* */
915 : /* SCALAR TO MATRIX/VECTOR */
916 : /* */
917 : /********************************************************************/
918 : /* fill the square nxn matrix equal to t*Id */
919 : static void
920 13397241 : fill_scalmat(GEN y, GEN t, long n)
921 : {
922 : long i;
923 51025998 : for (i = 1; i <= n; i++)
924 : {
925 37629061 : gel(y,i) = zerocol(n);
926 37628757 : gcoeff(y,i,i) = t;
927 : }
928 13396937 : }
929 :
930 : GEN
931 928190 : scalarmat(GEN x, long n) {
932 928190 : GEN y = cgetg(n+1, t_MAT);
933 928158 : if (!n) return y;
934 928158 : fill_scalmat(y, gcopy(x), n); return y;
935 : }
936 : GEN
937 3154437 : scalarmat_shallow(GEN x, long n) {
938 3154437 : GEN y = cgetg(n+1, t_MAT);
939 3154474 : fill_scalmat(y, x, n); return y;
940 : }
941 : GEN
942 217 : scalarmat_s(long x, long n) {
943 217 : GEN y = cgetg(n+1, t_MAT);
944 217 : if (!n) return y;
945 217 : fill_scalmat(y, stoi(x), n); return y;
946 : }
947 : GEN
948 9314921 : matid(long n) {
949 : GEN y;
950 9314921 : if (n < 0) pari_err_DOMAIN("matid", "size", "<", gen_0, stoi(n));
951 9314914 : y = cgetg(n+1, t_MAT);
952 9315036 : fill_scalmat(y, gen_1, n); return y;
953 : }
954 :
955 : INLINE GEN
956 2253680 : scalarcol_i(GEN x, long n, long c)
957 : {
958 : long i;
959 2253680 : GEN y = cgetg(n+1,t_COL);
960 2253679 : if (!n) return y;
961 2253679 : gel(y,1) = c? gcopy(x): x;
962 6729171 : for (i=2; i<=n; i++) gel(y,i) = gen_0;
963 2253682 : return y;
964 : }
965 :
966 : GEN
967 772236 : scalarcol(GEN x, long n) { return scalarcol_i(x,n,1); }
968 :
969 : GEN
970 1481445 : scalarcol_shallow(GEN x, long n) { return scalarcol_i(x,n,0); }
971 :
972 : int
973 33077 : RgM_isscalar(GEN x, GEN s)
974 : {
975 33077 : long i, j, lx = lg(x);
976 :
977 33077 : if (lx == 1) return 1;
978 33077 : if (lx != lgcols(x)) return 0;
979 33077 : if (!s) s = gcoeff(x,1,1);
980 :
981 91621 : for (j=1; j<lx; j++)
982 : {
983 74495 : GEN c = gel(x,j);
984 201501 : for (i=1; i<j; )
985 140395 : if (!gequal0(gel(c,i++))) return 0;
986 : /* i = j */
987 61106 : if (!gequal(gel(c,i++),s)) return 0;
988 224451 : for ( ; i<lx; )
989 165907 : if (!gequal0(gel(c,i++))) return 0;
990 : }
991 17126 : return 1;
992 : }
993 :
994 : int
995 15322 : RgM_isidentity(GEN x)
996 : {
997 15322 : long i,j, lx = lg(x);
998 :
999 15322 : if (lx == 1) return 1;
1000 15322 : if (lx != lgcols(x)) return 0;
1001 25172 : for (j=1; j<lx; j++)
1002 : {
1003 24976 : GEN c = gel(x,j);
1004 58246 : for (i=1; i<j; )
1005 38225 : if (!gequal0(gel(c,i++))) return 0;
1006 : /* i = j */
1007 20021 : if (!gequal1(gel(c,i++))) return 0;
1008 61007 : for ( ; i<lx; )
1009 51157 : if (!gequal0(gel(c,i++))) return 0;
1010 : }
1011 196 : return 1;
1012 : }
1013 :
1014 : long
1015 434 : RgC_is_ei(GEN x)
1016 : {
1017 434 : long i, j = 0, l = lg(x);
1018 2422 : for (i = 1; i < l; i++)
1019 : {
1020 1988 : GEN c = gel(x,i);
1021 1988 : if (gequal0(c)) continue;
1022 434 : if (!gequal1(c) || j) return 0;
1023 434 : j = i;
1024 : }
1025 434 : return j;
1026 : }
1027 :
1028 : int
1029 336 : RgM_isdiagonal(GEN x)
1030 : {
1031 336 : long i,j, lx = lg(x);
1032 336 : if (lx == 1) return 1;
1033 336 : if (lx != lgcols(x)) return 0;
1034 :
1035 3220 : for (j=1; j<lx; j++)
1036 : {
1037 2891 : GEN c = gel(x,j);
1038 18452 : for (i=1; i<j; i++)
1039 15561 : if (!gequal0(gel(c,i))) return 0;
1040 18452 : for (i++; i<lx; i++)
1041 15568 : if (!gequal0(gel(c,i))) return 0;
1042 : }
1043 329 : return 1;
1044 : }
1045 : int
1046 315 : isdiagonal(GEN x) { return (typ(x)==t_MAT) && RgM_isdiagonal(x); }
1047 :
1048 : GEN
1049 21337 : RgM_det_triangular(GEN mat)
1050 : {
1051 21337 : long i,l = lg(mat);
1052 : pari_sp av;
1053 : GEN s;
1054 :
1055 21337 : if (l<3) return l<2? gen_1: gcopy(gcoeff(mat,1,1));
1056 19762 : av = avma; s = gcoeff(mat,1,1);
1057 119922 : for (i=2; i<l; i++) s = gmul(s,gcoeff(mat,i,i));
1058 19762 : return av==avma? gcopy(s): gerepileupto(av,s);
1059 : }
1060 :
1061 : GEN
1062 478033 : RgV_kill0(GEN v)
1063 : {
1064 : long i, l;
1065 478033 : GEN w = cgetg_copy(v, &l);
1066 129995377 : for (i = 1; i < l; i++)
1067 : {
1068 129518257 : GEN a = gel(v,i);
1069 129518257 : gel(w,i) = gequal0(a) ? NULL: a;
1070 : }
1071 477120 : return w;
1072 : }
|