Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Testing latest pari + WASM + node.js... and it works?! Wow.

28485 views
License: GPL3
ubuntu2004
1
/* Copyright (C) 2012 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
/** LINEAR ALGEBRA **/
18
/** (third part) **/
19
/** **/
20
/********************************************************************/
21
#include "pari.h"
22
#include "paripriv.h"
23
24
#define DEBUGLEVEL DEBUGLEVEL_mat
25
26
/*******************************************************************/
27
/* */
28
/* SUM */
29
/* */
30
/*******************************************************************/
31
32
GEN
33
vecsum(GEN v)
34
{
35
pari_sp av = avma;
36
long i, l;
37
GEN p;
38
if (!is_vec_t(typ(v)))
39
pari_err_TYPE("vecsum", v);
40
l = lg(v);
41
if (l == 1) return gen_0;
42
p = gel(v,1);
43
if (l == 2) return gcopy(p);
44
for (i=2; i<l; i++)
45
{
46
p = gadd(p, gel(v,i));
47
if (gc_needed(av, 2))
48
{
49
if (DEBUGMEM>1) pari_warn(warnmem,"sum");
50
p = gerepileupto(av, p);
51
}
52
}
53
return gerepileupto(av, p);
54
}
55
56
/*******************************************************************/
57
/* */
58
/* TRANSPOSE */
59
/* */
60
/*******************************************************************/
61
/* A[x0,]~ */
62
static GEN
63
row_transpose(GEN A, long x0)
64
{
65
long i, lB = lg(A);
66
GEN B = cgetg(lB, t_COL);
67
for (i=1; i<lB; i++) gel(B, i) = gcoeff(A, x0, i);
68
return B;
69
}
70
static GEN
71
row_transposecopy(GEN A, long x0)
72
{
73
long i, lB = lg(A);
74
GEN B = cgetg(lB, t_COL);
75
for (i=1; i<lB; i++) gel(B, i) = gcopy(gcoeff(A, x0, i));
76
return B;
77
}
78
79
/* No copy*/
80
GEN
81
shallowtrans(GEN x)
82
{
83
long i, dx, lx;
84
GEN y;
85
switch(typ(x))
86
{
87
case t_VEC: y = leafcopy(x); settyp(y,t_COL); break;
88
case t_COL: y = leafcopy(x); settyp(y,t_VEC); break;
89
case t_MAT:
90
lx = lg(x); if (lx==1) return cgetg(1,t_MAT);
91
dx = lgcols(x); y = cgetg(dx,t_MAT);
92
for (i = 1; i < dx; i++) gel(y,i) = row_transpose(x,i);
93
break;
94
default: pari_err_TYPE("shallowtrans",x);
95
return NULL;/*LCOV_EXCL_LINE*/
96
}
97
return y;
98
}
99
100
GEN
101
gtrans(GEN x)
102
{
103
long i, dx, lx;
104
GEN y;
105
switch(typ(x))
106
{
107
case t_VEC: y = gcopy(x); settyp(y,t_COL); break;
108
case t_COL: y = gcopy(x); settyp(y,t_VEC); break;
109
case t_MAT:
110
lx = lg(x); if (lx==1) return cgetg(1,t_MAT);
111
dx = lgcols(x); y = cgetg(dx,t_MAT);
112
for (i = 1; i < dx; i++) gel(y,i) = row_transposecopy(x,i);
113
break;
114
default: pari_err_TYPE("gtrans",x);
115
return NULL;/*LCOV_EXCL_LINE*/
116
}
117
return y;
118
}
119
120
/*******************************************************************/
121
/* */
122
/* EXTRACTION */
123
/* */
124
/*******************************************************************/
125
126
static long
127
str_to_long(char *s, char **pt)
128
{
129
long a = atol(s);
130
while (isspace((int)*s)) s++;
131
if (*s == '-' || *s == '+') s++;
132
while (isdigit((int)*s) || isspace((int)*s)) s++;
133
*pt = s; return a;
134
}
135
136
static int
137
get_range(char *s, long *a, long *b, long *cmpl, long lx)
138
{
139
long max = lx - 1;
140
141
*a = 1; *b = max;
142
if (*s == '^') { *cmpl = 1; s++; } else *cmpl = 0;
143
if (!*s) return 0;
144
if (*s != '.')
145
{
146
*a = str_to_long(s, &s);
147
if (*a < 0) *a += lx;
148
if (*a<1 || *a>max) return 0;
149
}
150
if (*s == '.')
151
{
152
s++; if (*s != '.') return 0;
153
do s++; while (isspace((int)*s));
154
if (*s)
155
{
156
*b = str_to_long(s, &s);
157
if (*b < 0) *b += lx;
158
if (*b<1 || *b>max || *s) return 0;
159
}
160
return 1;
161
}
162
if (*s) return 0;
163
*b = *a; return 1;
164
}
165
166
static int
167
extract_selector_ok(long lx, GEN L)
168
{
169
long i, l;
170
switch (typ(L))
171
{
172
case t_INT: {
173
long maxj;
174
if (!signe(L)) return 1;
175
l = lgefint(L)-1;
176
maxj = BITS_IN_LONG - bfffo(*int_MSW(L));
177
return ((l-2) * BITS_IN_LONG + maxj < lx);
178
}
179
case t_STR: {
180
long first, last, cmpl;
181
return get_range(GSTR(L), &first, &last, &cmpl, lx);
182
}
183
case t_VEC: case t_COL:
184
l = lg(L);
185
for (i=1; i<l; i++)
186
{
187
long j = itos(gel(L,i));
188
if (j>=lx || j<=0) return 0;
189
}
190
return 1;
191
case t_VECSMALL:
192
l = lg(L);
193
for (i=1; i<l; i++)
194
{
195
long j = L[i];
196
if (j>=lx || j<=0) return 0;
197
}
198
return 1;
199
}
200
return 0;
201
}
202
203
GEN
204
shallowmatextract(GEN x, GEN l1, GEN l2)
205
{
206
long i, j, n1 = lg(l1), n2 = lg(l2);
207
GEN M = cgetg(n2, t_MAT);
208
for(i=1; i < n2; i++)
209
{
210
long ii = l2[i];
211
GEN C = cgetg(n1, t_COL);
212
for (j=1; j < n1; j++)
213
{
214
long jj = l1[j];
215
gel(C, j) = gmael(x, ii, jj);
216
}
217
gel(M, i) = C;
218
}
219
return M;
220
}
221
222
GEN
223
shallowextract(GEN x, GEN L)
224
{
225
long i,j, tl = typ(L), tx = typ(x), lx = lg(x);
226
GEN y;
227
228
switch(tx)
229
{
230
case t_VEC:
231
case t_COL:
232
case t_MAT:
233
case t_VECSMALL: break;
234
default: pari_err_TYPE("extract",x);
235
236
}
237
if (tl==t_INT)
238
{ /* extract components of x as per the bits of mask L */
239
long k, l, ix, iy, maxj;
240
GEN Ld;
241
if (!signe(L)) return cgetg(1,tx);
242
y = new_chunk(lx);
243
l = lgefint(L)-1; ix = iy = 1;
244
maxj = BITS_IN_LONG - bfffo(*int_MSW(L));
245
if ((l-2) * BITS_IN_LONG + maxj >= lx)
246
pari_err_TYPE("vecextract [mask too large]", L);
247
for (k = 2, Ld = int_LSW(L); k < l; k++, Ld = int_nextW(Ld))
248
{
249
ulong B = *Ld;
250
for (j = 0; j < BITS_IN_LONG; j++, B >>= 1, ix++)
251
if (B & 1) y[iy++] = x[ix];
252
}
253
{ /* k = l */
254
ulong B = *Ld;
255
for (j = 0; j < maxj; j++, B >>= 1, ix++)
256
if (B & 1) y[iy++] = x[ix];
257
}
258
y[0] = evaltyp(tx) | evallg(iy);
259
return y;
260
}
261
if (tl==t_STR)
262
{
263
char *s = GSTR(L);
264
long first, last, cmpl, d;
265
if (! get_range(s, &first, &last, &cmpl, lx))
266
pari_err_TYPE("vecextract [incorrect range]", L);
267
if (lx == 1) return cgetg(1,tx);
268
d = last - first;
269
if (cmpl)
270
{
271
if (d >= 0)
272
{
273
y = cgetg(lx - (1+d),tx);
274
for (j=1; j<first; j++) gel(y,j) = gel(x,j);
275
for (i=last+1; i<lx; i++,j++) gel(y,j) = gel(x,i);
276
}
277
else
278
{
279
y = cgetg(lx - (1-d),tx);
280
for (j=1,i=lx-1; i>first; i--,j++) gel(y,j) = gel(x,i);
281
for (i=last-1; i>0; i--,j++) gel(y,j) = gel(x,i);
282
}
283
}
284
else
285
{
286
if (d >= 0)
287
{
288
y = cgetg(d+2,tx);
289
for (i=first,j=1; i<=last; i++,j++) gel(y,j) = gel(x,i);
290
}
291
else
292
{
293
y = cgetg(2-d,tx);
294
for (i=first,j=1; i>=last; i--,j++) gel(y,j) = gel(x,i);
295
}
296
}
297
return y;
298
}
299
300
if (is_vec_t(tl))
301
{
302
long ll=lg(L); y=cgetg(ll,tx);
303
for (i=1; i<ll; i++)
304
{
305
j = itos(gel(L,i));
306
if (j<=0) pari_err_COMPONENT("vecextract","<=",gen_0,stoi(j));
307
if (j>=lx) pari_err_COMPONENT("vecextract",">=",stoi(lx),stoi(j));
308
gel(y,i) = gel(x,j);
309
}
310
return y;
311
}
312
if (tl == t_VECSMALL)
313
{
314
long ll=lg(L); y=cgetg(ll,tx);
315
for (i=1; i<ll; i++)
316
{
317
j = L[i];
318
if (j<=0) pari_err_COMPONENT("vecextract","<=",gen_0,stoi(j));
319
if (j>=lx) pari_err_COMPONENT("vecextract",">=",stoi(lx),stoi(j));
320
gel(y,i) = gel(x,j);
321
}
322
return y;
323
}
324
pari_err_TYPE("vecextract [mask]", L);
325
return NULL; /* LCOV_EXCL_LINE */
326
}
327
328
/* does the component selector l select 0 component ? */
329
static int
330
select_0(GEN l)
331
{
332
switch(typ(l))
333
{
334
case t_INT:
335
return (!signe(l));
336
case t_VEC: case t_COL: case t_VECSMALL:
337
return (lg(l) == 1);
338
}
339
return 0;
340
}
341
342
GEN
343
extract0(GEN x, GEN l1, GEN l2)
344
{
345
pari_sp av = avma, av2;
346
GEN y;
347
if (! l2)
348
{
349
y = shallowextract(x, l1);
350
if (lg(y) == 1 || typ(y) == t_VECSMALL) return y;
351
av2 = avma;
352
y = gcopy(y);
353
}
354
else
355
{
356
if (typ(x) != t_MAT) pari_err_TYPE("extract",x);
357
y = shallowextract(x,l2);
358
if (select_0(l1)) { set_avma(av); return zeromat(0, lg(y)-1); }
359
if (lg(y) == 1 && lg(x) > 1)
360
{
361
if (!extract_selector_ok(lgcols(x), l1))
362
pari_err_TYPE("vecextract [incorrect mask]", l1);
363
set_avma(av); return cgetg(1, t_MAT);
364
}
365
y = shallowextract(shallowtrans(y), l1);
366
av2 = avma;
367
y = gtrans(y);
368
}
369
stackdummy(av, av2);
370
return y;
371
}
372
373
static long
374
vecslice_parse_arg(long lA, long *y1, long *y2, long *skip)
375
{
376
*skip=0;
377
if (*y1==LONG_MAX)
378
{
379
if (*y2!=LONG_MAX)
380
{
381
if (*y2<0) *y2 += lA;
382
if (*y2<0 || *y2==LONG_MAX || *y2>=lA)
383
pari_err_DIM("_[..]");
384
*skip=*y2;
385
}
386
*y1 = 1; *y2 = lA-1;
387
}
388
else if (*y2==LONG_MAX) *y2 = *y1;
389
if (*y1<=0) *y1 += lA;
390
if (*y2<0) *y2 += lA;
391
if (*y1<=0 || *y1>*y2+1 || *y2>=lA) pari_err_DIM("_[..]");
392
return *y2 - *y1 + 2 - !!*skip;
393
}
394
395
static GEN
396
vecslice_i(GEN A, long t, long lB, long y1, long skip)
397
{
398
GEN B = cgetg(lB, t);
399
long i;
400
for (i=1; i<lB; i++, y1++)
401
{
402
if (y1 == skip) { i--; continue; }
403
gel(B,i) = gcopy(gel(A,y1));
404
}
405
return B;
406
}
407
408
static GEN
409
rowslice_i(GEN A, long lB, long x1, long y1, long skip)
410
{
411
GEN B = cgetg(lB, t_VEC);
412
long i;
413
for (i=1; i<lB; i++, y1++)
414
{
415
if (y1 == skip) { i--; continue; }
416
gel(B,i) = gcopy(gcoeff(A,x1,y1));
417
}
418
return B;
419
}
420
421
static GEN
422
rowsmallslice_i(GEN A, long lB, long x1, long y1, long skip)
423
{
424
GEN B = cgetg(lB, t_VECSMALL);
425
long i;
426
for (i=1; i<lB; i++, y1++)
427
{
428
if (y1 == skip) { i--; continue; }
429
B[i] = coeff(A,x1,y1);
430
}
431
return B;
432
}
433
434
static GEN
435
vecsmallslice_i(GEN A, long t, long lB, long y1, long skip)
436
{
437
GEN B = cgetg(lB, t);
438
long i;
439
for (i=1; i<lB; i++, y1++)
440
{
441
if (y1 == skip) { i--; continue; }
442
B[i] = A[y1];
443
}
444
return B;
445
}
446
GEN
447
vecslice0(GEN A, long y1, long y2)
448
{
449
long skip, lB, t = typ(A);
450
switch(t)
451
{
452
case t_VEC: case t_COL:
453
lB = vecslice_parse_arg(lg(A), &y1, &y2, &skip);
454
return vecslice_i(A, t,lB,y1,skip);
455
case t_VECSMALL:
456
lB = vecslice_parse_arg(lg(A), &y1, &y2, &skip);
457
return vecsmallslice_i(A, t,lB,y1,skip);
458
case t_LIST:
459
if (list_typ(A) == t_LIST_RAW)
460
{
461
GEN y, z = list_data(A);
462
long l = z? lg(z): 1;
463
lB = vecslice_parse_arg(l, &y1, &y2, &skip);
464
y = mklist(); if (!z) return y;
465
list_data(y) = vecslice_i(z, t_VEC,lB,y1,skip);
466
return y;
467
}
468
default:
469
pari_err_TYPE("_[_.._]",A);
470
return NULL;/*LCOV_EXCL_LINE*/
471
}
472
}
473
474
GEN
475
matslice0(GEN A, long x1, long x2, long y1, long y2)
476
{
477
GEN B;
478
long i, lB, lA = lg(A), rA, t, skip, rskip, rlB;
479
long is_col = y1!=LONG_MAX && y2==LONG_MAX;
480
long is_row = x1!=LONG_MAX && x2==LONG_MAX;
481
GEN (*slice)(GEN A, long t, long lB, long y1, long skip);
482
if (typ(A)!=t_MAT) pari_err_TYPE("_[_.._,_.._]",A);
483
lB = vecslice_parse_arg(lA, &y1, &y2, &skip);
484
if (is_col) return vecslice0(gel(A, y1), x1, x2);
485
rA = lg(A)==1 ? 1: lgcols(A);
486
rlB = vecslice_parse_arg(rA, &x1, &x2, &rskip);
487
t = lg(A)==1 ? t_COL: typ(gel(A,1));
488
if (is_row) return t == t_COL ? rowslice_i(A, lB, x1, y1, skip):
489
rowsmallslice_i(A, lB, x1, y1, skip);
490
slice = t == t_COL? &vecslice_i: &vecsmallslice_i;
491
492
B = cgetg(lB, t_MAT);
493
for (i=1; i<lB; i++, y1++)
494
{
495
if (y1 == skip) { i--; continue; }
496
gel(B,i) = slice(gel(A,y1),t,rlB, x1, rskip);
497
}
498
return B;
499
}
500
501
GEN
502
vecrange(GEN a, GEN b)
503
{
504
GEN y;
505
long i, l;
506
if (typ(a)!=t_INT) pari_err_TYPE("[_.._]",a);
507
if (typ(b)!=t_INT) pari_err_TYPE("[_.._]",b);
508
if (cmpii(a,b)>0) return cgetg(1,t_VEC);
509
l = itos(subii(b,a))+1;
510
a = setloop(a);
511
y = cgetg(l+1, t_VEC);
512
for (i=1; i<=l; a = incloop(a), i++) gel(y,i) = icopy(a);
513
return y;
514
}
515
516
GEN
517
vecrangess(long a, long b)
518
{
519
GEN y;
520
long i, l;
521
if (a>b) return cgetg(1,t_VEC);
522
l = b-a+1;
523
y = cgetg(l+1, t_VEC);
524
for (i=1; i<=l; a++, i++) gel(y,i) = stoi(a);
525
return y;
526
}
527
528
GEN
529
genindexselect(void *E, long (*f)(void* E, GEN x), GEN A)
530
{
531
long l, i, lv;
532
GEN v, z;
533
pari_sp av;
534
clone_lock(A);
535
switch(typ(A))
536
{
537
case t_LIST:
538
z = list_data(A);
539
l = z? lg(z): 1;
540
break;
541
case t_VEC: case t_COL: case t_MAT:
542
l = lg(A);
543
z = A;
544
break;
545
default:
546
pari_err_TYPE("select",A);
547
return NULL;/*LCOV_EXCL_LINE*/
548
}
549
v = cgetg(l, t_VECSMALL);
550
av = avma;
551
for (i = lv = 1; i < l; i++) {
552
if (f(E, gel(z,i))) v[lv++] = i;
553
set_avma(av);
554
}
555
clone_unlock_deep(A); fixlg(v, lv); return v;
556
}
557
static GEN
558
extract_copy(GEN A, GEN v)
559
{
560
long i, l = lg(v);
561
GEN B = cgetg(l, typ(A));
562
for (i = 1; i < l; i++) gel(B,i) = gcopy(gel(A,v[i]));
563
return B;
564
}
565
/* as genselect, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */
566
GEN
567
vecselect(void *E, long (*f)(void* E, GEN x), GEN A)
568
{
569
GEN v;
570
clone_lock(A);
571
v = genindexselect(E, f, A);
572
A = extract_copy(A, v); settyp(A, t_VEC);
573
clone_unlock_deep(A); return A;
574
}
575
GEN
576
genselect(void *E, long (*f)(void* E, GEN x), GEN A)
577
{
578
GEN y, z, v;/* v left on stack for efficiency */
579
clone_lock(A);
580
switch(typ(A))
581
{
582
case t_LIST:
583
z = list_data(A);
584
if (!z) y = mklist();
585
else
586
{
587
GEN B;
588
y = cgetg(3, t_LIST);
589
v = genindexselect(E, f, z);
590
B = extract_copy(z, v);
591
y[1] = lg(B)-1;
592
list_data(y) = B;
593
}
594
break;
595
case t_VEC: case t_COL: case t_MAT:
596
v = genindexselect(E, f, A);
597
y = extract_copy(A, v);
598
break;
599
default:
600
pari_err_TYPE("select",A);
601
return NULL;/*LCOV_EXCL_LINE*/
602
}
603
clone_unlock_deep(A); return y;
604
}
605
606
static void
607
check_callgen1(GEN f, const char *s)
608
{
609
if (typ(f) != t_CLOSURE || closure_is_variadic(f) || closure_arity(f) < 1)
610
pari_err_TYPE(s, f);
611
}
612
613
GEN
614
select0(GEN f, GEN x, long flag)
615
{
616
check_callgen1(f, "select");
617
switch(flag)
618
{
619
case 0: return genselect((void *) f, gp_callbool, x);
620
case 1: return genindexselect((void *) f, gp_callbool, x);
621
default: pari_err_FLAG("select");
622
return NULL;/*LCOV_EXCL_LINE*/
623
}
624
}
625
626
GEN
627
parselect_worker(GEN d, GEN C)
628
{
629
return gequal0(closure_callgen1(C, d))? gen_0: gen_1;
630
}
631
632
GEN
633
parselect(GEN C, GEN D, long flag)
634
{
635
pari_sp av;
636
long lv, l = lg(D), i;
637
GEN V, W, worker;
638
check_callgen1(C, "parselect");
639
if (!is_vec_t(typ(D))) pari_err_TYPE("parselect",D);
640
W = cgetg(l, t_VECSMALL); av = avma;
641
worker = snm_closure(is_entry("_parselect_worker"), mkvec(C));
642
V = gen_parapply(worker, D);
643
for (lv=1, i=1; i<l; i++)
644
if (signe(gel(V,i))) W[lv++] = i;
645
fixlg(W, lv);
646
set_avma(av);
647
return flag? W: extract_copy(D, W);
648
}
649
650
GEN
651
veccatapply(void *E, GEN (*f)(void* E, GEN x), GEN x)
652
{
653
pari_sp av = avma;
654
GEN v = vecapply(E, f, x);
655
return lg(v) == 1? v: gerepilecopy(av, shallowconcat1(v));
656
}
657
658
static GEN
659
vecapply2(void *E, GEN (*f)(void* E, GEN x), GEN x)
660
{
661
long i, lx;
662
GEN y = cgetg_copy(x, &lx); y[1] = x[1];
663
for (i=2; i<lx; i++) gel(y,i) = f(E, gel(x,i));
664
return y;
665
}
666
static GEN
667
vecapply1(void *E, GEN (*f)(void* E, GEN x), GEN x)
668
{
669
long i, lx;
670
GEN y = cgetg_copy(x, &lx);
671
for (i=1; i<lx; i++) gel(y,i) = f(E, gel(x,i));
672
return y;
673
}
674
static GEN
675
mapapply1(void *E, GEN (*f)(void* E, GEN x), GEN x)
676
{
677
long i, lx;
678
GEN y = cgetg_copy(x, &lx);
679
for (i=1; i<lx; i++)
680
{
681
GEN xi = gel(x, i);
682
gel(y,i) = mkvec2(mkvec2(gcopy(gmael(xi, 1, 1)), f(E,gmael(xi, 1, 2))),
683
gcopy(gel(xi, 2)));
684
}
685
return y;
686
}
687
/* as genapply, but treat A [ t_VEC,t_COL, or t_MAT] as a t_VEC */
688
GEN
689
vecapply(void *E, GEN (*f)(void* E, GEN x), GEN x)
690
{
691
GEN y;
692
clone_lock(x); y = vecapply1(E,f,x);
693
clone_unlock_deep(x); settyp(y, t_VEC); return y;
694
}
695
GEN
696
genapply(void *E, GEN (*f)(void* E, GEN x), GEN x)
697
{
698
long i, lx, tx = typ(x);
699
GEN y, z;
700
if (is_scalar_t(tx)) return f(E, x);
701
clone_lock(x);
702
switch(tx) {
703
case t_POL: y = normalizepol(vecapply2(E,f,x)); break;
704
case t_SER:
705
y = ser_isexactzero(x)? gcopy(x): normalize(vecapply2(E,f,x));
706
break;
707
case t_LIST:
708
{
709
long t = list_typ(x);
710
z = list_data(x);
711
if (!z)
712
y = mklist_typ(t);
713
else
714
{
715
y = cgetg(3, t_LIST);
716
y[1] = evaltyp(t)|evallg(lg(z)-1);
717
switch(t)
718
{
719
case t_LIST_RAW:
720
list_data(y) = vecapply1(E,f,z);
721
break;
722
case t_LIST_MAP:
723
list_data(y) = mapapply1(E,f,z);
724
break;
725
}
726
}
727
}
728
break;
729
case t_MAT:
730
y = cgetg_copy(x, &lx);
731
for (i = 1; i < lx; i++) gel(y,i) = vecapply1(E,f,gel(x,i));
732
break;
733
734
case t_VEC: case t_COL: y = vecapply1(E,f,x); break;
735
default:
736
pari_err_TYPE("apply",x);
737
return NULL;/*LCOV_EXCL_LINE*/
738
}
739
clone_unlock_deep(x); return y;
740
}
741
742
GEN
743
apply0(GEN f, GEN x)
744
{
745
check_callgen1(f, "apply");
746
return genapply((void *) f, gp_call, x);
747
}
748
749
GEN
750
vecselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun,
751
GEN (*fun)(void* E, GEN x), GEN A)
752
{
753
GEN y;
754
long i, l = lg(A), nb=1;
755
clone_lock(A); y = cgetg(l, t_VEC);
756
for (i=1; i<l; i++)
757
if (pred(Epred, gel(A,i))) gel(y,nb++) = fun(Efun, gel(A,i));
758
fixlg(y,nb); clone_unlock_deep(A); return y;
759
}
760
761
GEN
762
veccatselapply(void *Epred, long (*pred)(void* E, GEN x), void *Efun,
763
GEN (*fun)(void* E, GEN x), GEN A)
764
{
765
pari_sp av = avma;
766
GEN v = vecselapply(Epred, pred, Efun, fun, A);
767
return lg(v) == 1? v: gerepilecopy(av, shallowconcat1(v));
768
}
769
770
/* suitable for gerepileupto */
771
GEN
772
parapply_slice_worker(GEN D, GEN worker)
773
{
774
long l, i;
775
GEN w = cgetg_copy(D, &l);
776
for (i = 1; i < l; i++) gel(w,i) = closure_callgen1(worker, gel(D,i));
777
return w;
778
}
779
780
/* B <- {A[i] : i = r (mod m)}, 1 <= r <= m */
781
static void
782
arithprogset(GEN B, GEN A, long r, long m)
783
{
784
long i, k, l = lg(A);
785
for (k = 1, i = r; i < l; i += m, k++) gel(B, k) = gel(A, i);
786
setlg(B, k);
787
}
788
GEN
789
gen_parapply_slice(GEN worker, GEN D, long mmin)
790
{
791
long l, r, n = lg(D)-1, m = minss(mmin, n), pending = 0;
792
GEN L = cgetg(n / m + 2, t_VEC), va = mkvec(L), V = cgetg_copy(D, &l);
793
struct pari_mt pt;
794
mt_queue_start_lim(&pt, worker, m);
795
for (r = 1; r <= m || pending; r++)
796
{
797
long workid;
798
GEN done;
799
if (r <= m) arithprogset(L, D, r, m);
800
mt_queue_submit(&pt, r, r <= m? va: NULL);
801
done = mt_queue_get(&pt, &workid, &pending);
802
if (done)
803
{
804
long j, k, J = lg(done)-1;
805
for (j = 1, k = workid; j <= J; j++, k +=m) gel(V, k) = gel(done, j);
806
}
807
}
808
mt_queue_end(&pt); return V;
809
}
810
811
GEN
812
gen_parapply(GEN worker, GEN D)
813
{
814
long l = lg(D), i, pending = 0;
815
GEN W, V;
816
struct pari_mt pt;
817
818
if (l == 1) return cgetg(1, typ(D));
819
W = cgetg(2, t_VEC);
820
V = cgetg(l, typ(D));
821
mt_queue_start_lim(&pt, worker, l-1);
822
for (i = 1; i < l || pending; i++)
823
{
824
long workid;
825
GEN done;
826
if (i < l) gel(W,1) = gel(D,i);
827
mt_queue_submit(&pt, i, i<l? W: NULL);
828
done = mt_queue_get(&pt, &workid, &pending);
829
if (done) gel(V,workid) = done;
830
}
831
mt_queue_end(&pt); return V;
832
}
833
834
GEN
835
parapply(GEN C, GEN D)
836
{
837
pari_sp av = avma;
838
check_callgen1(C, "parapply");
839
if (!is_vec_t(typ(D))) pari_err_TYPE("parapply",D);
840
return gerepileupto(av, gen_parapply(C, D));
841
}
842
843
GEN
844
genfold(void *E, GEN (*f)(void* E, GEN x, GEN y), GEN x)
845
{
846
pari_sp av = avma;
847
GEN z;
848
long i, l = lg(x);
849
if (!is_vec_t(typ(x))|| l==1 ) pari_err_TYPE("fold",x);
850
clone_lock(x);
851
z = gel(x,1);
852
for (i=2; i<l; i++)
853
{
854
z = f(E,z,gel(x,i));
855
if (gc_needed(av, 2))
856
{
857
if (DEBUGMEM>1) pari_warn(warnmem,"fold");
858
z = gerepilecopy(av, z);
859
}
860
}
861
clone_unlock_deep(x);
862
return gerepilecopy(av, z);
863
}
864
865
GEN
866
fold0(GEN f, GEN x)
867
{
868
if (typ(f) != t_CLOSURE || closure_arity(f) < 2) pari_err_TYPE("apply",f);
869
return genfold((void *) f, gp_call2, x);
870
}
871
/*******************************************************************/
872
/* */
873
/* SCALAR-MATRIX OPERATIONS */
874
/* */
875
/*******************************************************************/
876
GEN
877
gtomat(GEN x)
878
{
879
long lx, i;
880
GEN y;
881
882
if (!x) return cgetg(1, t_MAT);
883
switch(typ(x))
884
{
885
case t_LIST:
886
if (list_typ(x)==t_LIST_MAP)
887
return maptomat(x);
888
x = list_data(x);
889
if (!x) return cgetg(1, t_MAT);
890
/* fall through */
891
case t_VEC: {
892
lx=lg(x); y=cgetg(lx,t_MAT);
893
if (lx == 1) break;
894
if (typ(gel(x,1)) == t_COL) {
895
long h = lgcols(x);
896
for (i=2; i<lx; i++) {
897
if (typ(gel(x,i)) != t_COL || lg(gel(x,i)) != h) break;
898
}
899
if (i == lx) { /* matrix with h-1 rows */
900
y = cgetg(lx, t_MAT);
901
for (i=1 ; i<lx; i++) gel(y,i) = gcopy(gel(x,i));
902
return y;
903
}
904
}
905
for (i=1; i<lx; i++) gel(y,i) = mkcolcopy(gel(x,i));
906
break;
907
}
908
case t_COL:
909
lx = lg(x);
910
if (lx == 1) return cgetg(1, t_MAT);
911
if (typ(gel(x,1)) == t_VEC) {
912
long j, h = lg(gel(x,1));
913
for (i=2; i<lx; i++) {
914
if (typ(gel(x,i)) != t_VEC || lg(gel(x,i)) != h) break;
915
}
916
if (i == lx) { /* matrix with h cols */
917
y = cgetg(h, t_MAT);
918
for (j=1 ; j<h; j++) {
919
gel(y,j) = cgetg(lx, t_COL);
920
for (i=1; i<lx; i++) gcoeff(y,i,j) = gcopy(gmael(x,i,j));
921
}
922
return y;
923
}
924
}
925
y = mkmatcopy(x); break;
926
case t_MAT:
927
y = gcopy(x); break;
928
case t_QFB: {
929
GEN b;
930
y = cgetg(3,t_MAT); b = gmul2n(gel(x,2),-1);
931
gel(y,1) = mkcol2(icopy(gel(x,1)), b);
932
gel(y,2) = mkcol2(b, icopy(gel(x,3)));
933
break;
934
}
935
default:
936
y = cgetg(2,t_MAT); gel(y,1) = mkcolcopy(x);
937
break;
938
}
939
return y;
940
}
941
942
/* create the diagonal matrix, whose diagonal is given by x */
943
GEN
944
diagonal(GEN x)
945
{
946
long j, lx, tx = typ(x);
947
GEN y;
948
949
if (! is_matvec_t(tx)) return scalarmat(x,1);
950
if (tx==t_MAT)
951
{
952
if (RgM_isdiagonal(x)) return gcopy(x);
953
pari_err_TYPE("diagonal",x);
954
}
955
lx=lg(x); y=cgetg(lx,t_MAT);
956
for (j=1; j<lx; j++)
957
{
958
gel(y,j) = zerocol(lx-1);
959
gcoeff(y,j,j) = gcopy(gel(x,j));
960
}
961
return y;
962
}
963
/* same, assuming x is a t_VEC/t_COL. Not memory clean. */
964
GEN
965
diagonal_shallow(GEN x)
966
{
967
long j, lx = lg(x);
968
GEN y = cgetg(lx,t_MAT);
969
970
for (j=1; j<lx; j++)
971
{
972
gel(y,j) = zerocol(lx-1);
973
gcoeff(y,j,j) = gel(x,j);
974
}
975
return y;
976
}
977
978
GEN
979
zv_diagonal(GEN x)
980
{
981
long j, l = lg(x), n = l-1;
982
GEN y = cgetg(l,t_MAT);
983
984
for (j = 1; j < l; j++)
985
{
986
gel(y,j) = zero_Flv(n);
987
ucoeff(y,j,j) = uel(x,j);
988
}
989
return y;
990
}
991
992
/* compute m*diagonal(d) */
993
GEN
994
matmuldiagonal(GEN m, GEN d)
995
{
996
long j, lx;
997
GEN y = cgetg_copy(m, &lx);
998
999
if (typ(m)!=t_MAT) pari_err_TYPE("matmuldiagonal",m);
1000
if (! is_vec_t(typ(d))) pari_err_TYPE("matmuldiagonal",d);
1001
if (lg(d) != lx) pari_err_OP("operation 'matmuldiagonal'", m,d);
1002
for (j=1; j<lx; j++) gel(y,j) = RgC_Rg_mul(gel(m,j), gel(d,j));
1003
return y;
1004
}
1005
1006
/* compute A*B assuming the result is a diagonal matrix */
1007
GEN
1008
matmultodiagonal(GEN A, GEN B)
1009
{
1010
long i, j, hA, hB, lA = lg(A), lB = lg(B);
1011
GEN y = matid(lB-1);
1012
1013
if (typ(A) != t_MAT) pari_err_TYPE("matmultodiagonal",A);
1014
if (typ(B) != t_MAT) pari_err_TYPE("matmultodiagonal",B);
1015
hA = (lA == 1)? lB: lgcols(A);
1016
hB = (lB == 1)? lA: lgcols(B);
1017
if (lA != hB || lB != hA) pari_err_OP("operation 'matmultodiagonal'", A,B);
1018
for (i=1; i<lB; i++)
1019
{
1020
GEN z = gen_0;
1021
for (j=1; j<lA; j++) z = gadd(z, gmul(gcoeff(A,i,j),gcoeff(B,j,i)));
1022
gcoeff(y,i,i) = z;
1023
}
1024
return y;
1025
}
1026
1027
/* [m[1,1], ..., m[l,l]], internal */
1028
GEN
1029
RgM_diagonal_shallow(GEN m)
1030
{
1031
long i, lx = lg(m);
1032
GEN y = cgetg(lx,t_VEC);
1033
for (i=1; i<lx; i++) gel(y, i) = gcoeff(m,i,i);
1034
return y;
1035
}
1036
1037
/* same, public function */
1038
GEN
1039
RgM_diagonal(GEN m)
1040
{
1041
long i, lx = lg(m);
1042
GEN y = cgetg(lx,t_VEC);
1043
for (i=1; i<lx; i++) gel(y,i) = gcopy(gcoeff(m,i,i));
1044
return y;
1045
}
1046
1047