Annotation of OpenXM_contrib2/asir2018/builtin/array.c, Revision 1.8
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.8 ! noro 48: * $OpenXM: OpenXM_contrib2/asir2018/builtin/array.c,v 1.7 2020/01/09 01:47:40 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
625: for ( i = 0, tn = BDY(list), vb = BDY(vect); tn; i++, tn = NEXT(tn) )
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;
1253:
1254: asir_assert(ARG0(arg),O_MAT,"generic_gauss_elim_mod64");
1255: asir_assert(ARG1(arg),O_N,"generic_gauss_elim_mod64");
1256: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1257: row = m->row; col = m->col; tmat = (Z **)m->body;
1258: wmat = (mp_limb_t **)almat64(row,col);
1259:
1260: row0 = (mp_limb_t **)ALLOCA(row*sizeof(mp_limb_t *));
1261: for ( i = 0; i < row; i++ ) row0[i] = wmat[i];
1262:
1263: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1264: for ( i = 0; i < row; i++ )
1265: for ( j = 0; j < col; j++ )
1266: wmat[i][j] = remqi64((Q)tmat[i][j],md);
1267: rank = generic_gauss_elim_mod64(wmat,row,col,md,colstat);
1268:
1269: MKVECT(rnum,rank);
1270: rnb = (Z *)rnum->body;
1271: for ( i = 0; i < rank; i++ )
1272: for ( j = 0, p = wmat[i]; j < row; j++ )
1273: if ( p == row0[j] )
1274: STOZ(j,rnb[i]);
1275:
1276: MKMAT(mat,rank,col-rank);
1277: tmat = (Z **)mat->body;
1278: for ( i = 0; i < rank; i++ )
1279: for ( j = k = 0; j < col; j++ )
1280: if ( !colstat[j] ) {
1281: UTOZ(wmat[i][j],tmat[i][k]); k++;
1282: }
1283:
1284: MKVECT(rind,rank);
1285: MKVECT(cind,col-rank);
1286: rib = (Z *)rind->body; cib = (Z *)cind->body;
1287: for ( j = k = l = 0; j < col; j++ )
1288: if ( colstat[j] ) {
1289: STOZ(j,rib[k]); k++;
1290: } else {
1291: STOZ(j,cib[l]); l++;
1292: }
1293: n0 = mknode(4,mat,rind,cind,rnum);
1294: MKLIST(*rp,n0);
1295: }
1296: #endif
1297:
1.1 noro 1298: void Pgeneric_gauss_elim_mod(NODE arg,LIST *rp)
1299: {
1300: NODE n0;
1301: MAT m,mat;
1302: VECT rind,cind,rnum;
1303: Z **tmat;
1304: int **wmat,**row0;
1305: Z *rib,*cib,*rnb;
1306: int *colstat,*p;
1307: Z q;
1.3 noro 1308: long mdl;
1.1 noro 1309: int md,i,j,k,l,row,col,t,rank;
1310:
1311: asir_assert(ARG0(arg),O_MAT,"generic_gauss_elim_mod");
1312: asir_assert(ARG1(arg),O_N,"generic_gauss_elim_mod");
1.3 noro 1313: #if SIZEOF_LONG==8
1314: mdl = ZTOS((Z)ARG1(arg));
1315: if ( mdl >= ((mp_limb_t)1)<<32 ) {
1316: Pgeneric_gauss_elim_mod64(arg,rp);
1317: return;
1318: }
1319: #endif
1320: m = (MAT)ARG0(arg);
1321: md = ZTOS((Z)ARG1(arg));
1.1 noro 1322: row = m->row; col = m->col; tmat = (Z **)m->body;
1323: wmat = (int **)almat(row,col);
1324:
1325: row0 = (int **)ALLOCA(row*sizeof(int *));
1326: for ( i = 0; i < row; i++ ) row0[i] = wmat[i];
1327:
1328: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
1329: for ( i = 0; i < row; i++ )
1330: for ( j = 0; j < col; j++ )
1331: wmat[i][j] = remqi((Q)tmat[i][j],md);
1332: rank = generic_gauss_elim_mod(wmat,row,col,md,colstat);
1333:
1334: MKVECT(rnum,rank);
1335: rnb = (Z *)rnum->body;
1336: for ( i = 0; i < rank; i++ )
1337: for ( j = 0, p = wmat[i]; j < row; j++ )
1338: if ( p == row0[j] )
1.2 noro 1339: STOZ(j,rnb[i]);
1.1 noro 1340:
1341: MKMAT(mat,rank,col-rank);
1342: tmat = (Z **)mat->body;
1343: for ( i = 0; i < rank; i++ )
1344: for ( j = k = 0; j < col; j++ )
1345: if ( !colstat[j] ) {
1.2 noro 1346: UTOZ(wmat[i][j],tmat[i][k]); k++;
1.1 noro 1347: }
1348:
1349: MKVECT(rind,rank);
1350: MKVECT(cind,col-rank);
1351: rib = (Z *)rind->body; cib = (Z *)cind->body;
1352: for ( j = k = l = 0; j < col; j++ )
1353: if ( colstat[j] ) {
1.2 noro 1354: STOZ(j,rib[k]); k++;
1.1 noro 1355: } else {
1.2 noro 1356: STOZ(j,cib[l]); l++;
1.1 noro 1357: }
1358: n0 = mknode(4,mat,rind,cind,rnum);
1359: MKLIST(*rp,n0);
1360: }
1361:
1.3 noro 1362:
1.1 noro 1363: void Pleqm(NODE arg,VECT *rp)
1364: {
1365: MAT m;
1366: VECT vect;
1367: pointer **mat;
1368: Z *v;
1369: Z q;
1370: int **wmat;
1371: int md,i,j,row,col,t,n,status;
1372:
1373: asir_assert(ARG0(arg),O_MAT,"leqm");
1374: asir_assert(ARG1(arg),O_N,"leqm");
1.2 noro 1375: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1.1 noro 1376: row = m->row; col = m->col; mat = m->body;
1377: wmat = (int **)almat(row,col);
1378: for ( i = 0; i < row; i++ )
1379: for ( j = 0; j < col; j++ )
1380: wmat[i][j] = remqi((Q)mat[i][j],md);
1381: status = gauss_elim_mod(wmat,row,col,md);
1382: if ( status < 0 )
1383: *rp = 0;
1384: else if ( status > 0 )
1385: *rp = (VECT)ONE;
1386: else {
1387: n = col - 1;
1388: MKVECT(vect,n);
1389: for ( i = 0, v = (Z *)vect->body; i < n; i++ ) {
1.2 noro 1390: t = (md-wmat[i][n])%md; STOZ(t,v[i]);
1.1 noro 1391: }
1392: *rp = vect;
1393: }
1394: }
1395:
1396: int gauss_elim_mod(int **mat,int row,int col,int md)
1397: {
1398: int i,j,k,inv,a,n;
1399: int *t,*pivot;
1400:
1401: n = col - 1;
1402: for ( j = 0; j < n; j++ ) {
1403: for ( i = j; i < row && !mat[i][j]; i++ );
1404: if ( i == row )
1405: return 1;
1406: if ( i != j ) {
1407: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
1408: }
1409: pivot = mat[j];
1410: inv = invm(pivot[j],md);
1411: for ( k = j; k <= n; k++ ) {
1412: /* pivot[k] = dmar(pivot[k],inv,0,md); */
1413: DMAR(pivot[k],inv,0,md,pivot[k])
1414: }
1415: for ( i = 0; i < row; i++ ) {
1416: t = mat[i];
1417: if ( i != j && (a = t[j]) )
1418: for ( k = j, a = md - a; k <= n; k++ ) {
1419: unsigned int tk;
1420: /* t[k] = dmar(pivot[k],a,t[k],md); */
1421: DMAR(pivot[k],a,t[k],md,tk)
1422: t[k] = tk;
1423: }
1424: }
1425: }
1426: for ( i = n; i < row && !mat[i][n]; i++ );
1427: if ( i == row )
1428: return 0;
1429: else
1430: return -1;
1431: }
1432:
1.7 noro 1433: 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 1434: struct oEGT eg_conv;
1435:
1436: #if 0
1437: void lu_dec_cr(MAT mat,MAT lu,Q *dn,int **perm);
1438:
1439: /* XXX broken */
1440: void lu_dec_cr(MAT mat,MAT lu,Q *dn,int **perm)
1441: {
1442: Q **a0,**b;
1443: Q *aiq;
1444: N **a;
1445: N *ai;
1446: Q q,q1,dn2,a1,q0,bik;
1447: MAT m;
1448: unsigned int md;
1449: int n,ind,i,j,rank,t,inv,t1,ret,min,k;
1450: int **w;
1451: int *wi,*rinfo0,*rinfo;
1452: N m1,m2,m3,u,s;
1453:
1454: a0 = (Q **)mat->body;
1455: n = mat->row;
1456: if ( n != mat->col )
1457: error("lu_dec_cr : non-square matrix");
1458: w = (int **)almat(n,n);
1459: MKMAT(m,n,n);
1460: a = (N **)m->body;
1461: UTON(1,m1);
1462: rinfo0 = 0;
1463: ind = 0;
1464: while ( 1 ) {
1465: md = get_lprime(ind);
1466: /* mat mod md */
1467: for ( i = 0; i < n; i++ )
1468: for ( j = 0, aiq = a0[i], wi = w[i]; j < n; j++ )
1469: if ( q = aiq[j] ) {
1470: t = rem(NM(q),md);
1471: if ( t && SGN(q) < 0 )
1472: t = (md - t) % md;
1473: wi[j] = t;
1474: } else
1475: wi[j] = 0;
1476:
1477: if ( !lu_mod((unsigned int **)w,n,md,&rinfo) ) continue;
1478: printf("."); fflush(stdout);
1479: if ( !rinfo0 )
1480: *perm = rinfo0 = rinfo;
1481: else {
1482: for ( i = 0; i < n; i++ )
1483: if ( rinfo[i] != rinfo0[i] ) break;
1484: if ( i < n ) continue;
1485: }
1486: if ( UNIN(m1) ) {
1487: for ( i = 0; i < n; i++ )
1488: for ( j = 0, ai = a[i], wi = w[i]; j < n; j++ ) {
1489: UTON(wi[j],u); ai[j] = u;
1490: }
1491: UTON(md,m1);
1492: } else {
1493: inv = invm(rem(m1,md),md);
1494: UTON(md,m2); muln(m1,m2,&m3);
1495: for ( i = 0; i < n; i++ )
1496: for ( j = 0, ai = a[i], wi = w[i]; j < n; j++ )
1497: if ( ai[i] ) {
1498: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
1499: t = rem(ai[j],md);
1500: if ( wi[j] >= t )
1501: t = wi[j]-t;
1502: else
1503: t = md-(t-wi[j]);
1504: DMAR(t,inv,0,md,t1)
1505: UTON(t1,u);
1506: muln(m1,u,&s);
1507: addn(ai[j],s,&u); ai[j] = u;
1508: } else if ( wi[j] ) {
1509: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
1510: DMAR(wi[j],inv,0,md,t)
1511: UTON(t,u);
1512: muln(m1,u,&s); ai[j] = s;
1513: }
1514: m1 = m3;
1515: }
1516: if ( (++ind%8) == 0 ) {
1517: ret = intmtoratm(m,m1,lu,dn);
1518: if ( ret ) {
1519: b = (Q **)lu->body;
1520: mulq(*dn,*dn,&dn2);
1521: for ( i = 0; i < n; i++ ) {
1522: for ( j = 0; j < n; j++ ) {
1523: q = 0;
1524: min = MIN(i,j);
1525: for ( k = 0; k <= min; k++ ) {
1526: bik = k==i ? *dn : b[i][k];
1527: mulq(bik,b[k][j],&q0);
1528: addq(q,q0,&q1); q = q1;
1529: }
1530: mulq(a0[rinfo0[i]][j],dn2,&q1);
1531: if ( cmpq(q,q1) ) break;
1532: }
1533: if ( j < n ) break;
1534: }
1535: if ( i == n )
1536: return;
1537: }
1538: }
1539: }
1540: }
1541: #endif
1542:
1543:
1544: int f4_nocheck;
1545:
1.8 ! noro 1546: #define ONE_STEP1 if ( ( zzz = *s ) != 0 ) { DMAR(zzz,hc,*tj,md,*tj) } tj++; s++;
1.1 noro 1547:
1548: void reduce_reducers_mod(int **mat,int row,int col,int md)
1549: {
1550: int i,j,k,l,hc,zzz;
1551: int *t,*s,*tj,*ind;
1552:
1553: /* reduce the reducers */
1554: ind = (int *)ALLOCA(row*sizeof(int));
1555: for ( i = 0; i < row; i++ ) {
1556: t = mat[i];
1557: for ( j = 0; j < col && !t[j]; j++ );
1558: /* register the position of the head term */
1559: ind[i] = j;
1560: for ( l = i-1; l >= 0; l-- ) {
1561: /* reduce mat[i] by mat[l] */
1.8 ! noro 1562: if ( ( hc = t[ind[l]] ) != 0 ) {
1.1 noro 1563: /* mat[i] = mat[i]-hc*mat[l] */
1564: j = ind[l];
1565: s = mat[l]+j;
1566: tj = t+j;
1567: hc = md-hc;
1568: k = col-j;
1569: for ( ; k >= 64; k -= 64 ) {
1570: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1571: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1572: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1573: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1574: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1575: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1576: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1577: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1578: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1579: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1580: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1581: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1582: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1583: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1584: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1585: ONE_STEP1 ONE_STEP1 ONE_STEP1 ONE_STEP1
1586: }
1587: for ( ; k > 0; k-- ) {
1.8 ! noro 1588: if ( ( zzz = *s ) != 0 ) { DMAR(zzz,hc,*tj,md,*tj) } tj++; s++;
1.1 noro 1589: }
1590: }
1591: }
1592: }
1593: }
1594:
1595: /*
1596: mat[i] : reducers (i=0,...,nred-1)
1597: spolys (i=nred,...,row-1)
1598: mat[0] < mat[1] < ... < mat[nred-1] w.r.t the term order
1599: 1. reduce the reducers
1600: 2. reduce spolys by the reduced reducers
1601: */
1602:
1603: void pre_reduce_mod(int **mat,int row,int col,int nred,int md)
1604: {
1605: int i,j,k,l,hc,inv;
1606: int *t,*s,*tk,*ind;
1607:
1608: #if 1
1609: /* reduce the reducers */
1610: ind = (int *)ALLOCA(row*sizeof(int));
1611: for ( i = 0; i < nred; i++ ) {
1612: /* make mat[i] monic and mat[i] by mat[0],...,mat[i-1] */
1613: t = mat[i];
1614: for ( j = 0; j < col && !t[j]; j++ );
1615: /* register the position of the head term */
1616: ind[i] = j;
1617: inv = invm(t[j],md);
1618: for ( k = j; k < col; k++ )
1619: if ( t[k] )
1620: DMAR(t[k],inv,0,md,t[k])
1621: for ( l = i-1; l >= 0; l-- ) {
1622: /* reduce mat[i] by mat[l] */
1.8 ! noro 1623: if ( ( hc = t[ind[l]] ) != 0 ) {
1.1 noro 1624: /* mat[i] = mat[i]-hc*mat[l] */
1625: for ( k = ind[l], hc = md-hc, s = mat[l]+k, tk = t+k;
1626: k < col; k++, tk++, s++ )
1627: if ( *s )
1628: DMAR(*s,hc,*tk,md,*tk)
1629: }
1630: }
1631: }
1632: /* reduce the spolys */
1633: for ( i = nred; i < row; i++ ) {
1634: t = mat[i];
1635: for ( l = nred-1; l >= 0; l-- ) {
1636: /* reduce mat[i] by mat[l] */
1.8 ! noro 1637: if ( ( hc = t[ind[l]] ) != 0 ) {
1.1 noro 1638: /* mat[i] = mat[i]-hc*mat[l] */
1639: for ( k = ind[l], hc = md-hc, s = mat[l]+k, tk = t+k;
1640: k < col; k++, tk++, s++ )
1641: if ( *s )
1642: DMAR(*s,hc,*tk,md,*tk)
1643: }
1644: }
1645: }
1646: #endif
1647: }
1648: /*
1649: mat[i] : reducers (i=0,...,nred-1)
1650: mat[0] < mat[1] < ... < mat[nred-1] w.r.t the term order
1651: */
1652:
1653: void reduce_sp_by_red_mod(int *sp,int **redmat,int *ind,int nred,int col,int md)
1654: {
1655: int i,j,k,hc,zzz;
1656: int *s,*tj;
1657:
1658: /* reduce the spolys by redmat */
1659: for ( i = nred-1; i >= 0; i-- ) {
1660: /* reduce sp by redmat[i] */
1.8 ! noro 1661: if ( ( hc = sp[ind[i]] ) != 0 ) {
1.1 noro 1662: /* sp = sp-hc*redmat[i] */
1663: j = ind[i];
1664: hc = md-hc;
1665: s = redmat[i]+j;
1666: tj = sp+j;
1667: for ( k = col-j; k > 0; k-- ) {
1.8 ! noro 1668: if ( ( zzz = *s ) != 0 ) { DMAR(zzz,hc,*tj,md,*tj) } tj++; s++;
1.1 noro 1669: }
1670: }
1671: }
1672: }
1673:
1674: /*
1675: mat[i] : compressed reducers (i=0,...,nred-1)
1676: mat[0] < mat[1] < ... < mat[nred-1] w.r.t the term order
1677: */
1678:
1679: void red_by_compress(int m,unsigned int *p,unsigned int *r,
1680: unsigned int *ri,unsigned int hc,int len)
1681: {
1682: unsigned int up,lo;
1683: unsigned int dmy;
1684: unsigned int *pj;
1685:
1686: p[*ri] = 0; r++; ri++;
1687: for ( len--; len; len--, r++, ri++ ) {
1688: pj = p+ *ri;
1689: DMA(*r,hc,*pj,up,lo);
1690: if ( up ) {
1691: DSAB(m,up,lo,dmy,*pj);
1692: } else
1693: *pj = lo;
1694: }
1695: }
1696:
1697: /* p -= hc*r */
1698:
1699: void red_by_vect(int m,unsigned int *p,unsigned int *r,unsigned int hc,int len)
1700: {
1701: unsigned int up,lo,dmy;
1702:
1703: *p++ = 0; r++; len--;
1704: for ( ; len; len--, r++, p++ )
1705: if ( *r ) {
1706: DMA(*r,hc,*p,up,lo);
1707: if ( up ) {
1708: DSAB(m,up,lo,dmy,*p);
1709: } else
1710: *p = lo;
1711: }
1712: }
1713:
1.3 noro 1714: #if SIZEOF_LONG==8
1715: /* mp_limb_t vector += U32 vector(normalized)*U32 */
1.1 noro 1716:
1.3 noro 1717: 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 1718: {
1.3 noro 1719: mp_limb_t t;
1.1 noro 1720:
1721: /* (p[0],c[0]) is normalized */
1722: *p++ = 0; *c++ = 0; r++; len--;
1723: for ( ; len; len--, r++, p++, c++ )
1724: if ( *r ) {
1725: t = (*p)+(*r)*hc;
1726: if ( t < *p ) (*c)++;
1727: *p = t;
1728: }
1729: }
1.3 noro 1730:
1731: /* mp_limb_t vector = (mp_limb_t vector+mp_limb_t vector*mp_limb_t)%mp_limb_t */
1732:
1733: void red_by_vect64mod(mp_limb_t m, mp_limb_t *p,mp_limb_t *r,mp_limb_t hc,int len)
1734: {
1735: *p++ = 0; r++; len--;
1736: for ( ; len; len--, r++, p++ )
1737: if ( *r )
1738: *p = muladdmod64(*r,hc,*p,m);
1739: }
1740:
1741: int generic_gauss_elim_mod64(mp_limb_t **mat,int row,int col,mp_limb_t md,int *colstat)
1742: {
1743: int i,j,k,l,rank;
1744: mp_limb_t inv,a;
1745: mp_limb_t *t,*pivot,*pk;
1746:
1747: for ( rank = 0, j = 0; j < col; j++ ) {
1748: for ( i = rank; i < row; i++ )
1749: if ( mat[i][j] )
1750: break;
1751: if ( i == row ) {
1752: colstat[j] = 0;
1753: continue;
1754: } else
1755: colstat[j] = 1;
1756: if ( i != rank ) {
1757: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
1758: }
1759: pivot = mat[rank];
1760: inv = invmod64(pivot[j],md);
1761: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
1762: if ( *pk )
1763: *pk = mulmod64(*pk,inv,md);
1764: for ( i = rank+1; i < row; i++ ) {
1765: t = mat[i];
1.8 ! noro 1766: if ( ( a = t[j] ) != 0 )
1.3 noro 1767: red_by_vect64mod(md,t+j,pivot+j,md-a,col-j);
1768: }
1769: rank++;
1770: }
1771: for ( j = col-1, l = rank-1; j >= 0; j-- )
1772: if ( colstat[j] ) {
1773: pivot = mat[l];
1774: for ( i = 0; i < l; i++ ) {
1775: t = mat[i];
1.8 ! noro 1776: if ( ( a = t[j] ) != 0 )
1.3 noro 1777: red_by_vect64mod(md,t+j,pivot+j,md-a,col-j);
1778: }
1779: l--;
1780: }
1781: return rank;
1782: }
1783:
1.4 noro 1784: int find_lhs_and_lu_mod64(mp_limb_t **a,int row,int col,
1785: mp_limb_t md,int **rinfo,int **cinfo)
1786: {
1787: int i,j,k,d;
1788: int *rp,*cp;
1789: mp_limb_t *t,*pivot;
1790: mp_limb_t inv,m;
1791:
1792: *rinfo = rp = (int *)MALLOC_ATOMIC(row*sizeof(int));
1793: *cinfo = cp = (int *)MALLOC_ATOMIC(col*sizeof(int));
1794: for ( i = 0; i < row; i++ )
1795: rp[i] = i;
1796: for ( k = 0, d = 0; k < col; k++ ) {
1797: for ( i = d; i < row && !a[i][k]; i++ );
1798: if ( i == row ) {
1799: cp[k] = 0;
1800: continue;
1801: } else
1802: cp[k] = 1;
1803: if ( i != d ) {
1804: j = rp[i]; rp[i] = rp[d]; rp[d] = j;
1805: t = a[i]; a[i] = a[d]; a[d] = t;
1806: }
1807: pivot = a[d];
1808: pivot[k] = inv = invmod64(pivot[k],md);
1809: for ( i = d+1; i < row; i++ ) {
1810: t = a[i];
1811: if ( (m = t[k]) != 0 ) {
1812: t[k] = mulmod64(inv,m,md);
1813: for ( j = k+1, m = md - t[k]; j < col; j++ )
1814: if ( pivot[j] ) {
1815: t[j] = muladdmod64(m,pivot[j],t[j],md);
1816: }
1817: }
1818: }
1819: d++;
1820: }
1821: return d;
1822: }
1823:
1824: int lu_mod64(mp_limb_t **a,int n,mp_limb_t md,int **rinfo)
1825: {
1826: int i,j,k;
1827: int *rp;
1828: mp_limb_t *t,*pivot;
1829: mp_limb_t inv,m;
1830:
1831: *rinfo = rp = (int *)MALLOC_ATOMIC(n*sizeof(int));
1832: for ( i = 0; i < n; i++ ) rp[i] = i;
1833: for ( k = 0; k < n; k++ ) {
1834: for ( i = k; i < n && !a[i][k]; i++ );
1835: if ( i == n ) return 0;
1836: if ( i != k ) {
1837: j = rp[i]; rp[i] = rp[k]; rp[k] = j;
1838: t = a[i]; a[i] = a[k]; a[k] = t;
1839: }
1840: pivot = a[k];
1841: inv = invmod64(pivot[k],md);
1842: for ( i = k+1; i < n; i++ ) {
1843: t = a[i];
1844: if ( (m = t[k]) != 0 ) {
1845: t[k] = mulmod64(inv,m,md);
1846: for ( j = k+1, m = md - t[k]; j < n; j++ )
1847: if ( pivot[j] ) {
1848: t[j] = muladdmod64(m,pivot[j],t[j],md);
1849: }
1850: }
1851: }
1852: }
1853: return 1;
1854: }
1855:
1856: /*
1857: Input
1858: a : n x n matrix; a result of LU-decomposition
1859: md : modulus
1860: b : n x l matrix
1861: Output
1862: b = a^(-1)b
1863: */
1864:
1865: void solve_by_lu_mod64(mp_limb_t **a,int n,mp_limb_t md,mp_limb_signed_t **b,int l,int normalize)
1866: {
1867: mp_limb_t *y,*c;
1868: int i,j,k;
1869: mp_limb_t t,m,m2;
1870:
1871: y = (mp_limb_t *)MALLOC_ATOMIC(n*sizeof(mp_limb_t));
1872: c = (mp_limb_t *)MALLOC_ATOMIC(n*sizeof(mp_limb_t));
1873: m2 = md/2;
1874: for ( k = 0; k < l; k++ ) {
1875: /* copy b[.][k] to c */
1876: for ( i = 0; i < n; i++ )
1877: c[i] = b[i][k];
1878: /* solve Ly=c */
1879: for ( i = 0; i < n; i++ ) {
1880: for ( t = c[i], j = 0; j < i; j++ )
1881: if ( a[i][j] ) {
1882: m = md - a[i][j];
1883: t = muladdmod64(m,y[j],t,md);
1884: }
1885: y[i] = t;
1886: }
1887: /* solve Uc=y */
1888: for ( i = n-1; i >= 0; i-- ) {
1889: for ( t = y[i], j =i+1; j < n; j++ )
1890: if ( a[i][j] ) {
1891: m = md - a[i][j];
1892: t = muladdmod64(m,c[j],t,md);
1893: }
1894: /* a[i][i] = 1/U[i][i] */
1895: c[i] = mulmod64(t,a[i][i],md);
1896: }
1897: /* copy c to b[.][k] with normalization */
1898: if ( normalize )
1899: for ( i = 0; i < n; i++ )
1900: b[i][k] = (mp_limb_signed_t)(c[i]>m2 ? c[i]-md : c[i]);
1901: else
1902: for ( i = 0; i < n; i++ )
1903: b[i][k] = (mp_limb_signed_t)c[i];
1904: }
1905: }
1.1 noro 1906: #endif
1907:
1908: void red_by_vect_sf(int m,unsigned int *p,unsigned int *r,unsigned int hc,int len)
1909: {
1910: *p++ = 0; r++; len--;
1911: for ( ; len; len--, r++, p++ )
1912: if ( *r )
1913: *p = _addsf(_mulsf(*r,hc),*p);
1914: }
1915:
1916: extern Z current_mod_lf;
1917: extern int current_mod_lf_size;
1918:
1919: void red_by_vect_lf(mpz_t *p,mpz_t *r,mpz_t hc,int len)
1920: {
1921: mpz_set_ui(*p++,0); r++; len--;
1922: for ( ; len; len--, r++, p++ ) {
1923: mpz_addmul(*p,*r,hc);
1924: #if 0
1925: if ( mpz_size(*p) > current_mod_lf_size )
1926: mpz_mod(*p,*p,BDY(current_mod_lf));
1927: #endif
1928: }
1929: }
1930:
1931:
1932: extern unsigned int **psca;
1933:
1934: void reduce_sp_by_red_mod_compress (int *sp,CDP *redmat,int *ind,
1935: int nred,int col,int md)
1936: {
1937: int i,len;
1938: CDP ri;
1939: unsigned int hc;
1940: unsigned int *usp;
1941:
1942: usp = (unsigned int *)sp;
1943: /* reduce the spolys by redmat */
1944: for ( i = nred-1; i >= 0; i-- ) {
1945: /* reduce sp by redmat[i] */
1946: usp[ind[i]] %= md;
1.8 ! noro 1947: if ( ( hc = usp[ind[i]] ) != 0 ) {
1.1 noro 1948: /* sp = sp-hc*redmat[i] */
1949: hc = md-hc;
1950: ri = redmat[i];
1951: len = ri->len;
1952: red_by_compress(md,usp,psca[ri->psindex],ri->body,hc,len);
1953: }
1954: }
1955: for ( i = 0; i < col; i++ )
1956: if ( usp[i] >= (unsigned int)md )
1957: usp[i] %= md;
1958: }
1959:
1960: #define ONE_STEP2 if ( zzz = *pk ) { DMAR(zzz,a,*tk,md,*tk) } pk++; tk++;
1961:
1962: int generic_gauss_elim_mod(int **mat0,int row,int col,int md,int *colstat)
1963: {
1964: int i,j,k,l,inv,a,rank;
1965: unsigned int *t,*pivot,*pk;
1966: unsigned int **mat;
1967:
1968: mat = (unsigned int **)mat0;
1969: for ( rank = 0, j = 0; j < col; j++ ) {
1970: for ( i = rank; i < row; i++ )
1971: mat[i][j] %= md;
1972: for ( i = rank; i < row; i++ )
1973: if ( mat[i][j] )
1974: break;
1975: if ( i == row ) {
1976: colstat[j] = 0;
1977: continue;
1978: } else
1979: colstat[j] = 1;
1980: if ( i != rank ) {
1981: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
1982: }
1983: pivot = mat[rank];
1984: inv = invm(pivot[j],md);
1985: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
1986: if ( *pk ) {
1987: if ( *pk >= (unsigned int)md )
1988: *pk %= md;
1989: DMAR(*pk,inv,0,md,*pk)
1990: }
1991: for ( i = rank+1; i < row; i++ ) {
1992: t = mat[i];
1.8 ! noro 1993: if ( ( a = t[j] ) != 0 )
1.1 noro 1994: red_by_vect(md,t+j,pivot+j,md-a,col-j);
1995: }
1996: rank++;
1997: }
1998: for ( j = col-1, l = rank-1; j >= 0; j-- )
1999: if ( colstat[j] ) {
2000: pivot = mat[l];
2001: for ( i = 0; i < l; i++ ) {
2002: t = mat[i];
2003: t[j] %= md;
1.8 ! noro 2004: if ( ( a = t[j] ) != 0 )
1.1 noro 2005: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2006: }
2007: l--;
2008: }
2009: for ( j = 0, l = 0; l < rank; j++ )
2010: if ( colstat[j] ) {
2011: t = mat[l];
2012: for ( k = j; k < col; k++ )
2013: if ( t[k] >= (unsigned int)md )
2014: t[k] %= md;
2015: l++;
2016: }
2017: return rank;
2018: }
2019:
2020: int generic_gauss_elim_mod2(int **mat0,int row,int col,int md,int *colstat,int *rowstat)
2021: {
2022: int i,j,k,l,inv,a,rank;
2023: unsigned int *t,*pivot,*pk;
2024: unsigned int **mat;
2025:
2026: for ( i = 0; i < row; i++ ) rowstat[i] = i;
2027: mat = (unsigned int **)mat0;
2028: for ( rank = 0, j = 0; j < col; j++ ) {
2029: for ( i = rank; i < row; i++ )
2030: mat[i][j] %= md;
2031: for ( i = rank; i < row; i++ )
2032: if ( mat[i][j] )
2033: break;
2034: if ( i == row ) {
2035: colstat[j] = 0;
2036: continue;
2037: } else
2038: colstat[j] = 1;
2039: if ( i != rank ) {
2040: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
2041: k = rowstat[i]; rowstat[i] = rowstat[rank]; rowstat[rank] = k;
2042: }
2043: pivot = mat[rank];
2044: inv = invm(pivot[j],md);
2045: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
2046: if ( *pk ) {
2047: if ( *pk >= (unsigned int)md )
2048: *pk %= md;
2049: DMAR(*pk,inv,0,md,*pk)
2050: }
2051: for ( i = rank+1; i < row; i++ ) {
2052: t = mat[i];
1.8 ! noro 2053: if ( ( a = t[j] ) != 0 )
1.1 noro 2054: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2055: }
2056: rank++;
2057: }
2058: for ( j = col-1, l = rank-1; j >= 0; j-- )
2059: if ( colstat[j] ) {
2060: pivot = mat[l];
2061: for ( i = 0; i < l; i++ ) {
2062: t = mat[i];
2063: t[j] %= md;
1.8 ! noro 2064: if ( ( a = t[j] ) != 0 )
1.1 noro 2065: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2066: }
2067: l--;
2068: }
2069: for ( j = 0, l = 0; l < rank; j++ )
2070: if ( colstat[j] ) {
2071: t = mat[l];
2072: for ( k = j; k < col; k++ )
2073: if ( t[k] >= (unsigned int)md )
2074: t[k] %= md;
2075: l++;
2076: }
2077: return rank;
2078: }
2079:
2080: int indep_rows_mod(int **mat0,int row,int col,int md,int *rowstat)
2081: {
2082: int i,j,k,l,inv,a,rank;
2083: unsigned int *t,*pivot,*pk;
2084: unsigned int **mat;
2085:
2086: for ( i = 0; i < row; i++ ) rowstat[i] = i;
2087: mat = (unsigned int **)mat0;
2088: for ( rank = 0, j = 0; j < col; j++ ) {
2089: for ( i = rank; i < row; i++ )
2090: mat[i][j] %= md;
2091: for ( i = rank; i < row; i++ )
2092: if ( mat[i][j] )
2093: break;
2094: if ( i == row ) continue;
2095: if ( i != rank ) {
2096: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
2097: k = rowstat[i]; rowstat[i] = rowstat[rank]; rowstat[rank] = k;
2098: }
2099: pivot = mat[rank];
2100: inv = invm(pivot[j],md);
2101: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
2102: if ( *pk ) {
2103: if ( *pk >= (unsigned int)md )
2104: *pk %= md;
2105: DMAR(*pk,inv,0,md,*pk)
2106: }
2107: for ( i = rank+1; i < row; i++ ) {
2108: t = mat[i];
1.8 ! noro 2109: if ( ( a = t[j] ) != 0 )
1.1 noro 2110: red_by_vect(md,t+j,pivot+j,md-a,col-j);
2111: }
2112: rank++;
2113: }
2114: return rank;
2115: }
2116:
2117: int generic_gauss_elim_sf(int **mat0,int row,int col,int md,int *colstat)
2118: {
2119: int i,j,k,l,inv,a,rank;
2120: unsigned int *t,*pivot,*pk;
2121: unsigned int **mat;
2122:
2123: mat = (unsigned int **)mat0;
2124: for ( rank = 0, j = 0; j < col; j++ ) {
2125: for ( i = rank; i < row; i++ )
2126: if ( mat[i][j] )
2127: break;
2128: if ( i == row ) {
2129: colstat[j] = 0;
2130: continue;
2131: } else
2132: colstat[j] = 1;
2133: if ( i != rank ) {
2134: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
2135: }
2136: pivot = mat[rank];
2137: inv = _invsf(pivot[j]);
2138: for ( k = j, pk = pivot+k; k < col; k++, pk++ )
2139: if ( *pk )
2140: *pk = _mulsf(*pk,inv);
2141: for ( i = rank+1; i < row; i++ ) {
2142: t = mat[i];
1.8 ! noro 2143: if ( ( a = t[j] ) != 0 )
1.1 noro 2144: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
2145: }
2146: rank++;
2147: }
2148: for ( j = col-1, l = rank-1; j >= 0; j-- )
2149: if ( colstat[j] ) {
2150: pivot = mat[l];
2151: for ( i = 0; i < l; i++ ) {
2152: t = mat[i];
1.8 ! noro 2153: if ( ( a = t[j] ) != 0 )
1.1 noro 2154: red_by_vect_sf(md,t+j,pivot+j,_chsgnsf(a),col-j);
2155: }
2156: l--;
2157: }
2158: return rank;
2159: }
2160:
2161: /* LU decomposition; a[i][i] = 1/U[i][i] */
2162:
2163: int lu_gfmmat(GFMMAT mat,unsigned int md,int *perm)
2164: {
2165: int row,col;
2166: int i,j,k;
2167: unsigned int *t,*pivot;
2168: unsigned int **a;
2169: unsigned int inv,m;
2170:
2171: row = mat->row; col = mat->col;
2172: a = mat->body;
2173: bzero(perm,row*sizeof(int));
2174:
2175: for ( i = 0; i < row; i++ )
2176: perm[i] = i;
2177: for ( k = 0; k < col; k++ ) {
2178: for ( i = k; i < row && !a[i][k]; i++ );
2179: if ( i == row )
2180: return 0;
2181: if ( i != k ) {
2182: j = perm[i]; perm[i] = perm[k]; perm[k] = j;
2183: t = a[i]; a[i] = a[k]; a[k] = t;
2184: }
2185: pivot = a[k];
2186: pivot[k] = inv = invm(pivot[k],md);
2187: for ( i = k+1; i < row; i++ ) {
2188: t = a[i];
1.8 ! noro 2189: if ( ( m = t[k] ) != 0 ) {
1.1 noro 2190: DMAR(inv,m,0,md,t[k])
2191: for ( j = k+1, m = md - t[k]; j < col; j++ )
2192: if ( pivot[j] ) {
2193: unsigned int tj;
2194:
2195: DMAR(m,pivot[j],t[j],md,tj)
2196: t[j] = tj;
2197: }
2198: }
2199: }
2200: }
2201: return 1;
2202: }
2203:
2204: /*
2205: Input
2206: a: a row x col matrix
2207: md : a modulus
2208:
2209: Output:
2210: return : d = the rank of mat
2211: a[0..(d-1)][0..(d-1)] : LU decomposition (a[i][i] = 1/U[i][i])
2212: rinfo: array of length row
2213: cinfo: array of length col
2214: i-th row in new a <-> rinfo[i]-th row in old a
2215: cinfo[j]=1 <=> j-th column is contained in the LU decomp.
2216: */
2217:
2218: int find_lhs_and_lu_mod(unsigned int **a,int row,int col,
2219: unsigned int md,int **rinfo,int **cinfo)
2220: {
2221: int i,j,k,d;
2222: int *rp,*cp;
2223: unsigned int *t,*pivot;
2224: unsigned int inv,m;
2225:
2226: *rinfo = rp = (int *)MALLOC_ATOMIC(row*sizeof(int));
2227: *cinfo = cp = (int *)MALLOC_ATOMIC(col*sizeof(int));
2228: for ( i = 0; i < row; i++ )
2229: rp[i] = i;
2230: for ( k = 0, d = 0; k < col; k++ ) {
2231: for ( i = d; i < row && !a[i][k]; i++ );
2232: if ( i == row ) {
2233: cp[k] = 0;
2234: continue;
2235: } else
2236: cp[k] = 1;
2237: if ( i != d ) {
2238: j = rp[i]; rp[i] = rp[d]; rp[d] = j;
2239: t = a[i]; a[i] = a[d]; a[d] = t;
2240: }
2241: pivot = a[d];
2242: pivot[k] = inv = invm(pivot[k],md);
2243: for ( i = d+1; i < row; i++ ) {
2244: t = a[i];
1.8 ! noro 2245: if ( ( m = t[k] ) != 0 ) {
1.1 noro 2246: DMAR(inv,m,0,md,t[k])
2247: for ( j = k+1, m = md - t[k]; j < col; j++ )
2248: if ( pivot[j] ) {
2249: unsigned int tj;
2250: DMAR(m,pivot[j],t[j],md,tj)
2251: t[j] = tj;
2252: }
2253: }
2254: }
2255: d++;
2256: }
2257: return d;
2258: }
2259:
2260: int lu_mod(unsigned int **a,int n,unsigned int md,int **rinfo)
2261: {
2262: int i,j,k;
2263: int *rp;
2264: unsigned int *t,*pivot;
2265: unsigned int inv,m;
2266:
2267: *rinfo = rp = (int *)MALLOC_ATOMIC(n*sizeof(int));
2268: for ( i = 0; i < n; i++ ) rp[i] = i;
2269: for ( k = 0; k < n; k++ ) {
2270: for ( i = k; i < n && !a[i][k]; i++ );
2271: if ( i == n ) return 0;
2272: if ( i != k ) {
2273: j = rp[i]; rp[i] = rp[k]; rp[k] = j;
2274: t = a[i]; a[i] = a[k]; a[k] = t;
2275: }
2276: pivot = a[k];
2277: inv = invm(pivot[k],md);
2278: for ( i = k+1; i < n; i++ ) {
2279: t = a[i];
1.8 ! noro 2280: if ( ( m = t[k] ) != 0 ) {
1.1 noro 2281: DMAR(inv,m,0,md,t[k])
2282: for ( j = k+1, m = md - t[k]; j < n; j++ )
2283: if ( pivot[j] ) {
2284: unsigned int tj;
2285: DMAR(m,pivot[j],t[j],md,tj)
2286: t[j] = tj;
2287: }
2288: }
2289: }
2290: }
2291: return 1;
2292: }
2293:
2294: /*
2295: Input
2296: a : n x n matrix; a result of LU-decomposition
2297: md : modulus
2298: b : n x l matrix
2299: Output
2300: b = a^(-1)b
2301: */
2302:
2303: void solve_by_lu_mod(int **a,int n,int md,int **b,int l,int normalize)
2304: {
2305: unsigned int *y,*c;
2306: int i,j,k;
2307: unsigned int t,m,m2;
2308:
1.8 ! noro 2309: y = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
! 2310: c = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
1.1 noro 2311: m2 = md>>1;
2312: for ( k = 0; k < l; k++ ) {
2313: /* copy b[.][k] to c */
2314: for ( i = 0; i < n; i++ )
2315: c[i] = (unsigned int)b[i][k];
2316: /* solve Ly=c */
2317: for ( i = 0; i < n; i++ ) {
2318: for ( t = c[i], j = 0; j < i; j++ )
2319: if ( a[i][j] ) {
2320: m = md - a[i][j];
2321: DMAR(m,y[j],t,md,t)
2322: }
2323: y[i] = t;
2324: }
2325: /* solve Uc=y */
2326: for ( i = n-1; i >= 0; i-- ) {
2327: for ( t = y[i], j =i+1; j < n; j++ )
2328: if ( a[i][j] ) {
2329: m = md - a[i][j];
2330: DMAR(m,c[j],t,md,t)
2331: }
2332: /* a[i][i] = 1/U[i][i] */
2333: DMAR(t,a[i][i],0,md,c[i])
2334: }
2335: /* copy c to b[.][k] with normalization */
2336: if ( normalize )
2337: for ( i = 0; i < n; i++ )
2338: b[i][k] = (int)(c[i]>m2 ? c[i]-md : c[i]);
2339: else
2340: for ( i = 0; i < n; i++ )
2341: b[i][k] = c[i];
2342: }
2343: }
2344:
2345: void Pleqm1(NODE arg,VECT *rp)
2346: {
2347: MAT m;
2348: VECT vect;
2349: pointer **mat;
2350: Z *v;
2351: Z q;
2352: int **wmat;
2353: int md,i,j,row,col,t,n,status;
2354:
2355: asir_assert(ARG0(arg),O_MAT,"leqm1");
2356: asir_assert(ARG1(arg),O_N,"leqm1");
1.2 noro 2357: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1.1 noro 2358: row = m->row; col = m->col; mat = m->body;
2359: wmat = (int **)almat(row,col);
2360: for ( i = 0; i < row; i++ )
2361: for ( j = 0; j < col; j++ )
2362: wmat[i][j] = remqi((Q)mat[i][j],md);
2363: status = gauss_elim_mod1(wmat,row,col,md);
2364: if ( status < 0 )
2365: *rp = 0;
2366: else if ( status > 0 )
2367: *rp = (VECT)ONE;
2368: else {
2369: n = col - 1;
2370: MKVECT(vect,n);
2371: for ( i = 0, v = (Z *)vect->body; i < n; i++ ) {
1.2 noro 2372: t = (md-wmat[i][n])%md; STOZ(t,v[i]);
1.1 noro 2373: }
2374: *rp = vect;
2375: }
2376: }
2377:
2378: int gauss_elim_mod1(int **mat,int row,int col,int md)
2379: {
2380: int i,j,k,inv,a,n;
2381: int *t,*pivot;
2382:
2383: n = col - 1;
2384: for ( j = 0; j < n; j++ ) {
2385: for ( i = j; i < row && !mat[i][j]; i++ );
2386: if ( i == row )
2387: return 1;
2388: if ( i != j ) {
2389: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2390: }
2391: pivot = mat[j];
2392: inv = invm(pivot[j],md);
2393: for ( k = j; k <= n; k++ )
2394: pivot[k] = dmar(pivot[k],inv,0,md);
2395: for ( i = j+1; i < row; i++ ) {
2396: t = mat[i];
2397: if ( i != j && (a = t[j]) )
2398: for ( k = j, a = md - a; k <= n; k++ )
2399: t[k] = dmar(pivot[k],a,t[k],md);
2400: }
2401: }
2402: for ( i = n; i < row && !mat[i][n]; i++ );
2403: if ( i == row ) {
2404: for ( j = n-1; j >= 0; j-- ) {
2405: for ( i = j-1, a = (md-mat[j][n])%md; i >= 0; i-- ) {
2406: mat[i][n] = dmar(mat[i][j],a,mat[i][n],md);
2407: mat[i][j] = 0;
2408: }
2409: }
2410: return 0;
2411: } else
2412: return -1;
2413: }
2414:
2415: void Pgeninvm(NODE arg,LIST *rp)
2416: {
2417: MAT m;
2418: pointer **mat;
2419: Z **tmat;
2420: Z q;
2421: unsigned int **wmat;
2422: int md,i,j,row,col,t,status;
2423: MAT mat1,mat2;
2424: NODE node1,node2;
2425:
2426: asir_assert(ARG0(arg),O_MAT,"leqm1");
2427: asir_assert(ARG1(arg),O_N,"leqm1");
1.2 noro 2428: m = (MAT)ARG0(arg); md = ZTOS((Q)ARG1(arg));
1.1 noro 2429: row = m->row; col = m->col; mat = m->body;
2430: wmat = (unsigned int **)almat(row,col+row);
2431: for ( i = 0; i < row; i++ ) {
2432: bzero((char *)wmat[i],(col+row)*sizeof(int));
2433: for ( j = 0; j < col; j++ )
2434: wmat[i][j] = remqi((Q)mat[i][j],md);
2435: }
2436: status = gauss_elim_geninv_mod(wmat,row,col,md);
2437: if ( status > 0 )
2438: *rp = 0;
2439: else {
2440: MKMAT(mat1,col,row); MKMAT(mat2,row-col,row);
2441: for ( i = 0, tmat = (Z **)mat1->body; i < col; i++ )
2442: for ( j = 0; j < row; j++ )
1.2 noro 2443: UTOZ(wmat[i][j+col],tmat[i][j]);
1.1 noro 2444: for ( tmat = (Z **)mat2->body; i < row; i++ )
2445: for ( j = 0; j < row; j++ )
1.2 noro 2446: UTOZ(wmat[i][j+col],tmat[i-col][j]);
1.1 noro 2447: MKNODE(node2,mat2,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
2448: }
2449: }
2450:
2451: int gauss_elim_geninv_mod(unsigned int **mat,int row,int col,int md)
2452: {
2453: int i,j,k,inv,a,n,m;
2454: unsigned int *t,*pivot;
2455:
2456: n = col; m = row+col;
2457: for ( j = 0; j < n; j++ ) {
2458: for ( i = j; i < row && !mat[i][j]; i++ );
2459: if ( i == row )
2460: return 1;
2461: if ( i != j ) {
2462: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2463: }
2464: pivot = mat[j];
2465: inv = invm(pivot[j],md);
2466: for ( k = j; k < m; k++ )
2467: pivot[k] = dmar(pivot[k],inv,0,md);
2468: for ( i = j+1; i < row; i++ ) {
2469: t = mat[i];
1.8 ! noro 2470: if ( ( a = t[j] ) != 0 )
1.1 noro 2471: for ( k = j, a = md - a; k < m; k++ )
2472: t[k] = dmar(pivot[k],a,t[k],md);
2473: }
2474: }
2475: for ( j = n-1; j >= 0; j-- ) {
2476: pivot = mat[j];
2477: for ( i = j-1; i >= 0; i-- ) {
2478: t = mat[i];
1.8 ! noro 2479: if ( ( a = t[j] ) != 0 )
1.1 noro 2480: for ( k = j, a = md - a; k < m; k++ )
2481: t[k] = dmar(pivot[k],a,t[k],md);
2482: }
2483: }
2484: return 0;
2485: }
2486:
2487: void Psolve_by_lu_gfmmat(NODE arg,VECT *rp)
2488: {
2489: GFMMAT lu;
2490: Z *perm,*rhs,*v;
2491: int n,i;
2492: unsigned int md;
2493: unsigned int *b,*sol;
2494: VECT r;
2495:
2496: lu = (GFMMAT)ARG0(arg);
2497: perm = (Z *)BDY((VECT)ARG1(arg));
2498: rhs = (Z *)BDY((VECT)ARG2(arg));
1.2 noro 2499: md = (unsigned int)ZTOS((Z)ARG3(arg));
1.1 noro 2500: n = lu->col;
2501: b = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
2502: sol = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
2503: for ( i = 0; i < n; i++ )
1.2 noro 2504: b[i] = ZTOS(rhs[ZTOS(perm[i])]);
1.1 noro 2505: solve_by_lu_gfmmat(lu,md,b,sol);
2506: MKVECT(r,n);
2507: for ( i = 0, v = (Z *)r->body; i < n; i++ )
1.2 noro 2508: UTOZ(sol[i],v[i]);
1.1 noro 2509: *rp = r;
2510: }
2511:
2512: void solve_by_lu_gfmmat(GFMMAT lu,unsigned int md,
2513: unsigned int *b,unsigned int *x)
2514: {
2515: int n;
2516: unsigned int **a;
2517: unsigned int *y;
2518: int i,j;
2519: unsigned int t,m;
2520:
2521: n = lu->col;
2522: a = lu->body;
2523: y = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
2524: /* solve Ly=b */
2525: for ( i = 0; i < n; i++ ) {
2526: for ( t = b[i], j = 0; j < i; j++ )
2527: if ( a[i][j] ) {
2528: m = md - a[i][j];
2529: DMAR(m,y[j],t,md,t)
2530: }
2531: y[i] = t;
2532: }
2533: /* solve Ux=y */
2534: for ( i = n-1; i >= 0; i-- ) {
2535: for ( t = y[i], j =i+1; j < n; j++ )
2536: if ( a[i][j] ) {
2537: m = md - a[i][j];
2538: DMAR(m,x[j],t,md,t)
2539: }
2540: /* a[i][i] = 1/U[i][i] */
2541: DMAR(t,a[i][i],0,md,x[i])
2542: }
2543: }
2544:
2545: #if 0
2546: void Plu_mat(NODE arg,LIST *rp)
2547: {
2548: MAT m,lu;
2549: Q dn;
2550: Q *v;
2551: int n,i;
2552: int *iperm;
2553: VECT perm;
2554: NODE n0;
2555:
2556: asir_assert(ARG0(arg),O_MAT,"lu_mat");
2557: m = (MAT)ARG0(arg);
2558: n = m->row;
2559: MKMAT(lu,n,n);
2560: lu_dec_cr(m,lu,&dn,&iperm);
2561: MKVECT(perm,n);
2562: for ( i = 0, v = (Q *)perm->body; i < n; i++ )
1.2 noro 2563: STOZ(iperm[i],v[i]);
1.1 noro 2564: n0 = mknode(3,lu,dn,perm);
2565: MKLIST(*rp,n0);
2566: }
2567: #endif
2568:
2569: void Plu_gfmmat(NODE arg,LIST *rp)
2570: {
2571: MAT m;
2572: GFMMAT mm;
2573: unsigned int md;
2574: int i,row,col,status;
2575: int *iperm;
2576: Z *v;
2577: VECT perm;
2578: NODE n0;
2579:
2580: asir_assert(ARG0(arg),O_MAT,"lu_gfmmat");
2581: asir_assert(ARG1(arg),O_N,"lu_gfmmat");
1.2 noro 2582: m = (MAT)ARG0(arg); md = (unsigned int)ZTOS((Q)ARG1(arg));
1.1 noro 2583: mat_to_gfmmat(m,md,&mm);
2584: row = m->row;
2585: col = m->col;
2586: iperm = (int *)MALLOC_ATOMIC(row*sizeof(int));
2587: status = lu_gfmmat(mm,md,iperm);
2588: if ( !status )
2589: n0 = 0;
2590: else {
2591: MKVECT(perm,row);
2592: for ( i = 0, v = (Z *)perm->body; i < row; i++ )
1.2 noro 2593: STOZ(iperm[i],v[i]);
1.1 noro 2594: n0 = mknode(2,mm,perm);
2595: }
2596: MKLIST(*rp,n0);
2597: }
2598:
2599: void Pmat_to_gfmmat(NODE arg,GFMMAT *rp)
2600: {
2601: MAT m;
2602: unsigned int md;
2603:
2604: asir_assert(ARG0(arg),O_MAT,"mat_to_gfmmat");
2605: asir_assert(ARG1(arg),O_N,"mat_to_gfmmat");
1.2 noro 2606: m = (MAT)ARG0(arg); md = (unsigned int)ZTOS((Q)ARG1(arg));
1.1 noro 2607: mat_to_gfmmat(m,md,rp);
2608: }
2609:
2610: void mat_to_gfmmat(MAT m,unsigned int md,GFMMAT *rp)
2611: {
2612: unsigned int **wmat;
2613: unsigned int t;
2614: Z **mat;
2615: Z q;
2616: int i,j,row,col;
2617:
2618: row = m->row; col = m->col; mat = (Z **)m->body;
2619: wmat = (unsigned int **)almat(row,col);
2620: for ( i = 0; i < row; i++ ) {
2621: bzero((char *)wmat[i],col*sizeof(unsigned int));
2622: for ( j = 0; j < col; j++ )
2623: wmat[i][j] = remqi((Q)mat[i][j],md);
2624: }
2625: TOGFMMAT(row,col,wmat,*rp);
2626: }
2627:
2628: void Pgeninvm_swap(NODE arg,LIST *rp)
2629: {
2630: MAT m;
2631: pointer **mat;
2632: Z **tmat;
2633: Z *tvect;
2634: Z q;
2635: unsigned int **wmat,**invmat;
2636: int *index;
2637: unsigned int t,md;
2638: int i,j,row,col,status;
2639: MAT mat1;
2640: VECT vect1;
2641: NODE node1,node2;
2642:
2643: asir_assert(ARG0(arg),O_MAT,"geninvm_swap");
2644: asir_assert(ARG1(arg),O_N,"geninvm_swap");
1.2 noro 2645: m = (MAT)ARG0(arg); md = ZTOS((Z)ARG1(arg));
1.1 noro 2646: row = m->row; col = m->col; mat = m->body;
2647: wmat = (unsigned int **)almat(row,col+row);
2648: for ( i = 0; i < row; i++ ) {
2649: bzero((char *)wmat[i],(col+row)*sizeof(int));
2650: for ( j = 0; j < col; j++ )
2651: wmat[i][j] = remqi((Q)mat[i][j],md);
2652: wmat[i][col+i] = 1;
2653: }
2654: status = gauss_elim_geninv_mod_swap(wmat,row,col,md,&invmat,&index);
2655: if ( status > 0 )
2656: *rp = 0;
2657: else {
2658: MKMAT(mat1,col,col);
2659: for ( i = 0, tmat = (Z **)mat1->body; i < col; i++ )
2660: for ( j = 0; j < col; j++ )
1.2 noro 2661: UTOZ(invmat[i][j],tmat[i][j]);
1.1 noro 2662: MKVECT(vect1,row);
2663: for ( i = 0, tvect = (Z *)vect1->body; i < row; i++ )
1.2 noro 2664: STOZ(index[i],tvect[i]);
1.1 noro 2665: MKNODE(node2,vect1,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
2666: }
2667: }
2668:
2669: int gauss_elim_geninv_mod_swap(unsigned int **mat,int row,int col,unsigned int md,
2670: unsigned int ***invmatp,int **indexp)
2671: {
2672: int i,j,k,inv,a,n,m;
2673: unsigned int *t,*pivot,*s;
2674: int *index;
2675: unsigned int **invmat;
2676:
2677: n = col; m = row+col;
2678: *indexp = index = (int *)MALLOC_ATOMIC(row*sizeof(int));
2679: for ( i = 0; i < row; i++ )
2680: index[i] = i;
2681: for ( j = 0; j < n; j++ ) {
2682: for ( i = j; i < row && !mat[i][j]; i++ );
2683: if ( i == row ) {
2684: *indexp = 0; *invmatp = 0; return 1;
2685: }
2686: if ( i != j ) {
2687: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2688: k = index[i]; index[i] = index[j]; index[j] = k;
2689: }
2690: pivot = mat[j];
2691: inv = (unsigned int)invm(pivot[j],md);
2692: for ( k = j; k < m; k++ )
2693: if ( pivot[k] )
2694: pivot[k] = (unsigned int)dmar(pivot[k],inv,0,md);
2695: for ( i = j+1; i < row; i++ ) {
2696: t = mat[i];
1.8 ! noro 2697: if ( ( a = t[j] ) != 0 )
1.1 noro 2698: for ( k = j, a = md - a; k < m; k++ )
2699: if ( pivot[k] )
2700: t[k] = dmar(pivot[k],a,t[k],md);
2701: }
2702: }
2703: for ( j = n-1; j >= 0; j-- ) {
2704: pivot = mat[j];
2705: for ( i = j-1; i >= 0; i-- ) {
2706: t = mat[i];
1.8 ! noro 2707: if ( ( a = t[j] ) != 0 )
1.1 noro 2708: for ( k = j, a = md - a; k < m; k++ )
2709: if ( pivot[k] )
2710: t[k] = dmar(pivot[k],a,t[k],md);
2711: }
2712: }
2713: *invmatp = invmat = (unsigned int **)almat(col,col);
2714: for ( i = 0; i < col; i++ )
2715: for ( j = 0, s = invmat[i], t = mat[i]; j < col; j++ )
2716: s[j] = t[col+index[j]];
2717: return 0;
2718: }
2719:
2720: int gauss_elim_geninv_sf_swap(int **mat,int row,int col, int ***invmatp,int **indexp);
2721:
2722: void Pgeninv_sf_swap(NODE arg,LIST *rp)
2723: {
2724: MAT m;
2725: GFS **mat,**tmat;
2726: Z *tvect;
2727: GFS q;
2728: int **wmat,**invmat;
2729: int *index;
2730: unsigned int t;
2731: int i,j,row,col,status;
2732: MAT mat1;
2733: VECT vect1;
2734: NODE node1,node2;
2735:
2736: asir_assert(ARG0(arg),O_MAT,"geninv_sf_swap");
2737: m = (MAT)ARG0(arg);
2738: row = m->row; col = m->col; mat = (GFS **)m->body;
2739: wmat = (int **)almat(row,col+row);
2740: for ( i = 0; i < row; i++ ) {
2741: bzero((char *)wmat[i],(col+row)*sizeof(int));
2742: for ( j = 0; j < col; j++ )
1.8 ! noro 2743: if ( ( q = (GFS)mat[i][j] ) != 0 )
1.1 noro 2744: wmat[i][j] = FTOIF(CONT(q));
2745: wmat[i][col+i] = _onesf();
2746: }
2747: status = gauss_elim_geninv_sf_swap(wmat,row,col,&invmat,&index);
2748: if ( status > 0 )
2749: *rp = 0;
2750: else {
2751: MKMAT(mat1,col,col);
2752: for ( i = 0, tmat = (GFS **)mat1->body; i < col; i++ )
2753: for ( j = 0; j < col; j++ )
1.8 ! noro 2754: if ( ( t = invmat[i][j] ) != 0 ) {
1.1 noro 2755: MKGFS(IFTOF(t),tmat[i][j]);
2756: }
2757: MKVECT(vect1,row);
2758: for ( i = 0, tvect = (Z *)vect1->body; i < row; i++ )
1.2 noro 2759: STOZ(index[i],tvect[i]);
1.1 noro 2760: MKNODE(node2,vect1,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
2761: }
2762: }
2763:
2764: int gauss_elim_geninv_sf_swap(int **mat,int row,int col, int ***invmatp,int **indexp)
2765: {
2766: int i,j,k,inv,a,n,m,u;
2767: int *t,*pivot,*s;
2768: int *index;
2769: int **invmat;
2770:
2771: n = col; m = row+col;
2772: *indexp = index = (int *)MALLOC_ATOMIC(row*sizeof(int));
2773: for ( i = 0; i < row; i++ )
2774: index[i] = i;
2775: for ( j = 0; j < n; j++ ) {
2776: for ( i = j; i < row && !mat[i][j]; i++ );
2777: if ( i == row ) {
2778: *indexp = 0; *invmatp = 0; return 1;
2779: }
2780: if ( i != j ) {
2781: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
2782: k = index[i]; index[i] = index[j]; index[j] = k;
2783: }
2784: pivot = mat[j];
2785: inv = _invsf(pivot[j]);
2786: for ( k = j; k < m; k++ )
2787: if ( pivot[k] )
2788: pivot[k] = _mulsf(pivot[k],inv);
2789: for ( i = j+1; i < row; i++ ) {
2790: t = mat[i];
1.8 ! noro 2791: if ( ( a = t[j] ) != 0 )
1.1 noro 2792: for ( k = j, a = _chsgnsf(a); k < m; k++ )
2793: if ( pivot[k] ) {
2794: u = _mulsf(pivot[k],a);
2795: t[k] = _addsf(u,t[k]);
2796: }
2797: }
2798: }
2799: for ( j = n-1; j >= 0; j-- ) {
2800: pivot = mat[j];
2801: for ( i = j-1; i >= 0; i-- ) {
2802: t = mat[i];
1.8 ! noro 2803: if ( ( a = t[j] ) != 0 )
1.1 noro 2804: for ( k = j, a = _chsgnsf(a); k < m; k++ )
2805: if ( pivot[k] ) {
2806: u = _mulsf(pivot[k],a);
2807: t[k] = _addsf(u,t[k]);
2808: }
2809: }
2810: }
2811: *invmatp = invmat = (int **)almat(col,col);
2812: for ( i = 0; i < col; i++ )
2813: for ( j = 0, s = invmat[i], t = mat[i]; j < col; j++ )
2814: s[j] = t[col+index[j]];
2815: return 0;
2816: }
2817:
2818: void inner_product_int(Z *a,Z *b,int n,Z *r)
2819: {
2820: int i;
2821: Z t;
2822:
2823: t = 0;
2824: for ( i = 0; i < n; i++ )
2825: muladdtoz(a[i],b[i],&t);
2826: *r = t;
2827: }
2828:
2829: void Pmul_mat_vect_int(NODE arg,VECT *rp)
2830: {
2831: MAT mat;
2832: VECT vect,r;
2833: int row,col,i;
2834:
2835: mat = (MAT)ARG0(arg);
2836: vect = (VECT)ARG1(arg);
2837: row = mat->row;
2838: col = mat->col;
2839: MKVECT(r,row);
2840: for ( i = 0; i < row; i++ ) {
2841: inner_product_int((Z *)mat->body[i],(Z *)vect->body,col,(Z *)&r->body[i]);
2842: }
2843: *rp = r;
2844: }
2845:
2846: void Pnbpoly_up2(NODE arg,GF2N *rp)
2847: {
2848: int m,type,ret;
2849: UP2 r;
2850:
1.2 noro 2851: m = ZTOS((Z)ARG0(arg));
2852: type = ZTOS((Z)ARG1(arg));
1.1 noro 2853: ret = generate_ONB_polynomial(&r,m,type);
2854: if ( ret == 0 )
2855: MKGF2N(r,*rp);
2856: else
2857: *rp = 0;
2858: }
2859:
2860: void Px962_irredpoly_up2(NODE arg,GF2N *rp)
2861: {
2862: int m,ret,w;
2863: GF2N prev;
2864: UP2 r;
2865:
1.2 noro 2866: m = ZTOS((Q)ARG0(arg));
1.1 noro 2867: prev = (GF2N)ARG1(arg);
2868: if ( !prev ) {
2869: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2870: bzero((char *)r->b,w*sizeof(unsigned int));
2871: } else {
2872: r = prev->body;
2873: if ( degup2(r) != m ) {
2874: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2875: bzero((char *)r->b,w*sizeof(unsigned int));
2876: }
2877: }
2878: ret = _generate_irreducible_polynomial(r,m);
2879: if ( ret == 0 )
2880: MKGF2N(r,*rp);
2881: else
2882: *rp = 0;
2883: }
2884:
2885: void Pirredpoly_up2(NODE arg,GF2N *rp)
2886: {
2887: int m,ret,w;
2888: GF2N prev;
2889: UP2 r;
2890:
1.2 noro 2891: m = ZTOS((Q)ARG0(arg));
1.1 noro 2892: prev = (GF2N)ARG1(arg);
2893: if ( !prev ) {
2894: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2895: bzero((char *)r->b,w*sizeof(unsigned int));
2896: } else {
2897: r = prev->body;
2898: if ( degup2(r) != m ) {
2899: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
2900: bzero((char *)r->b,w*sizeof(unsigned int));
2901: }
2902: }
2903: ret = _generate_good_irreducible_polynomial(r,m);
2904: if ( ret == 0 )
2905: MKGF2N(r,*rp);
2906: else
2907: *rp = 0;
2908: }
2909:
2910: void Pmat_swap_row_destructive(NODE arg, MAT *m)
2911: {
2912: int i1,i2;
2913: pointer *t;
2914: MAT mat;
2915:
2916: asir_assert(ARG0(arg),O_MAT,"mat_swap_row_destructive");
2917: asir_assert(ARG1(arg),O_N,"mat_swap_row_destructive");
2918: asir_assert(ARG2(arg),O_N,"mat_swap_row_destructive");
2919: mat = (MAT)ARG0(arg);
1.2 noro 2920: i1 = ZTOS((Q)ARG1(arg));
2921: i2 = ZTOS((Q)ARG2(arg));
1.1 noro 2922: if ( i1 < 0 || i2 < 0 || i1 >= mat->row || i2 >= mat->row )
2923: error("mat_swap_row_destructive : Out of range");
2924: t = mat->body[i1];
2925: mat->body[i1] = mat->body[i2];
2926: mat->body[i2] = t;
2927: *m = mat;
2928: }
2929:
2930: void Pmat_swap_col_destructive(NODE arg, MAT *m)
2931: {
2932: int j1,j2,i,n;
2933: pointer *mi;
2934: pointer t;
2935: MAT mat;
2936:
2937: asir_assert(ARG0(arg),O_MAT,"mat_swap_col_destructive");
2938: asir_assert(ARG1(arg),O_N,"mat_swap_col_destructive");
2939: asir_assert(ARG2(arg),O_N,"mat_swap_col_destructive");
2940: mat = (MAT)ARG0(arg);
1.2 noro 2941: j1 = ZTOS((Q)ARG1(arg));
2942: j2 = ZTOS((Q)ARG2(arg));
1.1 noro 2943: if ( j1 < 0 || j2 < 0 || j1 >= mat->col || j2 >= mat->col )
2944: error("mat_swap_col_destructive : Out of range");
2945: n = mat->row;
2946: for ( i = 0; i < n; i++ ) {
2947: mi = mat->body[i];
2948: t = mi[j1]; mi[j1] = mi[j2]; mi[j2] = t;
2949: }
2950: *m = mat;
2951: }
2952: /*
2953: * f = type 'type' normal polynomial of degree m if exists
2954: * IEEE P1363 A.7.2
2955: *
2956: * return value : 0 --- exists
2957: * 1 --- does not exist
2958: * -1 --- failure (memory allocation error)
2959: */
2960:
2961: int generate_ONB_polynomial(UP2 *rp,int m,int type)
2962: {
2963: int i,r;
2964: int w;
2965: UP2 f,f0,f1,f2,t;
2966:
2967: w = (m>>5)+1;
2968: switch ( type ) {
2969: case 1:
2970: if ( !TypeT_NB_check(m,1) ) return 1;
2971: NEWUP2(f,w); *rp = f; f->w = w;
2972: /* set all the bits */
2973: for ( i = 0; i < w; i++ )
2974: f->b[i] = 0xffffffff;
2975: /* mask the top word if necessary */
1.8 ! noro 2976: if ( ( r = (m+1)&31 ) != 0 )
1.1 noro 2977: f->b[w-1] &= (1<<r)-1;
2978: return 0;
2979: break;
2980: case 2:
2981: if ( !TypeT_NB_check(m,2) ) return 1;
2982: NEWUP2(f,w); *rp = f;
2983: W_NEWUP2(f0,w);
2984: W_NEWUP2(f1,w);
2985: W_NEWUP2(f2,w);
2986:
2987: /* recursion for genrating Type II normal polynomial */
2988:
2989: /* f0 = 1, f1 = t+1 */
2990: f0->w = 1; f0->b[0] = 1;
2991: f1->w = 1; f1->b[0] = 3;
2992: for ( i = 2; i <= m; i++ ) {
2993: /* f2 = t*f1+f0 */
2994: _bshiftup2(f1,-1,f2);
2995: _addup2_destructive(f2,f0);
2996: /* cyclic change of the variables */
2997: t = f0; f0 = f1; f1 = f2; f2 = t;
2998: }
2999: _copyup2(f1,f);
3000: return 0;
3001: break;
3002: default:
3003: return -1;
3004: break;
3005: }
3006: }
3007:
3008: /*
3009: * f = an irreducible trinomial or pentanomial of degree d 'after' f
3010: * return value : 0 --- exists
3011: * 1 --- does not exist (exhaustion)
3012: */
3013:
3014: int _generate_irreducible_polynomial(UP2 f,int d)
3015: {
3016: int ret,i,j,k,nz,i0,j0,k0;
3017: int w;
3018: unsigned int *fd;
3019:
3020: /*
3021: * if f = x^d+x^i+1 then i0 <- i, j0 <- 0, k0 <-0.
3022: * if f = x^d+x^k+x^j+x^i+1 (k>j>i) then i0 <- i, j0 <- j, k0 <-k.
3023: * otherwise i0,j0,k0 is set to 0.
3024: */
3025:
3026: fd = f->b;
3027: w = (d>>5)+1;
3028: if ( f->w && (d==degup2(f)) ) {
3029: for ( nz = 0, i = d; i >= 0; i-- )
3030: if ( fd[i>>5]&(1<<(i&31)) ) nz++;
3031: switch ( nz ) {
3032: case 3:
3033: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3034: /* reset i0-th bit */
3035: fd[i0>>5] &= ~(1<<(i0&31));
3036: j0 = k0 = 0;
3037: break;
3038: case 5:
3039: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3040: /* reset i0-th bit */
3041: fd[i0>>5] &= ~(1<<(i0&31));
3042: for ( j0 = i0+1; !(fd[j0>>5]&(1<<(j0&31))) ; j0++ );
3043: /* reset j0-th bit */
3044: fd[j0>>5] &= ~(1<<(j0&31));
3045: for ( k0 = j0+1; !(fd[k0>>5]&(1<<(k0&31))) ; k0++ );
3046: /* reset k0-th bit */
3047: fd[k0>>5] &= ~(1<<(k0&31));
3048: break;
3049: default:
3050: f->w = 0; break;
3051: }
3052: } else
3053: f->w = 0;
3054:
3055: if ( !f->w ) {
3056: fd = f->b;
3057: f->w = w; fd[0] |= 1; fd[d>>5] |= (1<<(d&31));
3058: i0 = j0 = k0 = 0;
3059: }
3060: /* if j0 > 0 then f is already a pentanomial */
3061: if ( j0 > 0 ) goto PENTA;
3062:
3063: /* searching for an irreducible trinomial */
3064:
3065: for ( i = 1; 2*i <= d; i++ ) {
3066: /* skip the polynomials 'before' f */
3067: if ( i < i0 ) continue;
3068: if ( i == i0 ) { i0 = 0; continue; }
3069: /* set i-th bit */
3070: fd[i>>5] |= (1<<(i&31));
3071: ret = irredcheck_dddup2(f);
3072: if ( ret == 1 ) return 0;
3073: /* reset i-th bit */
3074: fd[i>>5] &= ~(1<<(i&31));
3075: }
3076:
3077: /* searching for an irreducible pentanomial */
3078: PENTA:
3079: for ( i = 1; i < d; i++ ) {
3080: /* skip the polynomials 'before' f */
3081: if ( i < i0 ) continue;
3082: if ( i == i0 ) i0 = 0;
3083: /* set i-th bit */
3084: fd[i>>5] |= (1<<(i&31));
3085: for ( j = i+1; j < d; j++ ) {
3086: /* skip the polynomials 'before' f */
3087: if ( j < j0 ) continue;
3088: if ( j == j0 ) j0 = 0;
3089: /* set j-th bit */
3090: fd[j>>5] |= (1<<(j&31));
3091: for ( k = j+1; k < d; k++ ) {
3092: /* skip the polynomials 'before' f */
3093: if ( k < k0 ) continue;
3094: else if ( k == k0 ) { k0 = 0; continue; }
3095: /* set k-th bit */
3096: fd[k>>5] |= (1<<(k&31));
3097: ret = irredcheck_dddup2(f);
3098: if ( ret == 1 ) return 0;
3099: /* reset k-th bit */
3100: fd[k>>5] &= ~(1<<(k&31));
3101: }
3102: /* reset j-th bit */
3103: fd[j>>5] &= ~(1<<(j&31));
3104: }
3105: /* reset i-th bit */
3106: fd[i>>5] &= ~(1<<(i&31));
3107: }
3108: /* exhausted */
3109: return 1;
3110: }
3111:
3112: /*
3113: * f = an irreducible trinomial or pentanomial of degree d 'after' f
3114: *
3115: * searching strategy:
3116: * trinomial x^d+x^i+1:
3117: * i is as small as possible.
3118: * trinomial x^d+x^i+x^j+x^k+1:
3119: * i is as small as possible.
3120: * For such i, j is as small as possible.
3121: * For such i and j, 'k' is as small as possible.
3122: *
3123: * return value : 0 --- exists
3124: * 1 --- does not exist (exhaustion)
3125: */
3126:
3127: int _generate_good_irreducible_polynomial(UP2 f,int d)
3128: {
3129: int ret,i,j,k,nz,i0,j0,k0;
3130: int w;
3131: unsigned int *fd;
3132:
3133: /*
3134: * if f = x^d+x^i+1 then i0 <- i, j0 <- 0, k0 <-0.
3135: * if f = x^d+x^k+x^j+x^i+1 (k>j>i) then i0 <- i, j0 <- j, k0 <-k.
3136: * otherwise i0,j0,k0 is set to 0.
3137: */
3138:
3139: fd = f->b;
3140: w = (d>>5)+1;
3141: if ( f->w && (d==degup2(f)) ) {
3142: for ( nz = 0, i = d; i >= 0; i-- )
3143: if ( fd[i>>5]&(1<<(i&31)) ) nz++;
3144: switch ( nz ) {
3145: case 3:
3146: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3147: /* reset i0-th bit */
3148: fd[i0>>5] &= ~(1<<(i0&31));
3149: j0 = k0 = 0;
3150: break;
3151: case 5:
3152: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
3153: /* reset i0-th bit */
3154: fd[i0>>5] &= ~(1<<(i0&31));
3155: for ( j0 = i0+1; !(fd[j0>>5]&(1<<(j0&31))) ; j0++ );
3156: /* reset j0-th bit */
3157: fd[j0>>5] &= ~(1<<(j0&31));
3158: for ( k0 = j0+1; !(fd[k0>>5]&(1<<(k0&31))) ; k0++ );
3159: /* reset k0-th bit */
3160: fd[k0>>5] &= ~(1<<(k0&31));
3161: break;
3162: default:
3163: f->w = 0; break;
3164: }
3165: } else
3166: f->w = 0;
3167:
3168: if ( !f->w ) {
3169: fd = f->b;
3170: f->w = w; fd[0] |= 1; fd[d>>5] |= (1<<(d&31));
3171: i0 = j0 = k0 = 0;
3172: }
3173: /* if j0 > 0 then f is already a pentanomial */
3174: if ( j0 > 0 ) goto PENTA;
3175:
3176: /* searching for an irreducible trinomial */
3177:
3178: for ( i = 1; 2*i <= d; i++ ) {
3179: /* skip the polynomials 'before' f */
3180: if ( i < i0 ) continue;
3181: if ( i == i0 ) { i0 = 0; continue; }
3182: /* set i-th bit */
3183: fd[i>>5] |= (1<<(i&31));
3184: ret = irredcheck_dddup2(f);
3185: if ( ret == 1 ) return 0;
3186: /* reset i-th bit */
3187: fd[i>>5] &= ~(1<<(i&31));
3188: }
3189:
3190: /* searching for an irreducible pentanomial */
3191: PENTA:
3192: for ( i = 3; i < d; i++ ) {
3193: /* skip the polynomials 'before' f */
3194: if ( i < i0 ) continue;
3195: if ( i == i0 ) i0 = 0;
3196: /* set i-th bit */
3197: fd[i>>5] |= (1<<(i&31));
3198: for ( j = 2; j < i; j++ ) {
3199: /* skip the polynomials 'before' f */
3200: if ( j < j0 ) continue;
3201: if ( j == j0 ) j0 = 0;
3202: /* set j-th bit */
3203: fd[j>>5] |= (1<<(j&31));
3204: for ( k = 1; k < j; k++ ) {
3205: /* skip the polynomials 'before' f */
3206: if ( k < k0 ) continue;
3207: else if ( k == k0 ) { k0 = 0; continue; }
3208: /* set k-th bit */
3209: fd[k>>5] |= (1<<(k&31));
3210: ret = irredcheck_dddup2(f);
3211: if ( ret == 1 ) return 0;
3212: /* reset k-th bit */
3213: fd[k>>5] &= ~(1<<(k&31));
3214: }
3215: /* reset j-th bit */
3216: fd[j>>5] &= ~(1<<(j&31));
3217: }
3218: /* reset i-th bit */
3219: fd[i>>5] &= ~(1<<(i&31));
3220: }
3221: /* exhausted */
3222: return 1;
3223: }
3224:
3225: void printqmat(Q **mat,int row,int col)
3226: {
3227: int i,j;
3228:
3229: for ( i = 0; i < row; i++ ) {
3230: for ( j = 0; j < col; j++ ) {
3231: printnum((Num)mat[i][j]); printf(" ");
3232: }
3233: printf("\n");
3234: }
3235: }
3236:
3237: void printimat(int **mat,int row,int col)
3238: {
3239: int i,j;
3240:
3241: for ( i = 0; i < row; i++ ) {
3242: for ( j = 0; j < col; j++ ) {
3243: printf("%d ",mat[i][j]);
3244: }
3245: printf("\n");
3246: }
3247: }
3248:
3249: void Pnd_det(NODE arg,P *rp)
3250: {
3251: if ( argc(arg) == 1 )
3252: nd_det(0,ARG0(arg),rp);
3253: else
1.2 noro 3254: nd_det(ZTOS((Q)ARG1(arg)),ARG0(arg),rp);
1.1 noro 3255: }
3256:
3257: void Pmat_col(NODE arg,VECT *rp)
3258: {
3259: int i,j,n;
3260: MAT mat;
3261: VECT vect;
3262:
3263: asir_assert(ARG0(arg),O_MAT,"mat_col");
3264: asir_assert(ARG1(arg),O_N,"mat_col");
3265: mat = (MAT)ARG0(arg);
1.2 noro 3266: j = ZTOS((Q)ARG1(arg));
1.1 noro 3267: if ( j < 0 || j >= mat->col) {
3268: error("mat_col : Out of range");
3269: }
3270: n = mat->row;
3271: MKVECT(vect,n);
3272: for(i=0; i<n; i++) {
3273: BDY(vect)[i] = BDY(mat)[i][j];
3274: }
3275: *rp = vect;
3276: }
3277:
3278: NODE triangleq(NODE e)
3279: {
3280: int n,i,k;
3281: V v;
3282: VL vl;
3283: P *p;
3284: NODE r,r1;
3285:
3286: n = length(e);
3287: p = (P *)MALLOC(n*sizeof(P));
3288: for ( i = 0; i < n; i++, e = NEXT(e) ) p[i] = (P)BDY(e);
3289: i = 0;
3290: while ( 1 ) {
3291: for ( ; i < n && !p[i]; i++ );
3292: if ( i == n ) break;
3293: if ( OID(p[i]) == O_N ) return 0;
3294: v = p[i]->v;
3295: for ( k = i+1; k < n; k++ )
3296: if ( p[k] ) {
3297: if ( OID(p[k]) == O_N ) return 0;
3298: if ( p[k]->v == v ) p[k] = 0;
3299: }
3300: i++;
3301: }
3302: for ( r = 0, i = 0; i < n; i++ ) {
3303: if ( p[i] ) {
3304: MKNODE(r1,p[i],r); r = r1;
3305: }
3306: }
3307: return r;
3308: }
3309:
3310: void Ptriangleq(NODE arg,LIST *rp)
3311: {
3312: NODE ret;
3313:
3314: asir_assert(ARG0(arg),O_LIST,"sparseleq");
3315: ret = triangleq(BDY((LIST)ARG0(arg)));
3316: MKLIST(*rp,ret);
3317: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>