Annotation of OpenXM_contrib2/asir2018/builtin/array.c, Revision 1.11
1.1 noro 1: /*
2: * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
3: * All rights reserved.
4: *
5: * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
6: * non-exclusive and royalty-free license to use, copy, modify and
7: * redistribute, solely for non-commercial and non-profit purposes, the
8: * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
9: * conditions of this Agreement. For the avoidance of doubt, you acquire
10: * only a limited right to use the SOFTWARE hereunder, and FLL or any
11: * third party developer retains all rights, including but not limited to
12: * copyrights, in and to the SOFTWARE.
13: *
14: * (1) FLL does not grant you a license in any way for commercial
15: * purposes. You may use the SOFTWARE only for non-commercial and
16: * non-profit purposes only, such as academic, research and internal
17: * business use.
18: * (2) The SOFTWARE is protected by the Copyright Law of Japan and
19: * international copyright treaties. If you make copies of the SOFTWARE,
20: * with or without modification, as permitted hereunder, you shall affix
21: * to all such copies of the SOFTWARE the above copyright notice.
22: * (3) An explicit reference to this SOFTWARE and its copyright owner
23: * shall be made on your publication or presentation in any form of the
24: * results obtained by use of the SOFTWARE.
25: * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
26: * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
27: * for such modification or the source code of the modified part of the
28: * SOFTWARE.
29: *
30: * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
31: * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
32: * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
33: * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
34: * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
35: * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
36: * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
37: * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
38: * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
39: * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
40: * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
41: * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
42: * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
43: * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
44: * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
45: * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
46: * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
47: *
1.11 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2018/builtin/array.c,v 1.10 2022/01/13 08:15:02 noro Exp $
1.1 noro 49: */
50: #include "ca.h"
51: #include "base.h"
52: #include "parse.h"
53: #include "inline.h"
54:
55: #include <sys/types.h>
56: #include <sys/stat.h>
57: #if !defined(_MSC_VER)
58: #include <unistd.h>
59: #endif
60:
61: #define F4_INTRAT_PERIOD 8
62:
63: #if 0
64: #undef DMAR
65: #define DMAR(a1,a2,a3,d,r) (r)=dmar(a1,a2,a3,d);
66: #endif
67:
68: extern int DP_Print; /* XXX */
69:
70:
71: void Pnewvect(), Pnewmat(), Psepvect(), Psize(), Pdet(), Pleqm(), Pleqm1(), Pgeninvm(), Ptriangleq();
72: void Pinvmat();
73: void Pnewbytearray(),Pmemoryplot_to_coord();
74:
75: void Pgeneric_gauss_elim();
76: void Pgeneric_gauss_elim_mod();
77:
78: void Pindep_rows_mod();
79:
80: void Pmat_to_gfmmat(),Plu_gfmmat(),Psolve_by_lu_gfmmat();
81: void Pgeninvm_swap(), Premainder(), Psremainder(), Pvtol(), Pltov();
82: void Pgeninv_sf_swap();
83: void sepvect();
84: void Pmulmat_gf2n();
85: void Pbconvmat_gf2n();
86: void Pmul_vect_mat_gf2n();
87: void PNBmul_gf2n();
88: void Pmul_mat_vect_int();
89: void Psepmat_destructive();
90: void Px962_irredpoly_up2();
91: void Pirredpoly_up2();
92: void Pnbpoly_up2();
93: void Pqsort();
94: void Pexponent_vector();
95: void Pmat_swap_row_destructive();
96: void Pmat_swap_col_destructive();
97: void Pvect();
98: void Pmat();
99: void Pmatc();
100: void Pnd_det();
101: void Plu_mat();
102: void Pmat_col();
103: void Plusolve_prep();
104: void Plusolve_main();
105:
106: struct ftab array_tab[] = {
107: #if 0
108: {"lu_mat",Plu_mat,1},
109: #endif
110: {"solve_by_lu_gfmmat",Psolve_by_lu_gfmmat,4},
111: {"lu_gfmmat",Plu_gfmmat,2},
112: {"mat_to_gfmmat",Pmat_to_gfmmat,2},
113: {"generic_gauss_elim",Pgeneric_gauss_elim,1},
114: {"generic_gauss_elim_mod",Pgeneric_gauss_elim_mod,2},
115: {"indep_rows_mod",Pindep_rows_mod,2},
116: {"newvect",Pnewvect,-2},
117: {"vect",Pvect,-99999999},
118: {"vector",Pnewvect,-2},
119: {"exponent_vector",Pexponent_vector,-99999999},
120: {"newmat",Pnewmat,-3},
121: {"matrix",Pnewmat,-3},
122: {"mat",Pmat,-99999999},
123: {"matr",Pmat,-99999999},
124: {"matc",Pmatc,-99999999},
125: {"newbytearray",Pnewbytearray,-2},
126: {"memoryplot_to_coord",Pmemoryplot_to_coord,1},
127: {"sepmat_destructive",Psepmat_destructive,2},
128: {"sepvect",Psepvect,2},
129: {"qsort",Pqsort,-2},
130: {"vtol",Pvtol,1},
131: {"ltov",Pltov,1},
132: {"size",Psize,1},
133: {"det",Pdet,-2},
134: {"nd_det",Pnd_det,-2},
135: {"invmat",Pinvmat,-2},
136: {"leqm",Pleqm,2},
137: {"leqm1",Pleqm1,2},
138: {"geninvm",Pgeninvm,2},
139: {"geninvm_swap",Pgeninvm_swap,2},
140: {"geninv_sf_swap",Pgeninv_sf_swap,1},
141: {"remainder",Premainder,2},
142: {"sremainder",Psremainder,2},
143: {"mulmat_gf2n",Pmulmat_gf2n,1},
144: {"bconvmat_gf2n",Pbconvmat_gf2n,-4},
145: {"mul_vect_mat_gf2n",Pmul_vect_mat_gf2n,2},
146: {"mul_mat_vect_int",Pmul_mat_vect_int,2},
147: {"nbmul_gf2n",PNBmul_gf2n,3},
148: {"x962_irredpoly_up2",Px962_irredpoly_up2,2},
149: {"irredpoly_up2",Pirredpoly_up2,2},
150: {"nbpoly_up2",Pnbpoly_up2,2},
151: {"mat_swap_row_destructive",Pmat_swap_row_destructive,3},
152: {"mat_swap_col_destructive",Pmat_swap_col_destructive,3},
153: {"mat_col",Pmat_col,2},
154: {"lusolve_prep",Plusolve_prep,1},
155: {"lusolve_main",Plusolve_main,1},
156: {"triangleq",Ptriangleq,1},
157: {0,0,0},
158: };
159:
160: typedef struct _ent { int j; unsigned int e; } ent;
161:
162: ent *get_row(FILE *,int *l);
163: void put_row(FILE *out,int l,ent *a);
164: void lu_elim(int *l,ent **a,int k,int i,int mul,int mod);
165: void lu_append(int *,ent **,int *,int,int,int);
166: void solve_l(int *,ent **,int,int *,int);
167: void solve_u(int *,ent **,int,int *,int);
168:
169:
170: static int *ul,*ll;
171: static ent **u,**l;
172: static int modulus;
1.6 fujimoto 173: #if defined(ANDROID)
174: int getw(FILE *fp)
175: {
176: int x;
177: return (fread((void *)&x, sizeof(x), 1, fp) == 1 ? x : EOF);
178: }
179: #endif
1.1 noro 180:
181: void Plusolve_prep(NODE arg,Q *rp)
182: {
183: char *fname;
184: FILE *in;
185: int len,i,rank;
186: int *rhs;
187:
188: fname = BDY((STRING)ARG0(arg));
189: in = fopen(fname,"r");
190: modulus = getw(in);
191: len = getw(in);
192: ul = (int *)MALLOC_ATOMIC(len*sizeof(int));
193: u = (ent **)MALLOC(len*sizeof(ent *));
194: ll = (int *)MALLOC_ATOMIC(len*sizeof(int));
195: l = (ent **)MALLOC(len*sizeof(ent *));
196: for ( i = 0; i < len; i++ ) {
197: u[i] = get_row(in,&ul[i]);
198: }
199: for ( i = 0; i < len; i++ ) {
200: l[i] = get_row(in,&ll[i]);
201: }
202: fclose(in);
203: *rp = (Q)ONE;
204: }
205:
206: void Plusolve_main(NODE arg,VECT *rp)
207: {
208: Z *d,*p;
209: VECT v,r;
210: int len,i;
211: int *rhs;
212:
213: v = (VECT)ARG0(arg); len = v->len;
214: d = (Z *)BDY(v);
215: rhs = (int *)MALLOC_ATOMIC(len*sizeof(int));
1.2 noro 216: for ( i = 0; i < len; i++ ) rhs[i] = ZTOS(d[i]);
1.1 noro 217: solve_l(ll,l,len,rhs,modulus);
218: solve_u(ul,u,len,rhs,modulus);
219: NEWVECT(r); r->len = len;
220: r->body = (pointer *)MALLOC(len*sizeof(pointer));
221: p = (Z *)r->body;
222: for ( i = 0; i < len; i++ )
1.2 noro 223: STOZ(rhs[i],p[i]);
1.1 noro 224: *rp = r;
225: }
226:
227: ent *get_row(FILE *in,int *l)
228: {
229: int len,i;
230: ent *a;
231:
232: *l = len = getw(in);
233: a = (ent *)MALLOC_ATOMIC(len*sizeof(ent));
234: for ( i = 0; i < len; i++ ) {
235: a[i].j = getw(in);
236: a[i].e = getw(in);
237: }
238: return a;
239: }
240:
241: void lu_gauss(int *ul,ent **u,int *ll,ent **l,int n,int mod)
242: {
243: int i,j,k,s,mul;
244: unsigned int inv;
245: int *ll2;
246:
247: ll2 = (int *)MALLOC_ATOMIC(n*sizeof(int));
248: for ( i = 0; i < n; i++ ) ll2[i] = 0;
249: for ( i = 0; i < n; i++ ) {
250: fprintf(stderr,"i=%d\n",i);
251: inv = invm(u[i][0].e,mod);
252: for ( k = i+1; k < n; k++ )
253: if ( u[k][0].j == n-i ) {
254: s = u[k][0].e;
255: DMAR(s,inv,0,mod,mul);
256: lu_elim(ul,u,k,i,mul,mod);
257: lu_append(ll,l,ll2,k,i,mul);
258: }
259: }
260: }
261:
262: #define INITLEN 10
263:
264: void lu_append(int *l,ent **a,int *l2,int k,int i,int mul)
265: {
266: int len;
267: ent *p;
268:
269: len = l[k];
270: if ( !len ) {
271: a[k] = p = (ent *)MALLOC_ATOMIC(INITLEN*sizeof(ent));
272: p[0].j = i; p[0].e = mul;
273: l[k] = 1; l2[k] = INITLEN;
274: } else {
275: if ( l2[k] == l[k] ) {
276: l2[k] *= 2;
277: a[k] = REALLOC(a[k],l2[k]*sizeof(ent));
278: }
279: p =a[k];
280: p[l[k]].j = i; p[l[k]].e = mul;
281: l[k]++;
282: }
283: }
284:
285: /* a[k] = a[k]-mul*a[i] */
286:
287: void lu_elim(int *l,ent **a,int k,int i,int mul,int mod)
288: {
289: ent *ak,*ai,*w;
290: int lk,li,j,m,p,q,r,s,t,j0;
291:
292: ak = a[k]; ai = a[i]; lk = l[k]; li = l[i];
293: w = (ent *)alloca((lk+li)*sizeof(ent));
294: p = 0; q = 0; j = 0;
295: mul = mod-mul;
296: while ( p < lk && q < li ) {
297: if ( ak[p].j > ai[q].j ) {
298: w[j] = ak[p]; j++; p++;
299: } else if ( ak[p].j < ai[q].j ) {
300: w[j].j = ai[q].j;
301: t = ai[q].e;
302: DMAR(t,mul,0,mod,r);
303: w[j].e = r;
304: j++; q++;
305: } else {
306: t = ai[q].e; s = ak[p].e;
307: DMAR(t,mul,s,mod,r);
308: if ( r ) {
309: w[j].j = ai[q].j; w[j].e = r; j++;
310: }
311: p++; q++;
312: }
313: }
314: if ( q == li )
315: while ( p < lk ) {
316: w[j] = ak[p]; j++; p++;
317: }
318: else if ( p == lk )
319: while ( q < li ) {
320: w[j].j = ai[q].j;
321: t = ai[q].e;
322: DMAR(t,mul,0,mod,r);
323: w[j].e = r;
324: j++; q++;
325: }
326: if ( j <= lk ) {
327: for ( m = 0; m < j; m++ ) ak[m] = w[m];
328: } else {
329: a[k] = ak = (ent *)MALLOC_ATOMIC(j*sizeof(ent));
330: for ( m = 0; m < j; m++ ) ak[m] = w[m];
331: }
332: l[k] = j;
333: }
334:
335: void solve_l(int *ll,ent **l,int n,int *rhs,int mod)
336: {
337: int j,k,s,len;
338: ent *p;
339:
340: for ( j = 0; j < n; j++ ) {
341: len = ll[j]; p = l[j];
342: for ( k = 0, s = 0; k < len; k++ )
343: s = dmar(p[k].e,rhs[p[k].j],s,mod);
344: rhs[j] -= s;
345: if ( rhs[j] < 0 ) rhs[j] += mod;
346: }
347: }
348:
349: void solve_u(int *ul,ent **u,int n,int *rhs,int mod)
350: {
351: int j,k,s,len,inv;
352: ent *p;
353:
354: for ( j = n-1; j >= 0; j-- ) {
355: len = ul[j]; p = u[j];
356: for ( k = 1, s = 0; k < len; k++ )
357: s = dmar(p[k].e,rhs[p[k].j],s,mod);
358: rhs[j] -= s;
359: if ( rhs[j] < 0 ) rhs[j] += mod;
360: inv = invm((unsigned int)p[0].e,mod);
361: rhs[j] = dmar(rhs[j],inv,0,mod);
362: }
363: }
364:
365: int comp_obj(Obj *a,Obj *b)
366: {
367: return arf_comp(CO,*a,*b);
368: }
369:
370: static FUNC generic_comp_obj_func;
371: static NODE generic_comp_obj_arg;
372: static NODE generic_comp_obj_option;
373:
374: int generic_comp_obj(Obj *a,Obj *b)
375: {
376: Q r;
377:
378: BDY(generic_comp_obj_arg)=(pointer)(*a);
379: BDY(NEXT(generic_comp_obj_arg))=(pointer)(*b);
380: r = (Q)bevalf_with_opts(generic_comp_obj_func,generic_comp_obj_arg,generic_comp_obj_option);
381: if ( !r )
382: return 0;
383: else
384: return sgnq(r)>0?1:-1;
385: }
386:
387:
388: void Pqsort(NODE arg,LIST *rp)
389: {
390: VECT vect;
391: NODE n,n1;
392: P p;
393: V v;
394: FUNC func;
395: int len,i;
396: pointer *a;
397: Obj t;
398:
399: t = ARG0(arg);
400: if (OID(t) == O_LIST) {
401: n = (NODE)BDY((LIST)t);
402: len = length(n);
403: MKVECT(vect,len);
404: for ( i = 0; i < len; i++, n = NEXT(n) ) {
405: BDY(vect)[i] = BDY(n);
406: }
407:
408: }else if (OID(t) != O_VECT) {
409: error("qsort : invalid argument");
410: }else {
411: vect = (VECT)t;
412: }
413: if ( argc(arg) == 1 )
414: qsort(BDY(vect),vect->len,sizeof(Obj),(int (*)(const void *,const void *))comp_obj);
415: else {
416: p = (P)ARG1(arg);
417: if ( !p || OID(p)!=2 )
418: error("qsort : invalid argument");
419: v = VR(p);
420: gen_searchf(NAME(v),&func);
421: if ( !func ) {
422: if ( (long)v->attr != V_SR )
423: error("qsort : no such function");
424: func = (FUNC)v->priv;
425: }
426: generic_comp_obj_func = func;
427: MKNODE(n,0,0); MKNODE(generic_comp_obj_arg,0,n);
428: generic_comp_obj_option = current_option;
429: qsort(BDY(vect),vect->len,sizeof(Obj),(int (*)(const void *,const void *))generic_comp_obj);
430: }
431: if (OID(t) == O_LIST) {
432: a = BDY(vect);
433: for ( i = len - 1, n = 0; i >= 0; i-- ) {
434: MKNODE(n1,a[i],n); n = n1;
435: }
436: MKLIST(*rp,n);
437: }else {
438: *rp = (LIST)vect;
439: }
440: }
441:
442: void PNBmul_gf2n(NODE arg,GF2N *rp)
443: {
444: GF2N a,b;
445: GF2MAT mat;
446: int n,w;
447: unsigned int *ab,*bb;
448: UP2 r;
449:
450: a = (GF2N)ARG0(arg);
451: b = (GF2N)ARG1(arg);
452: mat = (GF2MAT)ARG2(arg);
453: if ( !a || !b )
454: *rp = 0;
455: else {
456: n = mat->row;
457: w = (n+BSH-1)/BSH;
458:
459: ab = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
460: bzero((char *)ab,w*sizeof(unsigned int));
461: bcopy(a->body->b,ab,(a->body->w)*sizeof(unsigned int));
462:
463: bb = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
464: bzero((char *)bb,w*sizeof(unsigned int));
465: bcopy(b->body->b,bb,(b->body->w)*sizeof(unsigned int));
466:
467: NEWUP2(r,w);
468: bzero((char *)r->b,w*sizeof(unsigned int));
469: mul_nb(mat,ab,bb,r->b);
470: r->w = w;
471: _adjup2(r);
472: if ( !r->w )
473: *rp = 0;
474: else
475: MKGF2N(r,*rp);
476: }
477: }
478:
479: void Pmul_vect_mat_gf2n(NODE arg,GF2N *rp)
480: {
481: GF2N a;
482: GF2MAT mat;
483: int n,w;
484: unsigned int *b;
485: UP2 r;
486:
487: a = (GF2N)ARG0(arg);
488: mat = (GF2MAT)ARG1(arg);
489: if ( !a )
490: *rp = 0;
491: else {
492: n = mat->row;
493: w = (n+BSH-1)/BSH;
494: b = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
495: bzero((char *)b,w*sizeof(unsigned int));
496: bcopy(a->body->b,b,(a->body->w)*sizeof(unsigned int));
497: NEWUP2(r,w);
498: bzero((char *)r->b,w*sizeof(unsigned int));
499: mulgf2vectmat(mat->row,b,mat->body,r->b);
500: r->w = w;
501: _adjup2(r);
502: if ( !r->w )
503: *rp = 0;
504: else {
505: MKGF2N(r,*rp);
506: }
507: }
508: }
509:
510: void Pbconvmat_gf2n(NODE arg,LIST *rp)
511: {
512: P p0,p1;
513: int to;
514: GF2MAT p01,p10;
515: GF2N root;
516: NODE n0,n1;
517:
518: p0 = (P)ARG0(arg);
519: p1 = (P)ARG1(arg);
520: to = ARG2(arg)?1:0;
521: if ( argc(arg) == 4 ) {
522: root = (GF2N)ARG3(arg);
523: compute_change_of_basis_matrix_with_root(p0,p1,to,root,&p01,&p10);
524: } else
525: compute_change_of_basis_matrix(p0,p1,to,&p01,&p10);
526: MKNODE(n1,p10,0); MKNODE(n0,p01,n1);
527: MKLIST(*rp,n0);
528: }
529:
530: void Pmulmat_gf2n(NODE arg,GF2MAT *rp)
531: {
532: GF2MAT m;
533:
534: if ( !compute_multiplication_matrix((P)ARG0(arg),&m) )
535: error("mulmat_gf2n : input is not a normal polynomial");
536: *rp = m;
537: }
538:
539: void Psepmat_destructive(NODE arg,LIST *rp)
540: {
541: MAT mat,mat1;
542: int i,j,row,col;
543: Z **a,**a1;
544: Z ent;
545: Z nm,mod,rem,quo;
546: int sgn;
547: NODE n0,n1;
548:
549: mat = (MAT)ARG0(arg); mod = (Z)ARG1(arg);
550: row = mat->row; col = mat->col;
551: MKMAT(mat1,row,col);
552: a = (Z **)mat->body; a1 = (Z **)mat1->body;
553: for ( i = 0; i < row; i++ )
554: for ( j = 0; j < col; j++ ) {
555: ent = a[i][j];
556: if ( !ent )
557: continue;
558: sgn = sgnz(ent);
559: absz(ent,&nm);
560: divqrz(nm,mod,&quo,&rem);
561: if ( sgn > 0 ) {
562: a[i][j] = rem;
563: a1[i][j] = quo;
564: } else {
565: chsgnz(rem,&a[i][j]);
566: chsgnz(quo,&a1[i][j]);
567: }
568: }
569: MKNODE(n1,mat1,0); MKNODE(n0,mat,n1);
570: MKLIST(*rp,n0);
571: }
572:
573: void Psepvect(NODE arg,VECT *rp)
574: {
1.2 noro 575: sepvect((VECT)ARG0(arg),ZTOS((Q)ARG1(arg)),rp);
1.1 noro 576: }
577:
578: void sepvect(VECT v,int d,VECT *rp)
579: {
580: int i,j,k,n,q,q1,r;
581: pointer *pv,*pw,*pu;
582: VECT w,u;
583:
584: n = v->len;
585: if ( d > n )
586: d = n;
587: q = n/d; r = n%d; q1 = q+1;
588: MKVECT(w,d); *rp = w;
589: pv = BDY(v); pw = BDY(w); k = 0;
590: for ( i = 0; i < r; i++ ) {
591: MKVECT(u,q1); pw[i] = (pointer)u;
592: for ( pu = BDY(u), j = 0; j < q1; j++, k++ )
593: pu[j] = pv[k];
594: }
595: for ( ; i < d; i++ ) {
596: MKVECT(u,q); pw[i] = (pointer)u;
597: for ( pu = BDY(u), j = 0; j < q; j++, k++ )
598: pu[j] = pv[k];
599: }
600: }
601:
602: void Pnewvect(NODE arg,VECT *rp)
603: {
604: int len,i,r;
605: VECT vect;
606: pointer *vb;
607: LIST list;
608: NODE tn;
609:
610: asir_assert(ARG0(arg),O_N,"newvect");
1.2 noro 611: len = ZTOS((Q)ARG0(arg));
1.1 noro 612: if ( len < 0 )
613: error("newvect : invalid size");
614: MKVECT(vect,len);
615: if ( argc(arg) == 2 ) {
616: list = (LIST)ARG1(arg);
617: asir_assert(list,O_LIST,"newvect");
618: #if 0
619: for ( r = 0, tn = BDY(list); tn; r++, tn = NEXT(tn) );
620: if ( r > len ) {
621: *rp = vect;
622: return;
623: }
624: #endif
1.9 ohara 625: for ( i = 0, tn = BDY(list), vb = BDY(vect); tn && i<len; i++, tn = NEXT(tn) )
1.1 noro 626: vb[i] = (pointer)BDY(tn);
627: }
628: *rp = vect;
629: }
630:
631: void Pvect(NODE arg,VECT *rp) {
632: int len,i;
633: VECT vect;
634: pointer *vb;
635: NODE tn;
636:
637: if ( !arg ) {
638: *rp =0;
639: return;
640: }
641:
642: for (len = 0, tn = arg; tn; tn = NEXT(tn), len++);
643: if ( len == 1 ) {
644: if ( ARG0(arg) != 0 ) {
645: switch ( OID(ARG0(arg)) ) {
646: case O_VECT:
647: *rp = ARG0(arg);
648: return;
649: case O_LIST:
650: for ( len = 0, tn = ARG0(arg); tn; tn = NEXT(tn), len++ );
651: MKVECT(vect,len-1);
652: for ( i = 0, tn = BDY((LIST)ARG0(arg)), vb =BDY(vect);
653: tn; i++, tn = NEXT(tn) )
654: vb[i] = (pointer)BDY(tn);
655: *rp=vect;
656: return;
657: }
658: }
659: }
660: MKVECT(vect,len);
661: for ( i = 0, tn = arg, vb = BDY(vect); tn; i++, tn = NEXT(tn) )
662: vb[i] = (pointer)BDY(tn);
663: *rp = vect;
664: }
665:
666: void Pexponent_vector(NODE arg,DP *rp)
667: {
668: nodetod(arg,rp);
669: }
670:
671: void Pnewbytearray(NODE arg,BYTEARRAY *rp)
672: {
673: int len,i,r;
674: BYTEARRAY array;
675: unsigned char *vb;
676: char *str;
677: LIST list;
678: NODE tn;
679: int ac;
680: struct stat sbuf;
681: char *fname;
682: FILE *fp;
683:
684: ac = argc(arg);
685: if ( ac == 1 ) {
686: if ( !OID((Obj)ARG0(arg)) ) error("newbytearray : invalid argument");
687: switch ( OID((Obj)ARG0(arg)) ) {
688: case O_STR:
689: fname = BDY((STRING)ARG0(arg));
690: fp = fopen(fname,"rb");
691: if ( !fp ) error("newbytearray : fopen failed");
692: if ( stat(fname,&sbuf) < 0 )
693: error("newbytearray : stat failed");
694: len = sbuf.st_size;
695: MKBYTEARRAY(array,len);
696: fread(BDY(array),len,sizeof(char),fp);
697: break;
698: case O_N:
699: if ( !RATN(ARG0(arg)) )
700: error("newbytearray : invalid argument");
1.2 noro 701: len = ZTOS((Q)ARG0(arg));
1.1 noro 702: if ( len < 0 )
703: error("newbytearray : invalid size");
704: MKBYTEARRAY(array,len);
705: break;
706: default:
707: error("newbytearray : invalid argument");
708: }
709: } else if ( ac == 2 ) {
710: asir_assert(ARG0(arg),O_N,"newbytearray");
1.2 noro 711: len = ZTOS((Q)ARG0(arg));
1.1 noro 712: if ( len < 0 )
713: error("newbytearray : invalid size");
714: MKBYTEARRAY(array,len);
715: if ( !ARG1(arg) )
716: error("newbytearray : invalid initialization");
717: switch ( OID((Obj)ARG1(arg)) ) {
718: case O_LIST:
719: list = (LIST)ARG1(arg);
720: asir_assert(list,O_LIST,"newbytearray");
721: for ( r = 0, tn = BDY(list); tn; r++, tn = NEXT(tn) );
722: if ( r <= len ) {
723: for ( i = 0, tn = BDY(list), vb = BDY(array); tn;
724: i++, tn = NEXT(tn) )
1.2 noro 725: vb[i] = (unsigned char)ZTOS((Q)BDY(tn));
1.1 noro 726: }
727: break;
728: case O_STR:
729: str = BDY((STRING)ARG1(arg));
730: r = strlen(str);
731: if ( r <= len )
732: bcopy(str,BDY(array),r);
733: break;
734: default:
735: if ( !ARG1(arg) )
736: error("newbytearray : invalid initialization");
737: }
738: } else
739: error("newbytearray : invalid argument");
740: *rp = array;
741: }
742:
743: #define MEMORY_GETPOINT(a,len,x,y) (((a)[(len)*(y)+((x)>>3)])&(1<<((x)&7)))
744:
745: void Pmemoryplot_to_coord(NODE arg,LIST *rp)
746: {
747: int len,blen,y,i,j;
748: unsigned char *a;
749: NODE r0,r,n;
750: LIST l;
751: BYTEARRAY ba;
752: Z iq,jq;
753:
754: asir_assert(ARG0(arg),O_LIST,"memoryplot_to_coord");
755: arg = BDY((LIST)ARG0(arg));
1.2 noro 756: len = ZTOS((Q)ARG0(arg));
1.1 noro 757: blen = (len+7)/8;
1.2 noro 758: y = ZTOS((Q)ARG1(arg));
1.1 noro 759: ba = (BYTEARRAY)ARG2(arg); a = ba->body;
760: r0 = 0;
761: for ( j = 0; j < y; j++ )
762: for ( i = 0; i < len; i++ )
763: if ( MEMORY_GETPOINT(a,blen,i,j) ) {
764: NEXTNODE(r0,r);
1.2 noro 765: STOZ(i,iq); STOZ(j,jq);
1.1 noro 766: n = mknode(2,iq,jq);
767: MKLIST(l,n);
768: BDY(r) = l;
769: }
770: if ( r0 ) NEXT(r) = 0;
771: MKLIST(*rp,r0);
772: }
773:
774: void Pnewmat(NODE arg,MAT *rp)
775: {
776: int row,col;
777: int i,j,r,c;
778: NODE tn,sn;
779: MAT m;
780: pointer **mb;
781: LIST list;
782:
783: asir_assert(ARG0(arg),O_N,"newmat");
784: asir_assert(ARG1(arg),O_N,"newmat");
1.2 noro 785: row = ZTOS((Q)ARG0(arg)); col = ZTOS((Q)ARG1(arg));
1.1 noro 786: if ( row < 0 || col < 0 )
787: error("newmat : invalid size");
788: MKMAT(m,row,col);
789: if ( argc(arg) == 3 ) {
790: list = (LIST)ARG2(arg);
791: asir_assert(list,O_LIST,"newmat");
792: for ( r = 0, c = 0, tn = BDY(list); tn; r++, tn = NEXT(tn) ) {
793: for ( j = 0, sn = BDY((LIST)BDY(tn)); sn; j++, sn = NEXT(sn) );
794: c = MAX(c,j);
795: }
796: if ( (r > row) || (c > col) ) {
797: *rp = m;
798: return;
799: }
800: for ( i = 0, tn = BDY(list), mb = BDY(m); tn; i++, tn = NEXT(tn) ) {
801: asir_assert(BDY(tn),O_LIST,"newmat");
802: for ( j = 0, sn = BDY((LIST)BDY(tn)); sn; j++, sn = NEXT(sn) )
803: mb[i][j] = (pointer)BDY(sn);
804: }
805: }
806: *rp = m;
807: }
808:
809: void Pmat(NODE arg, MAT *rp)
810: {
811: int row,col;
812: int i;
813: MAT m;
814: pointer **mb;
815: pointer *ent;
816: NODE tn, sn;
817: VECT v;
818:
819: if ( !arg ) {
820: *rp =0;
821: return;
822: }
823:
824: for (row = 0, tn = arg; tn; tn = NEXT(tn), row++);
825: if ( row == 1 ) {
826: if ( OID(ARG0(arg)) == O_MAT ) {
827: *rp=ARG0(arg);
828: return;
829: } else if ( !(OID(ARG0(arg)) == O_LIST || OID(ARG0(arg)) == O_VECT)) {
830: error("mat : invalid argument");
831: }
832: }
833: if ( OID(ARG0(arg)) == O_VECT ) {
834: v = ARG0(arg);
835: col = v->len;
836: } else if ( OID(ARG0(arg)) == O_LIST ) {
837: for (col = 0, tn = BDY((LIST)ARG0(arg)); tn ; tn = NEXT(tn), col++);
838: } else {
839: error("mat : invalid argument");
840: }
841:
842: MKMAT(m,row,col);
843: for (row = 0, tn = arg, mb = BDY(m); tn; tn = NEXT(tn), row++) {
844: if ( BDY(tn) == 0 ) {
845: error("mat : invalid argument");
846: } else if ( OID(BDY(tn)) == O_VECT ) {
847: v = tn->body;
848: ent = BDY(v);
849: for (i = 0; i < v->len; i++ ) mb[row][i] = (Obj)ent[i];
850: } else if ( OID(BDY(tn)) == O_LIST ) {
851: for (col = 0, sn = BDY((LIST)BDY(tn)); sn; col++, sn = NEXT(sn) )
852: mb[row][col] = (pointer)BDY(sn);
853: } else {
854: error("mat : invalid argument");
855: }
856: }
857: *rp = m;
858: }
859:
860: void Pmatc(NODE arg, MAT *rp)
861: {
862: int row,col;
863: int i;
864: MAT m;
865: pointer **mb;
866: pointer *ent;
867: NODE tn, sn;
868: VECT v;
869:
870: if ( !arg ) {
871: *rp =0;
872: return;
873: }
874:
875: for (col = 0, tn = arg; tn; tn = NEXT(tn), col++);
876: if ( col == 1 ) {
877: if ( OID(ARG0(arg)) == O_MAT ) {
878: *rp=ARG0(arg);
879: return;
880: } else if ( !(OID(ARG0(arg)) == O_LIST || OID(ARG0(arg)) == O_VECT)) {
881: error("matc : invalid argument");
882: }
883: }
884: if ( OID(ARG0(arg)) == O_VECT ) {
885: v = ARG0(arg);
886: row = v->len;
887: } else if ( OID(ARG0(arg)) == O_LIST ) {
888: for (row = 0, tn = BDY((LIST)ARG0(arg)); tn ; tn = NEXT(tn), row++);
889: } else {
890: error("matc : invalid argument");
891: }
892:
893: MKMAT(m,row,col);
894: for (col = 0, tn = arg, mb = BDY(m); tn; tn = NEXT(tn), col++) {
895: if ( BDY(tn) == 0 ) {
896: error("matc : invalid argument");
897: } else if ( OID(BDY(tn)) == O_VECT ) {
898: v = tn->body;
899: ent = BDY(v);
900: for (i = 0; i < v->len; i++ ) mb[i][col] = (Obj)ent[i];
901: } else if ( OID(BDY(tn)) == O_LIST ) {
902: for (row = 0, sn = BDY((LIST)BDY(tn)); sn; row++, sn = NEXT(sn) )
903: mb[row][col] = (pointer)BDY(sn);
904: } else {
905: error("matc : invalid argument");
906: }
907: }
908: *rp = m;
909: }
910:
911: void Pvtol(NODE arg,LIST *rp)
912: {
913: NODE n,n1;
914: VECT v;
915: pointer *a;
916: int len,i;
917:
918: if ( OID(ARG0(arg)) == O_LIST ) {
919: *rp = ARG0(arg);
920: return;
921: }
922: asir_assert(ARG0(arg),O_VECT,"vtol");
923: v = (VECT)ARG0(arg); len = v->len; a = BDY(v);
924: for ( i = len - 1, n = 0; i >= 0; i-- ) {
925: MKNODE(n1,a[i],n); n = n1;
926: }
927: MKLIST(*rp,n);
928: }
929:
930: void Pltov(NODE arg,VECT *rp)
931: {
932: NODE n;
933: VECT v,v0;
934: int len,i;
935:
936: if ( OID(ARG0(arg)) == O_VECT ) {
937: v0 = (VECT)ARG0(arg); len = v0->len;
938: MKVECT(v,len);
939: for ( i = 0; i < len; i++ ) {
940: BDY(v)[i] = BDY(v0)[i];
941: }
942: *rp = v;
943: return;
944: }
945: asir_assert(ARG0(arg),O_LIST,"ltov");
946: n = (NODE)BDY((LIST)ARG0(arg));
947: len = length(n);
948: MKVECT(v,len);
949: for ( i = 0; i < len; i++, n = NEXT(n) )
950: BDY(v)[i] = BDY(n);
951: *rp = v;
952: }
953:
954: /* XXX it seems that remainder is not used */
955:
956: void Premainder(NODE arg,Obj *rp)
957: {
958: Obj a;
959: VECT v,w;
960: MAT m,l;
961: pointer *vb,*wb;
962: pointer **mb,**lb;
963: int id,i,j,n,row,col,t,smd,sgn;
964: Z md,q,r;
965:
966: a = (Obj)ARG0(arg); md = (Z)ARG1(arg);
967: if ( !a )
968: *rp = 0;
969: else {
970: id = OID(a);
971: switch ( id ) {
972: case O_N:
973: case O_P:
974: cmp(md,(P)a,(P *)rp); break;
975: case O_VECT:
976: /* strage spec */
1.2 noro 977: smd = ZTOS(md);
1.1 noro 978: v = (VECT)a; n = v->len; vb = v->body;
979: MKVECT(w,n); wb = w->body;
980: for ( i = 0; i < n; i++ ) {
981: if ( sgnz(vb[i]) > 0 )
982: remz(vb[i],md,(Z *)&wb[i]);
983: else {
984: absz(vb[i],&q);
985: remz(q,md,&r);
986: chsgnz(r,(Z *)&wb[i]);
987: }
988: }
989: *rp = (Obj)w;
990: break;
991: case O_MAT:
992: m = (MAT)a; row = m->row; col = m->col; mb = m->body;
993: MKMAT(l,row,col); lb = l->body;
994: for ( i = 0; i < row; i++ )
995: for ( j = 0, vb = mb[i], wb = lb[i]; j < col; j++ )
996: cmp(md,(P)vb[j],(P *)&wb[j]);
997: *rp = (Obj)l;
998: break;
999: default:
1000: error("remainder : invalid argument");
1001: }
1002: }
1003: }
1004:
1005: void Psremainder(NODE arg,Obj *rp)
1006: {
1007: Obj a;
1008: VECT v,w;
1009: MAT m,l;
1010: pointer *vb,*wb;
1011: pointer **mb,**lb;
1012: int id,i,j,n,row,col,t,smd,sgn;
1013: Z md,q,r;
1014:
1015: a = (Obj)ARG0(arg); md = (Z)ARG1(arg);
1016: if ( !a )
1017: *rp = 0;
1018: else {
1019: id = OID(a);
1020: switch ( id ) {
1021: case O_N:
1022: case O_P:
1023: cmp(md,(P)a,(P *)rp); break;
1024: case O_VECT:
1.2 noro 1025: smd = ZTOS(md);
1.1 noro 1026: v = (VECT)a; n = v->len; vb = v->body;
1027: MKVECT(w,n); wb = w->body;
1028: for ( i = 0; i < n; i++ )
1029: remz(vb[i],md,(Z *)&wb[i]);
1030: *rp = (Obj)w;
1031: break;
1032: case O_MAT:
1033: m = (MAT)a; row = m->row; col = m->col; mb = m->body;
1034: MKMAT(l,row,col); lb = l->body;
1035: for ( i = 0; i < row; i++ )
1036: for ( j = 0, vb = mb[i], wb = lb[i]; j < col; j++ )
1037: cmp(md,(P)vb[j],(P *)&wb[j]);
1038: *rp = (Obj)l;
1039: break;
1040: default:
1041: error("remainder : invalid argument");
1042: }
1043: }
1044: }
1045:
1046: void Psize(NODE arg,LIST *rp)
1047: {
1048:
1049: int n,m;
1050: Z q;
1051: NODE t,s;
1052:
1053: if ( !ARG0(arg) )
1054: t = 0;
1055: else {
1056: switch (OID(ARG0(arg))) {
1057: case O_VECT:
1058: n = ((VECT)ARG0(arg))->len;
1.2 noro 1059: STOZ(n,q); MKNODE(t,q,0);
1.1 noro 1060: break;
1061: case O_MAT:
1062: n = ((MAT)ARG0(arg))->row; m = ((MAT)ARG0(arg))->col;
1.2 noro 1063: STOZ(m,q); MKNODE(s,q,0); STOZ(n,q); MKNODE(t,q,s);
1.1 noro 1064: break;
1065: case O_IMAT:
1066: n = ((IMAT)ARG0(arg))->row; m = ((IMAT)ARG0(arg))->col;
1.2 noro 1067: STOZ(m,q); MKNODE(s,q,0); STOZ(n,q); MKNODE(t,q,s);
1.1 noro 1068: break;
1069: default:
1070: error("size : invalid argument"); break;
1071: }
1072: }
1073: MKLIST(*rp,t);
1074: }
1075:
1076: void Pdet(NODE arg,P *rp)
1077: {
1078: MAT m;
1079: int n,i,j,mod;
1080: P d;
1081: P **mat,**w;
1082:
1083: m = (MAT)ARG0(arg);
1084: asir_assert(m,O_MAT,"det");
1085: if ( m->row != m->col )
1086: error("det : non-square matrix");
1087: else if ( argc(arg) == 1 )
1088: detp(CO,(P **)BDY(m),m->row,rp);
1089: else {
1.2 noro 1090: n = m->row; mod = ZTOS((Q)ARG1(arg)); mat = (P **)BDY(m);
1.1 noro 1091: w = (P **)almat_pointer(n,n);
1092: for ( i = 0; i < n; i++ )
1093: for ( j = 0; j < n; j++ )
1094: ptomp(mod,mat[i][j],&w[i][j]);
1095: detmp(CO,mod,w,n,&d);
1096: mptop(d,rp);
1097: }
1098: }
1099:
1100: void Pinvmat(NODE arg,LIST *rp)
1101: {
1102: MAT m,r;
1103: int n,i,j,mod;
1104: P dn;
1105: P **mat,**imat,**w;
1106: NODE nd;
1107:
1108: m = (MAT)ARG0(arg);
1109: asir_assert(m,O_MAT,"invmat");
1110: if ( m->row != m->col )
1111: error("invmat : non-square matrix");
1112: else if ( argc(arg) == 1 ) {
1113: n = m->row;
1114: invmatp(CO,(P **)BDY(m),n,&imat,&dn);
1115: NEWMAT(r); r->row = n; r->col = n; r->body = (pointer **)imat;
1116: nd = mknode(2,r,dn);
1117: MKLIST(*rp,nd);
1118: } else {
1.2 noro 1119: n = m->row; mod = ZTOS((Q)ARG1(arg)); mat = (P **)BDY(m);
1.1 noro 1120: w = (P **)almat_pointer(n,n);
1121: for ( i = 0; i < n; i++ )
1122: for ( j = 0; j < n; j++ )
1123: ptomp(mod,mat[i][j],&w[i][j]);
1124: #if 0
1125: detmp(CO,mod,w,n,&d);
1126: mptop(d,rp);
1127: #else
1128: error("not implemented yet");
1129: #endif
1130: }
1131: }
1132:
1133: /*
1134: input : a row x col matrix A
1135: A[I] <-> A[I][0]*x_0+A[I][1]*x_1+...
1136:
1137: output : [B,D,R,C]
1138: B : a rank(A) x col-rank(A) matrix
1139: D : the denominator
1140: R : a vector of length rank(A)
1141: C : a vector of length col-rank(A)
1142: B[I] <-> D*x_{R[I]}+B[I][0]x_{C[0]}+B[I][1]x_{C[1]}+...
1143: */
1144:
1145: void Pgeneric_gauss_elim(NODE arg,LIST *rp)
1146: {
1147: NODE n0,opt,p;
1148: MAT m,nm;
1149: int *ri,*ci;
1150: VECT rind,cind;
1151: Z dn,q;
1152: int i,row,col,t,rank;
1153: int is_hensel = 0;
1154: char *key;
1155: Obj value;
1156:
1157: if ( current_option ) {
1158: for ( opt = current_option; opt; opt = NEXT(opt) ) {
1159: p = BDY((LIST)BDY(opt));
1160: key = BDY((STRING)BDY(p));
1161: value = (Obj)BDY(NEXT(p));
1162: if ( !strcmp(key,"hensel") && value ) {
1163: is_hensel = value ? 1 : 0;
1164: break;
1165: }
1166: }
1167: }
1168: asir_assert(ARG0(arg),O_MAT,"generic_gauss_elim");
1169: m = (MAT)ARG0(arg);
1170: row = m->row; col = m->col;
1171: if ( is_hensel )
1172: rank = generic_gauss_elim_hensel(m,&nm,&dn,&ri,&ci);
1173: else
1.5 noro 1174: rank = generic_gauss_elim(m,&nm,&dn,&ri,&ci);
1.1 noro 1175: t = col-rank;
1176: MKVECT(rind,rank);
1177: MKVECT(cind,t);
1178: for ( i = 0; i < rank; i++ ) {
1.2 noro 1179: STOZ(ri[i],q);
1.1 noro 1180: BDY(rind)[i] = (pointer)q;
1181: }
1182: for ( i = 0; i < t; i++ ) {
1.2 noro 1183: STOZ(ci[i],q);
1.1 noro 1184: BDY(cind)[i] = (pointer)q;
1185: }
1186: n0 = mknode(4,nm,dn,rind,cind);
1187: MKLIST(*rp,n0);
1188: }
1189:
1190: int indep_rows_mod(int **mat0,int row,int col,int md,int *rowstat);
1191:
1192: void Pindep_rows_mod(NODE arg,VECT *rp)
1193: {
1194: MAT m,mat;
1195: VECT rind;
1196: Z **tmat;
1197: int **wmat,**row0;
1198: Z *rib;
1199: int *rowstat,*p;
1200: Z q;
1201: int md,i,j,k,l,row,col,t,rank;
1202:
1203: asir_assert(ARG0(arg),O_MAT,"indep_rows_mod");
1204: asir_assert(ARG1(arg),O_N,"indep_rows_mod");
1.2 noro 1205: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1.1 noro 1206: row = m->row; col = m->col; tmat = (Z **)m->body;
1207: wmat = (int **)almat(row,col);
1208:
1209: row0 = (int **)ALLOCA(row*sizeof(int *));
1210: for ( i = 0; i < row; i++ ) row0[i] = wmat[i];
1211:
1212: rowstat = (int *)MALLOC_ATOMIC(row*sizeof(int));
1213: for ( i = 0; i < row; i++ )
1214: for ( j = 0; j < col; j++ )
1215: wmat[i][j] = remqi((Q)tmat[i][j],md);
1216: rank = indep_rows_mod(wmat,row,col,md,rowstat);
1217:
1218: MKVECT(rind,rank);
1219: rib = (Z *)rind->body;
1220: for ( j = 0; j < rank; j++ ) {
1.2 noro 1221: STOZ(rowstat[j],rib[j]);
1.1 noro 1222: }
1223: *rp = rind;
1224: }
1225:
1226: /*
1227: input : a row x col matrix A
1228: A[I] <-> A[I][0]*x_0+A[I][1]*x_1+...
1229:
1230: output : [B,R,C]
1231: B : a rank(A) x col-rank(A) matrix
1232: R : a vector of length rank(A)
1233: C : a vector of length col-rank(A)
1234: RN : a vector of length rank(A) indicating useful rows
1235:
1236: B[I] <-> x_{R[I]}+B[I][0]x_{C[0]}+B[I][1]x_{C[1]}+...
1237: */
1238:
1.3 noro 1239: #if SIZEOF_LONG==8
1240: void Pgeneric_gauss_elim_mod64(NODE arg,LIST *rp)
1241: {
1242: NODE n0;
1243: MAT m,mat;
1244: VECT rind,cind,rnum;
1245: Z **tmat;
1246: mp_limb_t **wmat,**row0;
1247: Z *rib,*cib,*rnb;
1248: int *colstat;
1249: mp_limb_t *p;
1250: Z q;
1251: mp_limb_t md;
1252: int i,j,k,l,row,col,t,rank;
1.10 noro 1253: Obj val;
1254: int asis = 0;
1.3 noro 1255:
1256: asir_assert(ARG0(arg),O_MAT,"generic_gauss_elim_mod64");
1257: asir_assert(ARG1(arg),O_N,"generic_gauss_elim_mod64");
1.10 noro 1258: if ( get_opt("asis",&val) && val ) asis = 1;
1.3 noro 1259: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1260: row = m->row; col = m->col; tmat = (Z **)m->body;
1261: wmat = (mp_limb_t **)almat64(row,col);
1262:
1263: row0 = (mp_limb_t **)ALLOCA(row*sizeof(mp_limb_t *));
1264: for ( i = 0; i < row; i++ ) row0[i] = wmat[i];
1265:
1266: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1267: for ( i = 0; i < row; i++ )
1268: for ( j = 0; j < col; j++ )
1269: wmat[i][j] = remqi64((Q)tmat[i][j],md);
1270: rank = generic_gauss_elim_mod64(wmat,row,col,md,colstat);
1.10 noro 1271: if ( asis ) {
1.11 ! noro 1272: MKMAT(mat,rank,col);
1.10 noro 1273: tmat = (Z **)mat->body;
1274: for ( i = 0; i < rank; i++ )
1275: for ( j = 0; j < col; j++ ) {
1276: UTOZ(wmat[i][j],tmat[i][j]);
1277: }
1278: *rp = (LIST)mat;
1279: return;
1280: }
1.3 noro 1281:
1282: MKVECT(rnum,rank);
1283: rnb = (Z *)rnum->body;
1284: for ( i = 0; i < rank; i++ )
1285: for ( j = 0, p = wmat[i]; j < row; j++ )
1286: if ( p == row0[j] )
1287: STOZ(j,rnb[i]);
1288:
1289: MKMAT(mat,rank,col-rank);
1290: tmat = (Z **)mat->body;
1291: for ( i = 0; i < rank; i++ )
1292: for ( j = k = 0; j < col; j++ )
1293: if ( !colstat[j] ) {
1294: UTOZ(wmat[i][j],tmat[i][k]); k++;
1295: }
1296:
1297: MKVECT(rind,rank);
1298: MKVECT(cind,col-rank);
1299: rib = (Z *)rind->body; cib = (Z *)cind->body;
1300: for ( j = k = l = 0; j < col; j++ )
1301: if ( colstat[j] ) {
1302: STOZ(j,rib[k]); k++;
1303: } else {
1304: STOZ(j,cib[l]); l++;
1305: }
1306: n0 = mknode(4,mat,rind,cind,rnum);
1307: MKLIST(*rp,n0);
1308: }
1309: #endif
1310:
1.1 noro 1311: void Pgeneric_gauss_elim_mod(NODE arg,LIST *rp)
1312: {
1313: NODE n0;
1314: MAT m,mat;
1315: VECT rind,cind,rnum;
1316: Z **tmat;
1317: int **wmat,**row0;
1318: Z *rib,*cib,*rnb;
1319: int *colstat,*p;
1320: Z q;
1.3 noro 1321: long mdl;
1.1 noro 1322: int md,i,j,k,l,row,col,t,rank;
1.10 noro 1323: Obj val;
1324: int asis = 0;
1.1 noro 1325:
1326: asir_assert(ARG0(arg),O_MAT,"generic_gauss_elim_mod");
1327: asir_assert(ARG1(arg),O_N,"generic_gauss_elim_mod");
1.10 noro 1328: if ( get_opt("asis",&val) && val ) asis = 1;
1.3 noro 1329: #if SIZEOF_LONG==8
1330: mdl = ZTOS((Z)ARG1(arg));
1331: if ( mdl >= ((mp_limb_t)1)<<32 ) {
1332: Pgeneric_gauss_elim_mod64(arg,rp);
1333: return;
1334: }
1335: #endif
1336: m = (MAT)ARG0(arg);
1337: md = ZTOS((Z)ARG1(arg));
1.1 noro 1338: row = m->row; col = m->col; tmat = (Z **)m->body;
1339: wmat = (int **)almat(row,col);
1340:
1341: row0 = (int **)ALLOCA(row*sizeof(int *));
1342: for ( i = 0; i < row; i++ ) row0[i] = wmat[i];
1343:
1344: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1345: for ( i = 0; i < row; i++ )
1346: for ( j = 0; j < col; j++ )
1347: wmat[i][j] = remqi((Q)tmat[i][j],md);
1348: rank = generic_gauss_elim_mod(wmat,row,col,md,colstat);
1.10 noro 1349: if ( asis ) {
1.11 ! noro 1350: MKMAT(mat,rank,col);
1.10 noro 1351: tmat = (Z **)mat->body;
1352: for ( i = 0; i < rank; i++ )
1353: for ( j = 0; j < col; j++ ) {
1354: UTOZ(wmat[i][j],tmat[i][j]);
1355: }
1356: *rp = (LIST)mat;
1357: return;
1358: }
1.1 noro 1359:
1360: MKVECT(rnum,rank);
1361: rnb = (Z *)rnum->body;
1362: for ( i = 0; i < rank; i++ )
1363: for ( j = 0, p = wmat[i]; j < row; j++ )
1364: if ( p == row0[j] )
1.2 noro 1365: STOZ(j,rnb[i]);
1.1 noro 1366:
1367: MKMAT(mat,rank,col-rank);
1368: tmat = (Z **)mat->body;
1369: for ( i = 0; i < rank; i++ )
1370: for ( j = k = 0; j < col; j++ )
1371: if ( !colstat[j] ) {
1.2 noro 1372: UTOZ(wmat[i][j],tmat[i][k]); k++;
1.1 noro 1373: }
1374:
1375: MKVECT(rind,rank);
1376: MKVECT(cind,col-rank);
1377: rib = (Z *)rind->body; cib = (Z *)cind->body;
1378: for ( j = k = l = 0; j < col; j++ )
1379: if ( colstat[j] ) {
1.2 noro 1380: STOZ(j,rib[k]); k++;
1.1 noro 1381: } else {
1.2 noro 1382: STOZ(j,cib[l]); l++;
1.1 noro 1383: }
1384: n0 = mknode(4,mat,rind,cind,rnum);
1385: MKLIST(*rp,n0);
1386: }
1387:
1.3 noro 1388:
1.1 noro 1389: void Pleqm(NODE arg,VECT *rp)
1390: {
1391: MAT m;
1392: VECT vect;
1393: pointer **mat;
1394: Z *v;
1395: Z q;
1396: int **wmat;
1397: int md,i,j,row,col,t,n,status;
1398:
1399: asir_assert(ARG0(arg),O_MAT,"leqm");
1400: asir_assert(ARG1(arg),O_N,"leqm");
1.2 noro 1401: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1.1 noro 1402: row = m->row; col = m->col; mat = m->body;
1403: wmat = (int **)almat(row,col);
1404: for ( i = 0; i < row; i++ )
1405: for ( j = 0; j < col; j++ )
1406: wmat[i][j] = remqi((Q)mat[i][j],md);
1407: status = gauss_elim_mod(wmat,row,col,md);
1408: if ( status < 0 )
1409: *rp = 0;
1410: else if ( status > 0 )
1411: *rp = (VECT)ONE;
1412: else {
1413: n = col - 1;
1414: MKVECT(vect,n);
1415: for ( i = 0, v = (Z *)vect->body; i < n; i++ ) {
1.2 noro 1416: t = (md-wmat[i][n])%md; STOZ(t,v[i]);
1.1 noro 1417: }
1418: *rp = vect;
1419: }
1420: }
1421:
1422: int gauss_elim_mod(int **mat,int row,int col,int md)
1423: {
1424: int i,j,k,inv,a,n;
1425: int *t,*pivot;
1426:
1427: n = col - 1;
1428: for ( j = 0; j < n; j++ ) {
1429: for ( i = j; i < row && !mat[i][j]; i++ );
1430: if ( i == row )
1431: return 1;
1432: if ( i != j ) {
1433: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
1434: }
1435: pivot = mat[j];
1436: inv = invm(pivot[j],md);
1437: for ( k = j; k <= n; k++ ) {
1438: /* pivot[k] = dmar(pivot[k],inv,0,md); */
1439: DMAR(pivot[k],inv,0,md,pivot[k])
1440: }
1441: for ( i = 0; i < row; i++ ) {
1442: t = mat[i];
1443: if ( i != j && (a = t[j]) )
1444: for ( k = j, a = md - a; k <= n; k++ ) {
1445: unsigned int tk;
1446: /* t[k] = dmar(pivot[k],a,t[k],md); */
1447: DMAR(pivot[k],a,t[k],md,tk)
1448: t[k] = tk;
1449: }
1450: }
1451: }
1452: for ( i = n; i < row && !mat[i][n]; i++ );
1453: if ( i == row )
1454: return 0;
1455: else
1456: return -1;
1457: }
1458:
1.7 noro 1459: struct oEGT eg_mod,eg_elim,eg_elim1,eg_elim2,eg_chrem,eg_gschk,eg_intrat,eg_symb,eg_back,eg_fore;
1.1 noro 1460: struct oEGT eg_conv;
1461:
1462: #if 0
1463: void lu_dec_cr(MAT mat,MAT lu,Q *dn,int **perm);
1464:
1465: /* XXX broken */
1466: void lu_dec_cr(MAT mat,MAT lu,Q *dn,int **perm)
1467: {
1468: Q **a0,**b;
1469: Q *aiq;
1470: N **a;
1471: N *ai;
1472: Q q,q1,dn2,a1,q0,bik;
1473: MAT m;
1474: unsigned int md;
1475: int n,ind,i,j,rank,t,inv,t1,ret,min,k;
1476: int **w;
1477: int *wi,*rinfo0,*rinfo;
1478: N m1,m2,m3,u,s;
1479:
1480: a0 = (Q **)mat->body;
1481: n = mat->row;
1482: if ( n != mat->col )
1483: error("lu_dec_cr : non-square matrix");
1484: w = (int **)almat(n,n);
1485: MKMAT(m,n,n);
1486: a = (N **)m->body;
1487: UTON(1,m1);
1488: rinfo0 = 0;
1489: ind = 0;
1490: while ( 1 ) {
1491: md = get_lprime(ind);
1492: /* mat mod md */
1493: for ( i = 0; i < n; i++ )
1494: for ( j = 0, aiq = a0[i], wi = w[i]; j < n; j++ )
1495: if ( q = aiq[j] ) {
1496: t = rem(NM(q),md);
1497: if ( t && SGN(q) < 0 )
1498: t = (md - t) % md;
1499: wi[j] = t;
1500: } else
1501: wi[j] = 0;
1502:
1503: if ( !lu_mod((unsigned int **)w,n,md,&rinfo) ) continue;
1504: printf("."); fflush(stdout);
1505: if ( !rinfo0 )
1506: *perm = rinfo0 = rinfo;
1507: else {
1508: for ( i = 0; i < n; i++ )
1509: if ( rinfo[i] != rinfo0[i] ) break;
1510: if ( i < n ) continue;
1511: }
1512: if ( UNIN(m1) ) {
1513: for ( i = 0; i < n; i++ )
1514: for ( j = 0, ai = a[i], wi = w[i]; j < n; j++ ) {
1515: UTON(wi[j],u); ai[j] = u;
1516: }
1517: UTON(md,m1);
1518: } else {
1519: inv = invm(rem(m1,md),md);
1520: UTON(md,m2); muln(m1,m2,&m3);
1521: for ( i = 0; i < n; i++ )
1522: for ( j = 0, ai = a[i], wi = w[i]; j < n; j++ )
1523: if ( ai[i] ) {
1524: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
1525: t = rem(ai[j],md);
1526: if ( wi[j] >= t )
1527: t = wi[j]-t;
1528: else
1529: t = md-(t-wi[j]);
1530: DMAR(t,inv,0,md,t1)
1531: UTON(t1,u);
1532: muln(m1,u,&s);
1533: addn(ai[j],s,&u); ai[j] = u;
1534: } else if ( wi[j] ) {
1535: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
1536: DMAR(wi[j],inv,0,md,t)
1537: UTON(t,u);
1538: muln(m1,u,&s); ai[j] = s;
1539: }
1540: m1 = m3;
1541: }
1542: if ( (++ind%8) == 0 ) {
1543: ret = intmtoratm(m,m1,lu,dn);
1544: if ( ret ) {
1545: b = (Q **)lu->body;
1546: mulq(*dn,*dn,&dn2);
1547: for ( i = 0; i < n; i++ ) {
1548: for ( j = 0; j < n; j++ ) {
1549: q = 0;
1550: min = MIN(i,j);
1551: for ( k = 0; k <= min; k++ ) {
1552: bik = k==i ? *dn : b[i][k];
1553: mulq(bik,b[k][j],&q0);
1554: addq(q,q0,&q1); q = q1;
1555: }
1556: mulq(a0[rinfo0[i]][j],dn2,&q1);
1557: if ( cmpq(q,q1) ) break;
1558: }
1559: if ( j < n ) break;
1560: }
1561: if ( i == n )
1562: return;
1563: }
1564: }
1565: }
1566: }
1567: #endif
1568:
1569:
1570: int f4_nocheck;
1571:
1.8 noro 1572: #define ONE_STEP1 if ( ( zzz = *s ) != 0 ) { DMAR(zzz,hc,*tj,md,*tj) } tj++; s++;
1.1 noro 1573:
1574: void reduce_reducers_mod(int **mat,int row,int col,int md)
1575: {
1576: int i,j,k,l,hc,zzz;
1577: int *t,*s,*tj,*ind;
1578:
1579: /* reduce the reducers */
1580: ind = (int *)ALLOCA(row*sizeof(int));
1581: for ( i = 0; i < row; i++ ) {
1582: t = mat[i];
1583: for ( j = 0; j < col && !t[j]; j++ );
1584: /* register the position of the head term */
1585: ind[i] = j;
1586: for ( l = i-1; l >= 0; l-- ) {
1587: /* reduce mat[i] by mat[l] */
1.8 noro 1588: if ( ( hc = t[ind[l]] ) != 0 ) {
1.1 noro 1589: /* mat[i] = mat[i]-hc*mat[l] */
1590: j = ind[l];
1591: s = mat[l]+j;
1592: tj = t+j;
1593: hc = md-hc;
1594: k = col-j;
1595: for ( ; k >= 64; k -= 64 ) {
1596: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1597: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1598: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1599: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1600: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1601: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1602: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1603: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1604: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1605: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1606: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1607: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1608: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1609: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1610: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1611: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1612: }
1613: for ( ; k > 0; k-- ) {
1.8 noro 1614: if ( ( zzz = *s ) != 0 ) { DMAR(zzz,hc,*tj,md,*tj) } tj++; s++;
1.1 noro 1615: }
1616: }
1617: }
1618: }
1619: }
1620:
1621: /*
1622: mat[i] : reducers (i=0,...,nred-1)
1623: spolys (i=nred,...,row-1)
1624: mat[0] < mat[1] < ... < mat[nred-1] w.r.t the term order
1625: 1. reduce the reducers
1626: 2. reduce spolys by the reduced reducers
1627: */
1628:
1629: void pre_reduce_mod(int **mat,int row,int col,int nred,int md)
1630: {
1631: int i,j,k,l,hc,inv;
1632: int *t,*s,*tk,*ind;
1633:
1634: #if 1
1635: /* reduce the reducers */
1636: ind = (int *)ALLOCA(row*sizeof(int));
1637: for ( i = 0; i < nred; i++ ) {
1638: /* make mat[i] monic and mat[i] by mat[0],...,mat[i-1] */
1639: t = mat[i];
1640: for ( j = 0; j < col && !t[j]; j++ );
1641: /* register the position of the head term */
1642: ind[i] = j;
1643: inv = invm(t[j],md);
1644: for ( k = j; k < col; k++ )
1645: if ( t[k] )
1646: DMAR(t[k],inv,0,md,t[k])
1647: for ( l = i-1; l >= 0; l-- ) {
1648: /* reduce mat[i] by mat[l] */
1.8 noro 1649: if ( ( hc = t[ind[l]] ) != 0 ) {
1.1 noro 1650: /* mat[i] = mat[i]-hc*mat[l] */
1651: for ( k = ind[l], hc = md-hc, s = mat[l]+k, tk = t+k;
1652: k < col; k++, tk++, s++ )
1653: if ( *s )
1654: DMAR(*s,hc,*tk,md,*tk)
1655: }
1656: }
1657: }
1658: /* reduce the spolys */
1659: for ( i = nred; i < row; i++ ) {
1660: t = mat[i];
1661: for ( l = nred-1; l >= 0; l-- ) {
1662: /* reduce mat[i] by mat[l] */
1.8 noro 1663: if ( ( hc = t[ind[l]] ) != 0 ) {
1.1 noro 1664: /* mat[i] = mat[i]-hc*mat[l] */
1665: for ( k = ind[l], hc = md-hc, s = mat[l]+k, tk = t+k;
1666: k < col; k++, tk++, s++ )
1667: if ( *s )
1668: DMAR(*s,hc,*tk,md,*tk)
1669: }
1670: }
1671: }
1672: #endif
1673: }
1674: /*
1675: mat[i] : reducers (i=0,...,nred-1)
1676: mat[0] < mat[1] < ... < mat[nred-1] w.r.t the term order
1677: */
1678:
1679: void reduce_sp_by_red_mod(int *sp,int **redmat,int *ind,int nred,int col,int md)
1680: {
1681: int i,j,k,hc,zzz;
1682: int *s,*tj;
1683:
1684: /* reduce the spolys by redmat */
1685: for ( i = nred-1; i >= 0; i-- ) {
1686: /* reduce sp by redmat[i] */
1.8 noro 1687: if ( ( hc = sp[ind[i]] ) != 0 ) {
1.1 noro 1688: /* sp = sp-hc*redmat[i] */
1689: j = ind[i];
1690: hc = md-hc;
1691: s = redmat[i]+j;
1692: tj = sp+j;
1693: for ( k = col-j; k > 0; k-- ) {
1.8 noro 1694: if ( ( zzz = *s ) != 0 ) { DMAR(zzz,hc,*tj,md,*tj) } tj++; s++;
1.1 noro 1695: }
1696: }
1697: }
1698: }
1699:
1700: /*
1701: mat[i] : compressed reducers (i=0,...,nred-1)
1702: mat[0] < mat[1] < ... < mat[nred-1] w.r.t the term order
1703: */
1704:
1705: void red_by_compress(int m,unsigned int *p,unsigned int *r,
1706: unsigned int *ri,unsigned int hc,int len)
1707: {
1708: unsigned int up,lo;
1709: unsigned int dmy;
1710: unsigned int *pj;
1711:
1712: p[*ri] = 0; r++; ri++;
1713: for ( len--; len; len--, r++, ri++ ) {
1714: pj = p+ *ri;
1715: DMA(*r,hc,*pj,up,lo);
1716: if ( up ) {
1717: DSAB(m,up,lo,dmy,*pj);
1718: } else
1719: *pj = lo;
1720: }
1721: }
1722:
1723: /* p -= hc*r */
1724:
1725: void red_by_vect(int m,unsigned int *p,unsigned int *r,unsigned int hc,int len)
1726: {
1727: unsigned int up,lo,dmy;
1728:
1729: *p++ = 0; r++; len--;
1730: for ( ; len; len--, r++, p++ )
1731: if ( *r ) {
1732: DMA(*r,hc,*p,up,lo);
1733: if ( up ) {
1734: DSAB(m,up,lo,dmy,*p);
1735: } else
1736: *p = lo;
1737: }
1738: }
1739:
1.3 noro 1740: #if SIZEOF_LONG==8
1741: /* mp_limb_t vector += U32 vector(normalized)*U32 */
1.1 noro 1742:
1.3 noro 1743: void red_by_vect64(int m, mp_limb_t *p,unsigned int *c,mp_limb_t *r,unsigned int hc,int len)
1.1 noro 1744: {
1.3 noro 1745: mp_limb_t t;
1.1 noro 1746:
1747: /* (p[0],c[0]) is normalized */
1748: *p++ = 0; *c++ = 0; r++; len--;
1749: for ( ; len; len--, r++, p++, c++ )
1750: if ( *r ) {
1751: t = (*p)+(*r)*hc;
1752: if ( t < *p ) (*c)++;
1753: *p = t;
1754: }
1755: }
1.3 noro 1756:
1757: /* mp_limb_t vector = (mp_limb_t vector+mp_limb_t vector*mp_limb_t)%mp_limb_t */
1758:
1759: void red_by_vect64mod(mp_limb_t m, mp_limb_t *p,mp_limb_t *r,mp_limb_t hc,int len)
1760: {
1761: *p++ = 0; r++; len--;
1762: for ( ; len; len--, r++, p++ )
1763: if ( *r )
1764: *p = muladdmod64(*r,hc,*p,m);
1765: }
1766:
1767: int generic_gauss_elim_mod64(mp_limb_t **mat,int row,int col,mp_limb_t md,int *colstat)
1768: {
1769: int i,j,k,l,rank;
1770: mp_limb_t inv,a;
1771: mp_limb_t *t,*pivot,*pk;
1772:
1773: for ( rank = 0, j = 0; j < col; j++ ) {
1774: for ( i = rank; i < row; i++ )
1775: if ( mat[i][j] )
1776: break;
1777: if ( i == row ) {
1778: colstat[j] = 0;
1779: continue;
1780: } else
1781: colstat[j] = 1;
1782: if ( i != rank ) {
1783: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
1784: }
1785: pivot = mat[rank];
1786: inv = invmod64(pivot[j],md);
1787: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
1788: if ( *pk )
1789: *pk = mulmod64(*pk,inv,md);
1790: for ( i = rank+1; i < row; i++ ) {
1791: t = mat[i];
1.8 noro 1792: if ( ( a = t[j] ) != 0 )
1.3 noro 1793: red_by_vect64mod(md,t+j,pivot+j,md-a,col-j);
1794: }
1795: rank++;
1796: }
1797: for ( j = col-1, l = rank-1; j >= 0; j-- )
1798: if ( colstat[j] ) {
1799: pivot = mat[l];
1800: for ( i = 0; i < l; i++ ) {
1801: t = mat[i];
1.8 noro 1802: if ( ( a = t[j] ) != 0 )
1.3 noro 1803: red_by_vect64mod(md,t+j,pivot+j,md-a,col-j);
1804: }
1805: l--;
1806: }
1807: return rank;
1808: }
1809:
1.4 noro 1810: int find_lhs_and_lu_mod64(mp_limb_t **a,int row,int col,
1811: mp_limb_t md,int **rinfo,int **cinfo)
1812: {
1813: int i,j,k,d;
1814: int *rp,*cp;
1815: mp_limb_t *t,*pivot;
1816: mp_limb_t inv,m;
1817:
1818: *rinfo = rp = (int *)MALLOC_ATOMIC(row*sizeof(int));
1819: *cinfo = cp = (int *)MALLOC_ATOMIC(col*sizeof(int));
1820: for ( i = 0; i < row; i++ )
1821: rp[i] = i;
1822: for ( k = 0, d = 0; k < col; k++ ) {
1823: for ( i = d; i < row && !a[i][k]; i++ );
1824: if ( i == row ) {
1825: cp[k] = 0;
1826: continue;
1827: } else
1828: cp[k] = 1;
1829: if ( i != d ) {
1830: j = rp[i]; rp[i] = rp[d]; rp[d] = j;
1831: t = a[i]; a[i] = a[d]; a[d] = t;
1832: }
1833: pivot = a[d];
1834: pivot[k] = inv = invmod64(pivot[k],md);
1835: for ( i = d+1; i < row; i++ ) {
1836: t = a[i];
1837: if ( (m = t[k]) != 0 ) {
1838: t[k] = mulmod64(inv,m,md);
1839: for ( j = k+1, m = md - t[k]; j < col; j++ )
1840: if ( pivot[j] ) {
1841: t[j] = muladdmod64(m,pivot[j],t[j],md);
1842: }
1843: }
1844: }
1845: d++;
1846: }
1847: return d;
1848: }
1849:
1850: int lu_mod64(mp_limb_t **a,int n,mp_limb_t md,int **rinfo)
1851: {
1852: int i,j,k;
1853: int *rp;
1854: mp_limb_t *t,*pivot;
1855: mp_limb_t inv,m;
1856:
1857: *rinfo = rp = (int *)MALLOC_ATOMIC(n*sizeof(int));
1858: for ( i = 0; i < n; i++ ) rp[i] = i;
1859: for ( k = 0; k < n; k++ ) {
1860: for ( i = k; i < n && !a[i][k]; i++ );
1861: if ( i == n ) return 0;
1862: if ( i != k ) {
1863: j = rp[i]; rp[i] = rp[k]; rp[k] = j;
1864: t = a[i]; a[i] = a[k]; a[k] = t;
1865: }
1866: pivot = a[k];
1867: inv = invmod64(pivot[k],md);
1868: for ( i = k+1; i < n; i++ ) {
1869: t = a[i];
1870: if ( (m = t[k]) != 0 ) {
1871: t[k] = mulmod64(inv,m,md);
1872: for ( j = k+1, m = md - t[k]; j < n; j++ )
1873: if ( pivot[j] ) {
1874: t[j] = muladdmod64(m,pivot[j],t[j],md);
1875: }
1876: }
1877: }
1878: }
1879: return 1;
1880: }
1881:
1882: /*
1883: Input
1884: a : n x n matrix; a result of LU-decomposition
1885: md : modulus
1886: b : n x l matrix
1887: Output
1888: b = a^(-1)b
1889: */
1890:
1891: void solve_by_lu_mod64(mp_limb_t **a,int n,mp_limb_t md,mp_limb_signed_t **b,int l,int normalize)
1892: {
1893: mp_limb_t *y,*c;
1894: int i,j,k;
1895: mp_limb_t t,m,m2;
1896:
1897: y = (mp_limb_t *)MALLOC_ATOMIC(n*sizeof(mp_limb_t));
1898: c = (mp_limb_t *)MALLOC_ATOMIC(n*sizeof(mp_limb_t));
1899: m2 = md/2;
1900: for ( k = 0; k < l; k++ ) {
1901: /* copy b[.][k] to c */
1902: for ( i = 0; i < n; i++ )
1903: c[i] = b[i][k];
1904: /* solve Ly=c */
1905: for ( i = 0; i < n; i++ ) {
1906: for ( t = c[i], j = 0; j < i; j++ )
1907: if ( a[i][j] ) {
1908: m = md - a[i][j];
1909: t = muladdmod64(m,y[j],t,md);
1910: }
1911: y[i] = t;
1912: }
1913: /* solve Uc=y */
1914: for ( i = n-1; i >= 0; i-- ) {
1915: for ( t = y[i], j =i+1; j < n; j++ )
1916: if ( a[i][j] ) {
1917: m = md - a[i][j];
1918: t = muladdmod64(m,c[j],t,md);
1919: }
1920: /* a[i][i] = 1/U[i][i] */
1921: c[i] = mulmod64(t,a[i][i],md);
1922: }
1923: /* copy c to b[.][k] with normalization */
1924: if ( normalize )
1925: for ( i = 0; i < n; i++ )
1926: b[i][k] = (mp_limb_signed_t)(c[i]>m2 ? c[i]-md : c[i]);
1927: else
1928: for ( i = 0; i < n; i++ )
1929: b[i][k] = (mp_limb_signed_t)c[i];
1930: }
1931: }
1.1 noro 1932: #endif
1933:
1934: void red_by_vect_sf(int m,unsigned int *p,unsigned int *r,unsigned int hc,int len)
1935: {
1936: *p++ = 0; r++; len--;
1937: for ( ; len; len--, r++, p++ )
1938: if ( *r )
1939: *p = _addsf(_mulsf(*r,hc),*p);
1940: }
1941:
1942: extern Z current_mod_lf;
1943: extern int current_mod_lf_size;
1944:
1945: void red_by_vect_lf(mpz_t *p,mpz_t *r,mpz_t hc,int len)
1946: {
1947: mpz_set_ui(*p++,0); r++; len--;
1948: for ( ; len; len--, r++, p++ ) {
1949: mpz_addmul(*p,*r,hc);
1950: #if 0
1951: if ( mpz_size(*p) > current_mod_lf_size )
1952: mpz_mod(*p,*p,BDY(current_mod_lf));
1953: #endif
1954: }
1955: }
1956:
1957:
1958: extern unsigned int **psca;
1959:
1960: void reduce_sp_by_red_mod_compress (int *sp,CDP *redmat,int *ind,
1961: int nred,int col,int md)
1962: {
1963: int i,len;
1964: CDP ri;
1965: unsigned int hc;
1966: unsigned int *usp;
1967:
1968: usp = (unsigned int *)sp;
1969: /* reduce the spolys by redmat */
1970: for ( i = nred-1; i >= 0; i-- ) {
1971: /* reduce sp by redmat[i] */
1972: usp[ind[i]] %= md;
1.8 noro 1973: if ( ( hc = usp[ind[i]] ) != 0 ) {
1.1 noro 1974: /* sp = sp-hc*redmat[i] */
1975: hc = md-hc;
1976: ri = redmat[i];
1977: len = ri->len;
1978: red_by_compress(md,usp,psca[ri->psindex],ri->body,hc,len);
1979: }
1980: }
1981: for ( i = 0; i < col; i++ )
1982: if ( usp[i] >= (unsigned int)md )
1983: usp[i] %= md;
1984: }
1985:
1986: #define ONE_STEP2 if ( zzz = *pk ) { DMAR(zzz,a,*tk,md,*tk) } pk++; tk++;
1987:
1988: int generic_gauss_elim_mod(int **mat0,int row,int col,int md,int *colstat)
1989: {
1990: int i,j,k,l,inv,a,rank;
1991: unsigned int *t,*pivot,*pk;
1992: unsigned int **mat;
1993:
1994: mat = (unsigned int **)mat0;
1995: for ( rank = 0, j = 0; j < col; j++ ) {
1996: for ( i = rank; i < row; i++ )
1997: mat[i][j] %= md;
1998: for ( i = rank; i < row; i++ )
1999: if ( mat[i][j] )
2000: break;
2001: if ( i == row ) {
2002: colstat[j] = 0;
2003: continue;
2004: } else
2005: colstat[j] = 1;
2006: if ( i != rank ) {
2007: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
2008: }
2009: pivot = mat[rank];
2010: inv = invm(pivot[j],md);
2011: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
2012: if ( *pk ) {
2013: if ( *pk >= (unsigned int)md )
2014: *pk %= md;
2015: DMAR(*pk,inv,0,md,*pk)
2016: }
2017: for ( i = rank+1; i < row; i++ ) {
2018: t = mat[i];
1.8 noro 2019: if ( ( a = t[j] ) != 0 )
1.1 noro 2020: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2021: }
2022: rank++;
2023: }
2024: for ( j = col-1, l = rank-1; j >= 0; j-- )
2025: if ( colstat[j] ) {
2026: pivot = mat[l];
2027: for ( i = 0; i < l; i++ ) {
2028: t = mat[i];
2029: t[j] %= md;
1.8 noro 2030: if ( ( a = t[j] ) != 0 )
1.1 noro 2031: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2032: }
2033: l--;
2034: }
2035: for ( j = 0, l = 0; l < rank; j++ )
2036: if ( colstat[j] ) {
2037: t = mat[l];
2038: for ( k = j; k < col; k++ )
2039: if ( t[k] >= (unsigned int)md )
2040: t[k] %= md;
2041: l++;
2042: }
2043: return rank;
2044: }
2045:
2046: int generic_gauss_elim_mod2(int **mat0,int row,int col,int md,int *colstat,int *rowstat)
2047: {
2048: int i,j,k,l,inv,a,rank;
2049: unsigned int *t,*pivot,*pk;
2050: unsigned int **mat;
2051:
2052: for ( i = 0; i < row; i++ ) rowstat[i] = i;
2053: mat = (unsigned int **)mat0;
2054: for ( rank = 0, j = 0; j < col; j++ ) {
2055: for ( i = rank; i < row; i++ )
2056: mat[i][j] %= md;
2057: for ( i = rank; i < row; i++ )
2058: if ( mat[i][j] )
2059: break;
2060: if ( i == row ) {
2061: colstat[j] = 0;
2062: continue;
2063: } else
2064: colstat[j] = 1;
2065: if ( i != rank ) {
2066: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
2067: k = rowstat[i]; rowstat[i] = rowstat[rank]; rowstat[rank] = k;
2068: }
2069: pivot = mat[rank];
2070: inv = invm(pivot[j],md);
2071: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
2072: if ( *pk ) {
2073: if ( *pk >= (unsigned int)md )
2074: *pk %= md;
2075: DMAR(*pk,inv,0,md,*pk)
2076: }
2077: for ( i = rank+1; i < row; i++ ) {
2078: t = mat[i];
1.8 noro 2079: if ( ( a = t[j] ) != 0 )
1.1 noro 2080: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2081: }
2082: rank++;
2083: }
2084: for ( j = col-1, l = rank-1; j >= 0; j-- )
2085: if ( colstat[j] ) {
2086: pivot = mat[l];
2087: for ( i = 0; i < l; i++ ) {
2088: t = mat[i];
2089: t[j] %= md;
1.8 noro 2090: if ( ( a = t[j] ) != 0 )
1.1 noro 2091: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2092: }
2093: l--;
2094: }
2095: for ( j = 0, l = 0; l < rank; j++ )
2096: if ( colstat[j] ) {
2097: t = mat[l];
2098: for ( k = j; k < col; k++ )
2099: if ( t[k] >= (unsigned int)md )
2100: t[k] %= md;
2101: l++;
2102: }
2103: return rank;
2104: }
2105:
2106: int indep_rows_mod(int **mat0,int row,int col,int md,int *rowstat)
2107: {
2108: int i,j,k,l,inv,a,rank;
2109: unsigned int *t,*pivot,*pk;
2110: unsigned int **mat;
2111:
2112: for ( i = 0; i < row; i++ ) rowstat[i] = i;
2113: mat = (unsigned int **)mat0;
2114: for ( rank = 0, j = 0; j < col; j++ ) {
2115: for ( i = rank; i < row; i++ )
2116: mat[i][j] %= md;
2117: for ( i = rank; i < row; i++ )
2118: if ( mat[i][j] )
2119: break;
2120: if ( i == row ) continue;
2121: if ( i != rank ) {
2122: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
2123: k = rowstat[i]; rowstat[i] = rowstat[rank]; rowstat[rank] = k;
2124: }
2125: pivot = mat[rank];
2126: inv = invm(pivot[j],md);
2127: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
2128: if ( *pk ) {
2129: if ( *pk >= (unsigned int)md )
2130: *pk %= md;
2131: DMAR(*pk,inv,0,md,*pk)
2132: }
2133: for ( i = rank+1; i < row; i++ ) {
2134: t = mat[i];
1.8 noro 2135: if ( ( a = t[j] ) != 0 )
1.1 noro 2136: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2137: }
2138: rank++;
2139: }
2140: return rank;
2141: }
2142:
2143: int generic_gauss_elim_sf(int **mat0,int row,int col,int md,int *colstat)
2144: {
2145: int i,j,k,l,inv,a,rank;
2146: unsigned int *t,*pivot,*pk;
2147: unsigned int **mat;
2148:
2149: mat = (unsigned int **)mat0;
2150: for ( rank = 0, j = 0; j < col; j++ ) {
2151: for ( i = rank; i < row; i++ )
2152: if ( mat[i][j] )
2153: break;
2154: if ( i == row ) {
2155: colstat[j] = 0;
2156: continue;
2157: } else
2158: colstat[j] = 1;
2159: if ( i != rank ) {
2160: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
2161: }
2162: pivot = mat[rank];
2163: inv = _invsf(pivot[j]);
2164: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
2165: if ( *pk )
2166: *pk = _mulsf(*pk,inv);
2167: for ( i = rank+1; i < row; i++ ) {
2168: t = mat[i];
1.8 noro 2169: if ( ( a = t[j] ) != 0 )
1.1 noro 2170: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
2171: }
2172: rank++;
2173: }
2174: for ( j = col-1, l = rank-1; j >= 0; j-- )
2175: if ( colstat[j] ) {
2176: pivot = mat[l];
2177: for ( i = 0; i < l; i++ ) {
2178: t = mat[i];
1.8 noro 2179: if ( ( a = t[j] ) != 0 )
1.1 noro 2180: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
2181: }
2182: l--;
2183: }
2184: return rank;
2185: }
2186:
2187: /* LU decomposition; a[i][i] = 1/U[i][i] */
2188:
2189: int lu_gfmmat(GFMMAT mat,unsigned int md,int *perm)
2190: {
2191: int row,col;
2192: int i,j,k;
2193: unsigned int *t,*pivot;
2194: unsigned int **a;
2195: unsigned int inv,m;
2196:
2197: row = mat->row; col = mat->col;
2198: a = mat->body;
2199: bzero(perm,row*sizeof(int));
2200:
2201: for ( i = 0; i < row; i++ )
2202: perm[i] = i;
2203: for ( k = 0; k < col; k++ ) {
2204: for ( i = k; i < row && !a[i][k]; i++ );
2205: if ( i == row )
2206: return 0;
2207: if ( i != k ) {
2208: j = perm[i]; perm[i] = perm[k]; perm[k] = j;
2209: t = a[i]; a[i] = a[k]; a[k] = t;
2210: }
2211: pivot = a[k];
2212: pivot[k] = inv = invm(pivot[k],md);
2213: for ( i = k+1; i < row; i++ ) {
2214: t = a[i];
1.8 noro 2215: if ( ( m = t[k] ) != 0 ) {
1.1 noro 2216: DMAR(inv,m,0,md,t[k])
2217: for ( j = k+1, m = md - t[k]; j < col; j++ )
2218: if ( pivot[j] ) {
2219: unsigned int tj;
2220:
2221: DMAR(m,pivot[j],t[j],md,tj)
2222: t[j] = tj;
2223: }
2224: }
2225: }
2226: }
2227: return 1;
2228: }
2229:
2230: /*
2231: Input
2232: a: a row x col matrix
2233: md : a modulus
2234:
2235: Output:
2236: return : d = the rank of mat
2237: a[0..(d-1)][0..(d-1)] : LU decomposition (a[i][i] = 1/U[i][i])
2238: rinfo: array of length row
2239: cinfo: array of length col
2240: i-th row in new a <-> rinfo[i]-th row in old a
2241: cinfo[j]=1 <=> j-th column is contained in the LU decomp.
2242: */
2243:
2244: int find_lhs_and_lu_mod(unsigned int **a,int row,int col,
2245: unsigned int md,int **rinfo,int **cinfo)
2246: {
2247: int i,j,k,d;
2248: int *rp,*cp;
2249: unsigned int *t,*pivot;
2250: unsigned int inv,m;
2251:
2252: *rinfo = rp = (int *)MALLOC_ATOMIC(row*sizeof(int));
2253: *cinfo = cp = (int *)MALLOC_ATOMIC(col*sizeof(int));
2254: for ( i = 0; i < row; i++ )
2255: rp[i] = i;
2256: for ( k = 0, d = 0; k < col; k++ ) {
2257: for ( i = d; i < row && !a[i][k]; i++ );
2258: if ( i == row ) {
2259: cp[k] = 0;
2260: continue;
2261: } else
2262: cp[k] = 1;
2263: if ( i != d ) {
2264: j = rp[i]; rp[i] = rp[d]; rp[d] = j;
2265: t = a[i]; a[i] = a[d]; a[d] = t;
2266: }
2267: pivot = a[d];
2268: pivot[k] = inv = invm(pivot[k],md);
2269: for ( i = d+1; i < row; i++ ) {
2270: t = a[i];
1.8 noro 2271: if ( ( m = t[k] ) != 0 ) {
1.1 noro 2272: DMAR(inv,m,0,md,t[k])
2273: for ( j = k+1, m = md - t[k]; j < col; j++ )
2274: if ( pivot[j] ) {
2275: unsigned int tj;
2276: DMAR(m,pivot[j],t[j],md,tj)
2277: t[j] = tj;
2278: }
2279: }
2280: }
2281: d++;
2282: }
2283: return d;
2284: }
2285:
2286: int lu_mod(unsigned int **a,int n,unsigned int md,int **rinfo)
2287: {
2288: int i,j,k;
2289: int *rp;
2290: unsigned int *t,*pivot;
2291: unsigned int inv,m;
2292:
2293: *rinfo = rp = (int *)MALLOC_ATOMIC(n*sizeof(int));
2294: for ( i = 0; i < n; i++ ) rp[i] = i;
2295: for ( k = 0; k < n; k++ ) {
2296: for ( i = k; i < n && !a[i][k]; i++ );
2297: if ( i == n ) return 0;
2298: if ( i != k ) {
2299: j = rp[i]; rp[i] = rp[k]; rp[k] = j;
2300: t = a[i]; a[i] = a[k]; a[k] = t;
2301: }
2302: pivot = a[k];
2303: inv = invm(pivot[k],md);
2304: for ( i = k+1; i < n; i++ ) {
2305: t = a[i];
1.8 noro 2306: if ( ( m = t[k] ) != 0 ) {
1.1 noro 2307: DMAR(inv,m,0,md,t[k])
2308: for ( j = k+1, m = md - t[k]; j < n; j++ )
2309: if ( pivot[j] ) {
2310: unsigned int tj;
2311: DMAR(m,pivot[j],t[j],md,tj)
2312: t[j] = tj;
2313: }
2314: }
2315: }
2316: }
2317: return 1;
2318: }
2319:
2320: /*
2321: Input
2322: a : n x n matrix; a result of LU-decomposition
2323: md : modulus
2324: b : n x l matrix
2325: Output
2326: b = a^(-1)b
2327: */
2328:
2329: void solve_by_lu_mod(int **a,int n,int md,int **b,int l,int normalize)
2330: {
2331: unsigned int *y,*c;
2332: int i,j,k;
2333: unsigned int t,m,m2;
2334:
1.8 noro 2335: y = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
2336: c = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
1.1 noro 2337: m2 = md>>1;
2338: for ( k = 0; k < l; k++ ) {
2339: /* copy b[.][k] to c */
2340: for ( i = 0; i < n; i++ )
2341: c[i] = (unsigned int)b[i][k];
2342: /* solve Ly=c */
2343: for ( i = 0; i < n; i++ ) {
2344: for ( t = c[i], j = 0; j < i; j++ )
2345: if ( a[i][j] ) {
2346: m = md - a[i][j];
2347: DMAR(m,y[j],t,md,t)
2348: }
2349: y[i] = t;
2350: }
2351: /* solve Uc=y */
2352: for ( i = n-1; i >= 0; i-- ) {
2353: for ( t = y[i], j =i+1; j < n; j++ )
2354: if ( a[i][j] ) {
2355: m = md - a[i][j];
2356: DMAR(m,c[j],t,md,t)
2357: }
2358: /* a[i][i] = 1/U[i][i] */
2359: DMAR(t,a[i][i],0,md,c[i])
2360: }
2361: /* copy c to b[.][k] with normalization */
2362: if ( normalize )
2363: for ( i = 0; i < n; i++ )
2364: b[i][k] = (int)(c[i]>m2 ? c[i]-md : c[i]);
2365: else
2366: for ( i = 0; i < n; i++ )
2367: b[i][k] = c[i];
2368: }
2369: }
2370:
2371: void Pleqm1(NODE arg,VECT *rp)
2372: {
2373: MAT m;
2374: VECT vect;
2375: pointer **mat;
2376: Z *v;
2377: Z q;
2378: int **wmat;
2379: int md,i,j,row,col,t,n,status;
2380:
2381: asir_assert(ARG0(arg),O_MAT,"leqm1");
2382: asir_assert(ARG1(arg),O_N,"leqm1");
1.2 noro 2383: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1.1 noro 2384: row = m->row; col = m->col; mat = m->body;
2385: wmat = (int **)almat(row,col);
2386: for ( i = 0; i < row; i++ )
2387: for ( j = 0; j < col; j++ )
2388: wmat[i][j] = remqi((Q)mat[i][j],md);
2389: status = gauss_elim_mod1(wmat,row,col,md);
2390: if ( status < 0 )
2391: *rp = 0;
2392: else if ( status > 0 )
2393: *rp = (VECT)ONE;
2394: else {
2395: n = col - 1;
2396: MKVECT(vect,n);
2397: for ( i = 0, v = (Z *)vect->body; i < n; i++ ) {
1.2 noro 2398: t = (md-wmat[i][n])%md; STOZ(t,v[i]);
1.1 noro 2399: }
2400: *rp = vect;
2401: }
2402: }
2403:
2404: int gauss_elim_mod1(int **mat,int row,int col,int md)
2405: {
2406: int i,j,k,inv,a,n;
2407: int *t,*pivot;
2408:
2409: n = col - 1;
2410: for ( j = 0; j < n; j++ ) {
2411: for ( i = j; i < row && !mat[i][j]; i++ );
2412: if ( i == row )
2413: return 1;
2414: if ( i != j ) {
2415: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2416: }
2417: pivot = mat[j];
2418: inv = invm(pivot[j],md);
2419: for ( k = j; k <= n; k++ )
2420: pivot[k] = dmar(pivot[k],inv,0,md);
2421: for ( i = j+1; i < row; i++ ) {
2422: t = mat[i];
2423: if ( i != j && (a = t[j]) )
2424: for ( k = j, a = md - a; k <= n; k++ )
2425: t[k] = dmar(pivot[k],a,t[k],md);
2426: }
2427: }
2428: for ( i = n; i < row && !mat[i][n]; i++ );
2429: if ( i == row ) {
2430: for ( j = n-1; j >= 0; j-- ) {
2431: for ( i = j-1, a = (md-mat[j][n])%md; i >= 0; i-- ) {
2432: mat[i][n] = dmar(mat[i][j],a,mat[i][n],md);
2433: mat[i][j] = 0;
2434: }
2435: }
2436: return 0;
2437: } else
2438: return -1;
2439: }
2440:
2441: void Pgeninvm(NODE arg,LIST *rp)
2442: {
2443: MAT m;
2444: pointer **mat;
2445: Z **tmat;
2446: Z q;
2447: unsigned int **wmat;
2448: int md,i,j,row,col,t,status;
2449: MAT mat1,mat2;
2450: NODE node1,node2;
2451:
2452: asir_assert(ARG0(arg),O_MAT,"leqm1");
2453: asir_assert(ARG1(arg),O_N,"leqm1");
1.2 noro 2454: m = (MAT)ARG0(arg); md = ZTOS((Q)ARG1(arg));
1.1 noro 2455: row = m->row; col = m->col; mat = m->body;
2456: wmat = (unsigned int **)almat(row,col+row);
2457: for ( i = 0; i < row; i++ ) {
2458: bzero((char *)wmat[i],(col+row)*sizeof(int));
2459: for ( j = 0; j < col; j++ )
2460: wmat[i][j] = remqi((Q)mat[i][j],md);
2461: }
2462: status = gauss_elim_geninv_mod(wmat,row,col,md);
2463: if ( status > 0 )
2464: *rp = 0;
2465: else {
2466: MKMAT(mat1,col,row); MKMAT(mat2,row-col,row);
2467: for ( i = 0, tmat = (Z **)mat1->body; i < col; i++ )
2468: for ( j = 0; j < row; j++ )
1.2 noro 2469: UTOZ(wmat[i][j+col],tmat[i][j]);
1.1 noro 2470: for ( tmat = (Z **)mat2->body; i < row; i++ )
2471: for ( j = 0; j < row; j++ )
1.2 noro 2472: UTOZ(wmat[i][j+col],tmat[i-col][j]);
1.1 noro 2473: MKNODE(node2,mat2,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
2474: }
2475: }
2476:
2477: int gauss_elim_geninv_mod(unsigned int **mat,int row,int col,int md)
2478: {
2479: int i,j,k,inv,a,n,m;
2480: unsigned int *t,*pivot;
2481:
2482: n = col; m = row+col;
2483: for ( j = 0; j < n; j++ ) {
2484: for ( i = j; i < row && !mat[i][j]; i++ );
2485: if ( i == row )
2486: return 1;
2487: if ( i != j ) {
2488: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2489: }
2490: pivot = mat[j];
2491: inv = invm(pivot[j],md);
2492: for ( k = j; k < m; k++ )
2493: pivot[k] = dmar(pivot[k],inv,0,md);
2494: for ( i = j+1; i < row; i++ ) {
2495: t = mat[i];
1.8 noro 2496: if ( ( a = t[j] ) != 0 )
1.1 noro 2497: for ( k = j, a = md - a; k < m; k++ )
2498: t[k] = dmar(pivot[k],a,t[k],md);
2499: }
2500: }
2501: for ( j = n-1; j >= 0; j-- ) {
2502: pivot = mat[j];
2503: for ( i = j-1; i >= 0; i-- ) {
2504: t = mat[i];
1.8 noro 2505: if ( ( a = t[j] ) != 0 )
1.1 noro 2506: for ( k = j, a = md - a; k < m; k++ )
2507: t[k] = dmar(pivot[k],a,t[k],md);
2508: }
2509: }
2510: return 0;
2511: }
2512:
2513: void Psolve_by_lu_gfmmat(NODE arg,VECT *rp)
2514: {
2515: GFMMAT lu;
2516: Z *perm,*rhs,*v;
2517: int n,i;
2518: unsigned int md;
2519: unsigned int *b,*sol;
2520: VECT r;
2521:
2522: lu = (GFMMAT)ARG0(arg);
2523: perm = (Z *)BDY((VECT)ARG1(arg));
2524: rhs = (Z *)BDY((VECT)ARG2(arg));
1.2 noro 2525: md = (unsigned int)ZTOS((Z)ARG3(arg));
1.1 noro 2526: n = lu->col;
2527: b = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
2528: sol = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
2529: for ( i = 0; i < n; i++ )
1.2 noro 2530: b[i] = ZTOS(rhs[ZTOS(perm[i])]);
1.1 noro 2531: solve_by_lu_gfmmat(lu,md,b,sol);
2532: MKVECT(r,n);
2533: for ( i = 0, v = (Z *)r->body; i < n; i++ )
1.2 noro 2534: UTOZ(sol[i],v[i]);
1.1 noro 2535: *rp = r;
2536: }
2537:
2538: void solve_by_lu_gfmmat(GFMMAT lu,unsigned int md,
2539: unsigned int *b,unsigned int *x)
2540: {
2541: int n;
2542: unsigned int **a;
2543: unsigned int *y;
2544: int i,j;
2545: unsigned int t,m;
2546:
2547: n = lu->col;
2548: a = lu->body;
2549: y = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
2550: /* solve Ly=b */
2551: for ( i = 0; i < n; i++ ) {
2552: for ( t = b[i], j = 0; j < i; j++ )
2553: if ( a[i][j] ) {
2554: m = md - a[i][j];
2555: DMAR(m,y[j],t,md,t)
2556: }
2557: y[i] = t;
2558: }
2559: /* solve Ux=y */
2560: for ( i = n-1; i >= 0; i-- ) {
2561: for ( t = y[i], j =i+1; j < n; j++ )
2562: if ( a[i][j] ) {
2563: m = md - a[i][j];
2564: DMAR(m,x[j],t,md,t)
2565: }
2566: /* a[i][i] = 1/U[i][i] */
2567: DMAR(t,a[i][i],0,md,x[i])
2568: }
2569: }
2570:
2571: #if 0
2572: void Plu_mat(NODE arg,LIST *rp)
2573: {
2574: MAT m,lu;
2575: Q dn;
2576: Q *v;
2577: int n,i;
2578: int *iperm;
2579: VECT perm;
2580: NODE n0;
2581:
2582: asir_assert(ARG0(arg),O_MAT,"lu_mat");
2583: m = (MAT)ARG0(arg);
2584: n = m->row;
2585: MKMAT(lu,n,n);
2586: lu_dec_cr(m,lu,&dn,&iperm);
2587: MKVECT(perm,n);
2588: for ( i = 0, v = (Q *)perm->body; i < n; i++ )
1.2 noro 2589: STOZ(iperm[i],v[i]);
1.1 noro 2590: n0 = mknode(3,lu,dn,perm);
2591: MKLIST(*rp,n0);
2592: }
2593: #endif
2594:
2595: void Plu_gfmmat(NODE arg,LIST *rp)
2596: {
2597: MAT m;
2598: GFMMAT mm;
2599: unsigned int md;
2600: int i,row,col,status;
2601: int *iperm;
2602: Z *v;
2603: VECT perm;
2604: NODE n0;
2605:
2606: asir_assert(ARG0(arg),O_MAT,"lu_gfmmat");
2607: asir_assert(ARG1(arg),O_N,"lu_gfmmat");
1.2 noro 2608: m = (MAT)ARG0(arg); md = (unsigned int)ZTOS((Q)ARG1(arg));
1.1 noro 2609: mat_to_gfmmat(m,md,&mm);
2610: row = m->row;
2611: col = m->col;
2612: iperm = (int *)MALLOC_ATOMIC(row*sizeof(int));
2613: status = lu_gfmmat(mm,md,iperm);
2614: if ( !status )
2615: n0 = 0;
2616: else {
2617: MKVECT(perm,row);
2618: for ( i = 0, v = (Z *)perm->body; i < row; i++ )
1.2 noro 2619: STOZ(iperm[i],v[i]);
1.1 noro 2620: n0 = mknode(2,mm,perm);
2621: }
2622: MKLIST(*rp,n0);
2623: }
2624:
2625: void Pmat_to_gfmmat(NODE arg,GFMMAT *rp)
2626: {
2627: MAT m;
2628: unsigned int md;
2629:
2630: asir_assert(ARG0(arg),O_MAT,"mat_to_gfmmat");
2631: asir_assert(ARG1(arg),O_N,"mat_to_gfmmat");
1.2 noro 2632: m = (MAT)ARG0(arg); md = (unsigned int)ZTOS((Q)ARG1(arg));
1.1 noro 2633: mat_to_gfmmat(m,md,rp);
2634: }
2635:
2636: void mat_to_gfmmat(MAT m,unsigned int md,GFMMAT *rp)
2637: {
2638: unsigned int **wmat;
2639: unsigned int t;
2640: Z **mat;
2641: Z q;
2642: int i,j,row,col;
2643:
2644: row = m->row; col = m->col; mat = (Z **)m->body;
2645: wmat = (unsigned int **)almat(row,col);
2646: for ( i = 0; i < row; i++ ) {
2647: bzero((char *)wmat[i],col*sizeof(unsigned int));
2648: for ( j = 0; j < col; j++ )
2649: wmat[i][j] = remqi((Q)mat[i][j],md);
2650: }
2651: TOGFMMAT(row,col,wmat,*rp);
2652: }
2653:
2654: void Pgeninvm_swap(NODE arg,LIST *rp)
2655: {
2656: MAT m;
2657: pointer **mat;
2658: Z **tmat;
2659: Z *tvect;
2660: Z q;
2661: unsigned int **wmat,**invmat;
2662: int *index;
2663: unsigned int t,md;
2664: int i,j,row,col,status;
2665: MAT mat1;
2666: VECT vect1;
2667: NODE node1,node2;
2668:
2669: asir_assert(ARG0(arg),O_MAT,"geninvm_swap");
2670: asir_assert(ARG1(arg),O_N,"geninvm_swap");
1.2 noro 2671: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1.1 noro 2672: row = m->row; col = m->col; mat = m->body;
2673: wmat = (unsigned int **)almat(row,col+row);
2674: for ( i = 0; i < row; i++ ) {
2675: bzero((char *)wmat[i],(col+row)*sizeof(int));
2676: for ( j = 0; j < col; j++ )
2677: wmat[i][j] = remqi((Q)mat[i][j],md);
2678: wmat[i][col+i] = 1;
2679: }
2680: status = gauss_elim_geninv_mod_swap(wmat,row,col,md,&invmat,&index);
2681: if ( status > 0 )
2682: *rp = 0;
2683: else {
2684: MKMAT(mat1,col,col);
2685: for ( i = 0, tmat = (Z **)mat1->body; i < col; i++ )
2686: for ( j = 0; j < col; j++ )
1.2 noro 2687: UTOZ(invmat[i][j],tmat[i][j]);
1.1 noro 2688: MKVECT(vect1,row);
2689: for ( i = 0, tvect = (Z *)vect1->body; i < row; i++ )
1.2 noro 2690: STOZ(index[i],tvect[i]);
1.1 noro 2691: MKNODE(node2,vect1,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
2692: }
2693: }
2694:
2695: int gauss_elim_geninv_mod_swap(unsigned int **mat,int row,int col,unsigned int md,
2696: unsigned int ***invmatp,int **indexp)
2697: {
2698: int i,j,k,inv,a,n,m;
2699: unsigned int *t,*pivot,*s;
2700: int *index;
2701: unsigned int **invmat;
2702:
2703: n = col; m = row+col;
2704: *indexp = index = (int *)MALLOC_ATOMIC(row*sizeof(int));
2705: for ( i = 0; i < row; i++ )
2706: index[i] = i;
2707: for ( j = 0; j < n; j++ ) {
2708: for ( i = j; i < row && !mat[i][j]; i++ );
2709: if ( i == row ) {
2710: *indexp = 0; *invmatp = 0; return 1;
2711: }
2712: if ( i != j ) {
2713: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2714: k = index[i]; index[i] = index[j]; index[j] = k;
2715: }
2716: pivot = mat[j];
2717: inv = (unsigned int)invm(pivot[j],md);
2718: for ( k = j; k < m; k++ )
2719: if ( pivot[k] )
2720: pivot[k] = (unsigned int)dmar(pivot[k],inv,0,md);
2721: for ( i = j+1; i < row; i++ ) {
2722: t = mat[i];
1.8 noro 2723: if ( ( a = t[j] ) != 0 )
1.1 noro 2724: for ( k = j, a = md - a; k < m; k++ )
2725: if ( pivot[k] )
2726: t[k] = dmar(pivot[k],a,t[k],md);
2727: }
2728: }
2729: for ( j = n-1; j >= 0; j-- ) {
2730: pivot = mat[j];
2731: for ( i = j-1; i >= 0; i-- ) {
2732: t = mat[i];
1.8 noro 2733: if ( ( a = t[j] ) != 0 )
1.1 noro 2734: for ( k = j, a = md - a; k < m; k++ )
2735: if ( pivot[k] )
2736: t[k] = dmar(pivot[k],a,t[k],md);
2737: }
2738: }
2739: *invmatp = invmat = (unsigned int **)almat(col,col);
2740: for ( i = 0; i < col; i++ )
2741: for ( j = 0, s = invmat[i], t = mat[i]; j < col; j++ )
2742: s[j] = t[col+index[j]];
2743: return 0;
2744: }
2745:
2746: int gauss_elim_geninv_sf_swap(int **mat,int row,int col, int ***invmatp,int **indexp);
2747:
2748: void Pgeninv_sf_swap(NODE arg,LIST *rp)
2749: {
2750: MAT m;
2751: GFS **mat,**tmat;
2752: Z *tvect;
2753: GFS q;
2754: int **wmat,**invmat;
2755: int *index;
2756: unsigned int t;
2757: int i,j,row,col,status;
2758: MAT mat1;
2759: VECT vect1;
2760: NODE node1,node2;
2761:
2762: asir_assert(ARG0(arg),O_MAT,"geninv_sf_swap");
2763: m = (MAT)ARG0(arg);
2764: row = m->row; col = m->col; mat = (GFS **)m->body;
2765: wmat = (int **)almat(row,col+row);
2766: for ( i = 0; i < row; i++ ) {
2767: bzero((char *)wmat[i],(col+row)*sizeof(int));
2768: for ( j = 0; j < col; j++ )
1.8 noro 2769: if ( ( q = (GFS)mat[i][j] ) != 0 )
1.1 noro 2770: wmat[i][j] = FTOIF(CONT(q));
2771: wmat[i][col+i] = _onesf();
2772: }
2773: status = gauss_elim_geninv_sf_swap(wmat,row,col,&invmat,&index);
2774: if ( status > 0 )
2775: *rp = 0;
2776: else {
2777: MKMAT(mat1,col,col);
2778: for ( i = 0, tmat = (GFS **)mat1->body; i < col; i++ )
2779: for ( j = 0; j < col; j++ )
1.8 noro 2780: if ( ( t = invmat[i][j] ) != 0 ) {
1.1 noro 2781: MKGFS(IFTOF(t),tmat[i][j]);
2782: }
2783: MKVECT(vect1,row);
2784: for ( i = 0, tvect = (Z *)vect1->body; i < row; i++ )
1.2 noro 2785: STOZ(index[i],tvect[i]);
1.1 noro 2786: MKNODE(node2,vect1,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
2787: }
2788: }
2789:
2790: int gauss_elim_geninv_sf_swap(int **mat,int row,int col, int ***invmatp,int **indexp)
2791: {
2792: int i,j,k,inv,a,n,m,u;
2793: int *t,*pivot,*s;
2794: int *index;
2795: int **invmat;
2796:
2797: n = col; m = row+col;
2798: *indexp = index = (int *)MALLOC_ATOMIC(row*sizeof(int));
2799: for ( i = 0; i < row; i++ )
2800: index[i] = i;
2801: for ( j = 0; j < n; j++ ) {
2802: for ( i = j; i < row && !mat[i][j]; i++ );
2803: if ( i == row ) {
2804: *indexp = 0; *invmatp = 0; return 1;
2805: }
2806: if ( i != j ) {
2807: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2808: k = index[i]; index[i] = index[j]; index[j] = k;
2809: }
2810: pivot = mat[j];
2811: inv = _invsf(pivot[j]);
2812: for ( k = j; k < m; k++ )
2813: if ( pivot[k] )
2814: pivot[k] = _mulsf(pivot[k],inv);
2815: for ( i = j+1; i < row; i++ ) {
2816: t = mat[i];
1.8 noro 2817: if ( ( a = t[j] ) != 0 )
1.1 noro 2818: for ( k = j, a = _chsgnsf(a); k < m; k++ )
2819: if ( pivot[k] ) {
2820: u = _mulsf(pivot[k],a);
2821: t[k] = _addsf(u,t[k]);
2822: }
2823: }
2824: }
2825: for ( j = n-1; j >= 0; j-- ) {
2826: pivot = mat[j];
2827: for ( i = j-1; i >= 0; i-- ) {
2828: t = mat[i];
1.8 noro 2829: if ( ( a = t[j] ) != 0 )
1.1 noro 2830: for ( k = j, a = _chsgnsf(a); k < m; k++ )
2831: if ( pivot[k] ) {
2832: u = _mulsf(pivot[k],a);
2833: t[k] = _addsf(u,t[k]);
2834: }
2835: }
2836: }
2837: *invmatp = invmat = (int **)almat(col,col);
2838: for ( i = 0; i < col; i++ )
2839: for ( j = 0, s = invmat[i], t = mat[i]; j < col; j++ )
2840: s[j] = t[col+index[j]];
2841: return 0;
2842: }
2843:
2844: void inner_product_int(Z *a,Z *b,int n,Z *r)
2845: {
2846: int i;
2847: Z t;
2848:
2849: t = 0;
2850: for ( i = 0; i < n; i++ )
2851: muladdtoz(a[i],b[i],&t);
2852: *r = t;
2853: }
2854:
2855: void Pmul_mat_vect_int(NODE arg,VECT *rp)
2856: {
2857: MAT mat;
2858: VECT vect,r;
2859: int row,col,i;
2860:
2861: mat = (MAT)ARG0(arg);
2862: vect = (VECT)ARG1(arg);
2863: row = mat->row;
2864: col = mat->col;
2865: MKVECT(r,row);
2866: for ( i = 0; i < row; i++ ) {
2867: inner_product_int((Z *)mat->body[i],(Z *)vect->body,col,(Z *)&r->body[i]);
2868: }
2869: *rp = r;
2870: }
2871:
2872: void Pnbpoly_up2(NODE arg,GF2N *rp)
2873: {
2874: int m,type,ret;
2875: UP2 r;
2876:
1.2 noro 2877: m = ZTOS((Z)ARG0(arg));
2878: type = ZTOS((Z)ARG1(arg));
1.1 noro 2879: ret = generate_ONB_polynomial(&r,m,type);
2880: if ( ret == 0 )
2881: MKGF2N(r,*rp);
2882: else
2883: *rp = 0;
2884: }
2885:
2886: void Px962_irredpoly_up2(NODE arg,GF2N *rp)
2887: {
2888: int m,ret,w;
2889: GF2N prev;
2890: UP2 r;
2891:
1.2 noro 2892: m = ZTOS((Q)ARG0(arg));
1.1 noro 2893: prev = (GF2N)ARG1(arg);
2894: if ( !prev ) {
2895: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2896: bzero((char *)r->b,w*sizeof(unsigned int));
2897: } else {
2898: r = prev->body;
2899: if ( degup2(r) != m ) {
2900: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2901: bzero((char *)r->b,w*sizeof(unsigned int));
2902: }
2903: }
2904: ret = _generate_irreducible_polynomial(r,m);
2905: if ( ret == 0 )
2906: MKGF2N(r,*rp);
2907: else
2908: *rp = 0;
2909: }
2910:
2911: void Pirredpoly_up2(NODE arg,GF2N *rp)
2912: {
2913: int m,ret,w;
2914: GF2N prev;
2915: UP2 r;
2916:
1.2 noro 2917: m = ZTOS((Q)ARG0(arg));
1.1 noro 2918: prev = (GF2N)ARG1(arg);
2919: if ( !prev ) {
2920: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2921: bzero((char *)r->b,w*sizeof(unsigned int));
2922: } else {
2923: r = prev->body;
2924: if ( degup2(r) != m ) {
2925: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2926: bzero((char *)r->b,w*sizeof(unsigned int));
2927: }
2928: }
2929: ret = _generate_good_irreducible_polynomial(r,m);
2930: if ( ret == 0 )
2931: MKGF2N(r,*rp);
2932: else
2933: *rp = 0;
2934: }
2935:
2936: void Pmat_swap_row_destructive(NODE arg, MAT *m)
2937: {
2938: int i1,i2;
2939: pointer *t;
2940: MAT mat;
2941:
2942: asir_assert(ARG0(arg),O_MAT,"mat_swap_row_destructive");
2943: asir_assert(ARG1(arg),O_N,"mat_swap_row_destructive");
2944: asir_assert(ARG2(arg),O_N,"mat_swap_row_destructive");
2945: mat = (MAT)ARG0(arg);
1.2 noro 2946: i1 = ZTOS((Q)ARG1(arg));
2947: i2 = ZTOS((Q)ARG2(arg));
1.1 noro 2948: if ( i1 < 0 || i2 < 0 || i1 >= mat->row || i2 >= mat->row )
2949: error("mat_swap_row_destructive : Out of range");
2950: t = mat->body[i1];
2951: mat->body[i1] = mat->body[i2];
2952: mat->body[i2] = t;
2953: *m = mat;
2954: }
2955:
2956: void Pmat_swap_col_destructive(NODE arg, MAT *m)
2957: {
2958: int j1,j2,i,n;
2959: pointer *mi;
2960: pointer t;
2961: MAT mat;
2962:
2963: asir_assert(ARG0(arg),O_MAT,"mat_swap_col_destructive");
2964: asir_assert(ARG1(arg),O_N,"mat_swap_col_destructive");
2965: asir_assert(ARG2(arg),O_N,"mat_swap_col_destructive");
2966: mat = (MAT)ARG0(arg);
1.2 noro 2967: j1 = ZTOS((Q)ARG1(arg));
2968: j2 = ZTOS((Q)ARG2(arg));
1.1 noro 2969: if ( j1 < 0 || j2 < 0 || j1 >= mat->col || j2 >= mat->col )
2970: error("mat_swap_col_destructive : Out of range");
2971: n = mat->row;
2972: for ( i = 0; i < n; i++ ) {
2973: mi = mat->body[i];
2974: t = mi[j1]; mi[j1] = mi[j2]; mi[j2] = t;
2975: }
2976: *m = mat;
2977: }
2978: /*
2979: * f = type 'type' normal polynomial of degree m if exists
2980: * IEEE P1363 A.7.2
2981: *
2982: * return value : 0 --- exists
2983: * 1 --- does not exist
2984: * -1 --- failure (memory allocation error)
2985: */
2986:
2987: int generate_ONB_polynomial(UP2 *rp,int m,int type)
2988: {
2989: int i,r;
2990: int w;
2991: UP2 f,f0,f1,f2,t;
2992:
2993: w = (m>>5)+1;
2994: switch ( type ) {
2995: case 1:
2996: if ( !TypeT_NB_check(m,1) ) return 1;
2997: NEWUP2(f,w); *rp = f; f->w = w;
2998: /* set all the bits */
2999: for ( i = 0; i < w; i++ )
3000: f->b[i] = 0xffffffff;
3001: /* mask the top word if necessary */
1.8 noro 3002: if ( ( r = (m+1)&31 ) != 0 )
1.1 noro 3003: f->b[w-1] &= (1<<r)-1;
3004: return 0;
3005: break;
3006: case 2:
3007: if ( !TypeT_NB_check(m,2) ) return 1;
3008: NEWUP2(f,w); *rp = f;
3009: W_NEWUP2(f0,w);
3010: W_NEWUP2(f1,w);
3011: W_NEWUP2(f2,w);
3012:
3013: /* recursion for genrating Type II normal polynomial */
3014:
3015: /* f0 = 1, f1 = t+1 */
3016: f0->w = 1; f0->b[0] = 1;
3017: f1->w = 1; f1->b[0] = 3;
3018: for ( i = 2; i <= m; i++ ) {
3019: /* f2 = t*f1+f0 */
3020: _bshiftup2(f1,-1,f2);
3021: _addup2_destructive(f2,f0);
3022: /* cyclic change of the variables */
3023: t = f0; f0 = f1; f1 = f2; f2 = t;
3024: }
3025: _copyup2(f1,f);
3026: return 0;
3027: break;
3028: default:
3029: return -1;
3030: break;
3031: }
3032: }
3033:
3034: /*
3035: * f = an irreducible trinomial or pentanomial of degree d 'after' f
3036: * return value : 0 --- exists
3037: * 1 --- does not exist (exhaustion)
3038: */
3039:
3040: int _generate_irreducible_polynomial(UP2 f,int d)
3041: {
3042: int ret,i,j,k,nz,i0,j0,k0;
3043: int w;
3044: unsigned int *fd;
3045:
3046: /*
3047: * if f = x^d+x^i+1 then i0 <- i, j0 <- 0, k0 <-0.
3048: * if f = x^d+x^k+x^j+x^i+1 (k>j>i) then i0 <- i, j0 <- j, k0 <-k.
3049: * otherwise i0,j0,k0 is set to 0.
3050: */
3051:
3052: fd = f->b;
3053: w = (d>>5)+1;
3054: if ( f->w && (d==degup2(f)) ) {
3055: for ( nz = 0, i = d; i >= 0; i-- )
3056: if ( fd[i>>5]&(1<<(i&31)) ) nz++;
3057: switch ( nz ) {
3058: case 3:
3059: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3060: /* reset i0-th bit */
3061: fd[i0>>5] &= ~(1<<(i0&31));
3062: j0 = k0 = 0;
3063: break;
3064: case 5:
3065: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3066: /* reset i0-th bit */
3067: fd[i0>>5] &= ~(1<<(i0&31));
3068: for ( j0 = i0+1; !(fd[j0>>5]&(1<<(j0&31))) ; j0++ );
3069: /* reset j0-th bit */
3070: fd[j0>>5] &= ~(1<<(j0&31));
3071: for ( k0 = j0+1; !(fd[k0>>5]&(1<<(k0&31))) ; k0++ );
3072: /* reset k0-th bit */
3073: fd[k0>>5] &= ~(1<<(k0&31));
3074: break;
3075: default:
3076: f->w = 0; break;
3077: }
3078: } else
3079: f->w = 0;
3080:
3081: if ( !f->w ) {
3082: fd = f->b;
3083: f->w = w; fd[0] |= 1; fd[d>>5] |= (1<<(d&31));
3084: i0 = j0 = k0 = 0;
3085: }
3086: /* if j0 > 0 then f is already a pentanomial */
3087: if ( j0 > 0 ) goto PENTA;
3088:
3089: /* searching for an irreducible trinomial */
3090:
3091: for ( i = 1; 2*i <= d; i++ ) {
3092: /* skip the polynomials 'before' f */
3093: if ( i < i0 ) continue;
3094: if ( i == i0 ) { i0 = 0; continue; }
3095: /* set i-th bit */
3096: fd[i>>5] |= (1<<(i&31));
3097: ret = irredcheck_dddup2(f);
3098: if ( ret == 1 ) return 0;
3099: /* reset i-th bit */
3100: fd[i>>5] &= ~(1<<(i&31));
3101: }
3102:
3103: /* searching for an irreducible pentanomial */
3104: PENTA:
3105: for ( i = 1; i < d; i++ ) {
3106: /* skip the polynomials 'before' f */
3107: if ( i < i0 ) continue;
3108: if ( i == i0 ) i0 = 0;
3109: /* set i-th bit */
3110: fd[i>>5] |= (1<<(i&31));
3111: for ( j = i+1; j < d; j++ ) {
3112: /* skip the polynomials 'before' f */
3113: if ( j < j0 ) continue;
3114: if ( j == j0 ) j0 = 0;
3115: /* set j-th bit */
3116: fd[j>>5] |= (1<<(j&31));
3117: for ( k = j+1; k < d; k++ ) {
3118: /* skip the polynomials 'before' f */
3119: if ( k < k0 ) continue;
3120: else if ( k == k0 ) { k0 = 0; continue; }
3121: /* set k-th bit */
3122: fd[k>>5] |= (1<<(k&31));
3123: ret = irredcheck_dddup2(f);
3124: if ( ret == 1 ) return 0;
3125: /* reset k-th bit */
3126: fd[k>>5] &= ~(1<<(k&31));
3127: }
3128: /* reset j-th bit */
3129: fd[j>>5] &= ~(1<<(j&31));
3130: }
3131: /* reset i-th bit */
3132: fd[i>>5] &= ~(1<<(i&31));
3133: }
3134: /* exhausted */
3135: return 1;
3136: }
3137:
3138: /*
3139: * f = an irreducible trinomial or pentanomial of degree d 'after' f
3140: *
3141: * searching strategy:
3142: * trinomial x^d+x^i+1:
3143: * i is as small as possible.
3144: * trinomial x^d+x^i+x^j+x^k+1:
3145: * i is as small as possible.
3146: * For such i, j is as small as possible.
3147: * For such i and j, 'k' is as small as possible.
3148: *
3149: * return value : 0 --- exists
3150: * 1 --- does not exist (exhaustion)
3151: */
3152:
3153: int _generate_good_irreducible_polynomial(UP2 f,int d)
3154: {
3155: int ret,i,j,k,nz,i0,j0,k0;
3156: int w;
3157: unsigned int *fd;
3158:
3159: /*
3160: * if f = x^d+x^i+1 then i0 <- i, j0 <- 0, k0 <-0.
3161: * if f = x^d+x^k+x^j+x^i+1 (k>j>i) then i0 <- i, j0 <- j, k0 <-k.
3162: * otherwise i0,j0,k0 is set to 0.
3163: */
3164:
3165: fd = f->b;
3166: w = (d>>5)+1;
3167: if ( f->w && (d==degup2(f)) ) {
3168: for ( nz = 0, i = d; i >= 0; i-- )
3169: if ( fd[i>>5]&(1<<(i&31)) ) nz++;
3170: switch ( nz ) {
3171: case 3:
3172: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3173: /* reset i0-th bit */
3174: fd[i0>>5] &= ~(1<<(i0&31));
3175: j0 = k0 = 0;
3176: break;
3177: case 5:
3178: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3179: /* reset i0-th bit */
3180: fd[i0>>5] &= ~(1<<(i0&31));
3181: for ( j0 = i0+1; !(fd[j0>>5]&(1<<(j0&31))) ; j0++ );
3182: /* reset j0-th bit */
3183: fd[j0>>5] &= ~(1<<(j0&31));
3184: for ( k0 = j0+1; !(fd[k0>>5]&(1<<(k0&31))) ; k0++ );
3185: /* reset k0-th bit */
3186: fd[k0>>5] &= ~(1<<(k0&31));
3187: break;
3188: default:
3189: f->w = 0; break;
3190: }
3191: } else
3192: f->w = 0;
3193:
3194: if ( !f->w ) {
3195: fd = f->b;
3196: f->w = w; fd[0] |= 1; fd[d>>5] |= (1<<(d&31));
3197: i0 = j0 = k0 = 0;
3198: }
3199: /* if j0 > 0 then f is already a pentanomial */
3200: if ( j0 > 0 ) goto PENTA;
3201:
3202: /* searching for an irreducible trinomial */
3203:
3204: for ( i = 1; 2*i <= d; i++ ) {
3205: /* skip the polynomials 'before' f */
3206: if ( i < i0 ) continue;
3207: if ( i == i0 ) { i0 = 0; continue; }
3208: /* set i-th bit */
3209: fd[i>>5] |= (1<<(i&31));
3210: ret = irredcheck_dddup2(f);
3211: if ( ret == 1 ) return 0;
3212: /* reset i-th bit */
3213: fd[i>>5] &= ~(1<<(i&31));
3214: }
3215:
3216: /* searching for an irreducible pentanomial */
3217: PENTA:
3218: for ( i = 3; i < d; i++ ) {
3219: /* skip the polynomials 'before' f */
3220: if ( i < i0 ) continue;
3221: if ( i == i0 ) i0 = 0;
3222: /* set i-th bit */
3223: fd[i>>5] |= (1<<(i&31));
3224: for ( j = 2; j < i; j++ ) {
3225: /* skip the polynomials 'before' f */
3226: if ( j < j0 ) continue;
3227: if ( j == j0 ) j0 = 0;
3228: /* set j-th bit */
3229: fd[j>>5] |= (1<<(j&31));
3230: for ( k = 1; k < j; k++ ) {
3231: /* skip the polynomials 'before' f */
3232: if ( k < k0 ) continue;
3233: else if ( k == k0 ) { k0 = 0; continue; }
3234: /* set k-th bit */
3235: fd[k>>5] |= (1<<(k&31));
3236: ret = irredcheck_dddup2(f);
3237: if ( ret == 1 ) return 0;
3238: /* reset k-th bit */
3239: fd[k>>5] &= ~(1<<(k&31));
3240: }
3241: /* reset j-th bit */
3242: fd[j>>5] &= ~(1<<(j&31));
3243: }
3244: /* reset i-th bit */
3245: fd[i>>5] &= ~(1<<(i&31));
3246: }
3247: /* exhausted */
3248: return 1;
3249: }
3250:
3251: void printqmat(Q **mat,int row,int col)
3252: {
3253: int i,j;
3254:
3255: for ( i = 0; i < row; i++ ) {
3256: for ( j = 0; j < col; j++ ) {
3257: printnum((Num)mat[i][j]); printf(" ");
3258: }
3259: printf("\n");
3260: }
3261: }
3262:
3263: void printimat(int **mat,int row,int col)
3264: {
3265: int i,j;
3266:
3267: for ( i = 0; i < row; i++ ) {
3268: for ( j = 0; j < col; j++ ) {
3269: printf("%d ",mat[i][j]);
3270: }
3271: printf("\n");
3272: }
3273: }
3274:
3275: void Pnd_det(NODE arg,P *rp)
3276: {
3277: if ( argc(arg) == 1 )
3278: nd_det(0,ARG0(arg),rp);
3279: else
1.2 noro 3280: nd_det(ZTOS((Q)ARG1(arg)),ARG0(arg),rp);
1.1 noro 3281: }
3282:
3283: void Pmat_col(NODE arg,VECT *rp)
3284: {
3285: int i,j,n;
3286: MAT mat;
3287: VECT vect;
3288:
3289: asir_assert(ARG0(arg),O_MAT,"mat_col");
3290: asir_assert(ARG1(arg),O_N,"mat_col");
3291: mat = (MAT)ARG0(arg);
1.2 noro 3292: j = ZTOS((Q)ARG1(arg));
1.1 noro 3293: if ( j < 0 || j >= mat->col) {
3294: error("mat_col : Out of range");
3295: }
3296: n = mat->row;
3297: MKVECT(vect,n);
3298: for(i=0; i<n; i++) {
3299: BDY(vect)[i] = BDY(mat)[i][j];
3300: }
3301: *rp = vect;
3302: }
3303:
3304: NODE triangleq(NODE e)
3305: {
3306: int n,i,k;
3307: V v;
3308: VL vl;
3309: P *p;
3310: NODE r,r1;
3311:
3312: n = length(e);
3313: p = (P *)MALLOC(n*sizeof(P));
3314: for ( i = 0; i < n; i++, e = NEXT(e) ) p[i] = (P)BDY(e);
3315: i = 0;
3316: while ( 1 ) {
3317: for ( ; i < n && !p[i]; i++ );
3318: if ( i == n ) break;
3319: if ( OID(p[i]) == O_N ) return 0;
3320: v = p[i]->v;
3321: for ( k = i+1; k < n; k++ )
3322: if ( p[k] ) {
3323: if ( OID(p[k]) == O_N ) return 0;
3324: if ( p[k]->v == v ) p[k] = 0;
3325: }
3326: i++;
3327: }
3328: for ( r = 0, i = 0; i < n; i++ ) {
3329: if ( p[i] ) {
3330: MKNODE(r1,p[i],r); r = r1;
3331: }
3332: }
3333: return r;
3334: }
3335:
3336: void Ptriangleq(NODE arg,LIST *rp)
3337: {
3338: NODE ret;
3339:
3340: asir_assert(ARG0(arg),O_LIST,"sparseleq");
3341: ret = triangleq(BDY((LIST)ARG0(arg)));
3342: MKLIST(*rp,ret);
3343: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>