Annotation of OpenXM_contrib2/asir2000/builtin/array.c, Revision 1.1
1.1 ! noro 1: /* $OpenXM: OpenXM/src/asir99/builtin/array.c,v 1.2 1999/11/23 07:14:14 noro Exp $ */
! 2: #include "ca.h"
! 3: #include "base.h"
! 4: #include "parse.h"
! 5: #include "inline.h"
! 6: /*
! 7: #undef DMAR
! 8: #define DMAR(a1,a2,a3,d,r) (r)=dmar(a1,a2,a3,d);
! 9: */
! 10:
! 11: extern int Print; /* XXX */
! 12:
! 13: void solve_by_lu_gfmmat(GFMMAT,unsigned int,unsigned int *,unsigned int *);
! 14: int lu_gfmmat(GFMMAT,unsigned int,int *);
! 15: void mat_to_gfmmat(MAT,unsigned int,GFMMAT *);
! 16:
! 17: int generic_gauss_elim_mod(int **,int,int,int,int *);
! 18: int generic_gauss_elim(MAT ,MAT *,Q *,int **,int **);
! 19:
! 20: int gauss_elim_mod(int **,int,int,int);
! 21: int gauss_elim_mod1(int **,int,int,int);
! 22: int gauss_elim_geninv_mod(unsigned int **,int,int,int);
! 23: int gauss_elim_geninv_mod_swap(unsigned int **,int,int,unsigned int,unsigned int ***,int **);
! 24: void Pnewvect(), Pnewmat(), Psepvect(), Psize(), Pdet(), Pleqm(), Pleqm1(), Pgeninvm();
! 25:
! 26: void Pgeneric_gauss_elim_mod();
! 27:
! 28: void Pmat_to_gfmmat(),Plu_gfmmat(),Psolve_by_lu_gfmmat();
! 29: void Pgeninvm_swap(), Premainder(), Psremainder(), Pvtol();
! 30: void sepvect();
! 31: void Pmulmat_gf2n();
! 32: void Pbconvmat_gf2n();
! 33: void Pmul_vect_mat_gf2n();
! 34: void PNBmul_gf2n();
! 35: void Pmul_mat_vect_int();
! 36: void Psepmat_destructive();
! 37: void Px962_irredpoly_up2();
! 38: void Pirredpoly_up2();
! 39: void Pnbpoly_up2();
! 40: void Pqsort();
! 41:
! 42: struct ftab array_tab[] = {
! 43: {"solve_by_lu_gfmmat",Psolve_by_lu_gfmmat,4},
! 44: {"lu_gfmmat",Plu_gfmmat,2},
! 45: {"mat_to_gfmmat",Pmat_to_gfmmat,2},
! 46: {"generic_gauss_elim_mod",Pgeneric_gauss_elim_mod,2},
! 47: {"newvect",Pnewvect,-2},
! 48: {"newmat",Pnewmat,-3},
! 49: {"sepmat_destructive",Psepmat_destructive,2},
! 50: {"sepvect",Psepvect,2},
! 51: {"qsort",Pqsort,-2},
! 52: {"vtol",Pvtol,1},
! 53: {"size",Psize,1},
! 54: {"det",Pdet,-2},
! 55: {"leqm",Pleqm,2},
! 56: {"leqm1",Pleqm1,2},
! 57: {"geninvm",Pgeninvm,2},
! 58: {"geninvm_swap",Pgeninvm_swap,2},
! 59: {"remainder",Premainder,2},
! 60: {"sremainder",Psremainder,2},
! 61: {"mulmat_gf2n",Pmulmat_gf2n,1},
! 62: {"bconvmat_gf2n",Pbconvmat_gf2n,-4},
! 63: {"mul_vect_mat_gf2n",Pmul_vect_mat_gf2n,2},
! 64: {"mul_mat_vect_int",Pmul_mat_vect_int,2},
! 65: {"nbmul_gf2n",PNBmul_gf2n,3},
! 66: {"x962_irredpoly_up2",Px962_irredpoly_up2,2},
! 67: {"irredpoly_up2",Pirredpoly_up2,2},
! 68: {"nbpoly_up2",Pnbpoly_up2,2},
! 69: {0,0,0},
! 70: };
! 71:
! 72: int comp_obj(a,b)
! 73: Obj *a,*b;
! 74: {
! 75: return arf_comp(CO,*a,*b);
! 76: }
! 77:
! 78: static FUNC generic_comp_obj_func;
! 79: static NODE generic_comp_obj_arg;
! 80:
! 81: int generic_comp_obj(a,b)
! 82: Obj *a,*b;
! 83: {
! 84: Q r;
! 85:
! 86: BDY(generic_comp_obj_arg)=(pointer)(*a);
! 87: BDY(NEXT(generic_comp_obj_arg))=(pointer)(*b);
! 88: r = (Q)bevalf(generic_comp_obj_func,generic_comp_obj_arg);
! 89: if ( !r )
! 90: return 0;
! 91: else
! 92: return SGN(r)>0?1:-1;
! 93: }
! 94:
! 95:
! 96: void Pqsort(arg,rp)
! 97: NODE arg;
! 98: VECT *rp;
! 99: {
! 100: VECT vect;
! 101: char buf[BUFSIZ];
! 102: char *fname;
! 103: NODE n;
! 104: P p;
! 105: V v;
! 106:
! 107: asir_assert(ARG0(arg),O_VECT,"qsort");
! 108: vect = (VECT)ARG0(arg);
! 109: if ( argc(arg) == 1 )
! 110: qsort(BDY(vect),vect->len,sizeof(Obj),(int (*)(const void *,const void *))comp_obj);
! 111: else {
! 112: p = (P)ARG1(arg);
! 113: if ( !p || OID(p)!=2 )
! 114: error("qsort : invalid argument");
! 115: v = VR(p);
! 116: if ( (int)v->attr != V_SR )
! 117: error("qsort : no such function");
! 118: generic_comp_obj_func = (FUNC)v->priv;
! 119: MKNODE(n,0,0); MKNODE(generic_comp_obj_arg,0,n);
! 120: qsort(BDY(vect),vect->len,sizeof(Obj),(int (*)(const void *,const void *))generic_comp_obj);
! 121: }
! 122: *rp = vect;
! 123: }
! 124:
! 125: void PNBmul_gf2n(arg,rp)
! 126: NODE arg;
! 127: GF2N *rp;
! 128: {
! 129: GF2N a,b;
! 130: GF2MAT mat;
! 131: int n,w;
! 132: unsigned int *ab,*bb;
! 133: UP2 r;
! 134:
! 135: a = (GF2N)ARG0(arg);
! 136: b = (GF2N)ARG1(arg);
! 137: mat = (GF2MAT)ARG2(arg);
! 138: if ( !a || !b )
! 139: *rp = 0;
! 140: else {
! 141: n = mat->row;
! 142: w = (n+BSH-1)/BSH;
! 143:
! 144: ab = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
! 145: bzero((char *)ab,w*sizeof(unsigned int));
! 146: bcopy(a->body->b,ab,(a->body->w)*sizeof(unsigned int));
! 147:
! 148: bb = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
! 149: bzero((char *)bb,w*sizeof(unsigned int));
! 150: bcopy(b->body->b,bb,(b->body->w)*sizeof(unsigned int));
! 151:
! 152: NEWUP2(r,w);
! 153: bzero((char *)r->b,w*sizeof(unsigned int));
! 154: mul_nb(mat,ab,bb,r->b);
! 155: r->w = w;
! 156: _adjup2(r);
! 157: if ( !r->w )
! 158: *rp = 0;
! 159: else
! 160: MKGF2N(r,*rp);
! 161: }
! 162: }
! 163:
! 164: void Pmul_vect_mat_gf2n(arg,rp)
! 165: NODE arg;
! 166: GF2N *rp;
! 167: {
! 168: GF2N a;
! 169: GF2MAT mat;
! 170: int n,w;
! 171: unsigned int *b;
! 172: UP2 r;
! 173:
! 174: a = (GF2N)ARG0(arg);
! 175: mat = (GF2MAT)ARG1(arg);
! 176: if ( !a )
! 177: *rp = 0;
! 178: else {
! 179: n = mat->row;
! 180: w = (n+BSH-1)/BSH;
! 181: b = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
! 182: bzero((char *)b,w*sizeof(unsigned int));
! 183: bcopy(a->body->b,b,(a->body->w)*sizeof(unsigned int));
! 184: NEWUP2(r,w);
! 185: bzero((char *)r->b,w*sizeof(unsigned int));
! 186: mulgf2vectmat(mat->row,b,mat->body,r->b);
! 187: r->w = w;
! 188: _adjup2(r);
! 189: if ( !r->w )
! 190: *rp = 0;
! 191: else {
! 192: MKGF2N(r,*rp);
! 193: }
! 194: }
! 195: }
! 196:
! 197: void Pbconvmat_gf2n(arg,rp)
! 198: NODE arg;
! 199: LIST *rp;
! 200: {
! 201: P p0,p1;
! 202: int to;
! 203: GF2MAT p01,p10;
! 204: GF2N root;
! 205: NODE n0,n1;
! 206:
! 207: p0 = (P)ARG0(arg);
! 208: p1 = (P)ARG1(arg);
! 209: to = ARG2(arg)?1:0;
! 210: if ( argc(arg) == 4 ) {
! 211: root = (GF2N)ARG3(arg);
! 212: compute_change_of_basis_matrix_with_root(p0,p1,to,root,&p01,&p10);
! 213: } else
! 214: compute_change_of_basis_matrix(p0,p1,to,&p01,&p10);
! 215: MKNODE(n1,p10,0); MKNODE(n0,p01,n1);
! 216: MKLIST(*rp,n0);
! 217: }
! 218:
! 219: void Pmulmat_gf2n(arg,rp)
! 220: NODE arg;
! 221: GF2MAT *rp;
! 222: {
! 223: GF2MAT m;
! 224:
! 225: if ( !compute_multiplication_matrix((P)ARG0(arg),&m) )
! 226: error("mulmat_gf2n : input is not a normal polynomial");
! 227: *rp = m;
! 228: }
! 229:
! 230: void Psepmat_destructive(arg,rp)
! 231: NODE arg;
! 232: LIST *rp;
! 233: {
! 234: MAT mat,mat1;
! 235: int i,j,row,col;
! 236: Q **a,**a1;
! 237: Q ent;
! 238: N nm,mod,rem,quo;
! 239: int sgn;
! 240: NODE n0,n1;
! 241:
! 242: mat = (MAT)ARG0(arg); mod = NM((Q)ARG1(arg));
! 243: row = mat->row; col = mat->col;
! 244: MKMAT(mat1,row,col);
! 245: a = (Q **)mat->body; a1 = (Q **)mat1->body;
! 246: for ( i = 0; i < row; i++ )
! 247: for ( j = 0; j < col; j++ ) {
! 248: ent = a[i][j];
! 249: if ( !ent )
! 250: continue;
! 251: nm = NM(ent);
! 252: sgn = SGN(ent);
! 253: divn(nm,mod,&quo,&rem);
! 254: /* if ( quo != nm && rem != nm ) */
! 255: /* GC_free(nm); */
! 256: /* GC_free(ent); */
! 257: NTOQ(rem,sgn,a[i][j]); NTOQ(quo,sgn,a1[i][j]);
! 258: }
! 259: MKNODE(n1,mat1,0); MKNODE(n0,mat,n1);
! 260: MKLIST(*rp,n0);
! 261: }
! 262:
! 263: void Psepvect(arg,rp)
! 264: NODE arg;
! 265: VECT *rp;
! 266: {
! 267: sepvect((VECT)ARG0(arg),QTOS((Q)ARG1(arg)),rp);
! 268: }
! 269:
! 270: void sepvect(v,d,rp)
! 271: VECT v;
! 272: int d;
! 273: VECT *rp;
! 274: {
! 275: int i,j,k,n,q,q1,r;
! 276: pointer *pv,*pw,*pu;
! 277: VECT w,u;
! 278:
! 279: n = v->len;
! 280: if ( d > n )
! 281: d = n;
! 282: q = n/d; r = n%d; q1 = q+1;
! 283: MKVECT(w,d); *rp = w;
! 284: pv = BDY(v); pw = BDY(w); k = 0;
! 285: for ( i = 0; i < r; i++ ) {
! 286: MKVECT(u,q1); pw[i] = (pointer)u;
! 287: for ( pu = BDY(u), j = 0; j < q1; j++, k++ )
! 288: pu[j] = pv[k];
! 289: }
! 290: for ( ; i < d; i++ ) {
! 291: MKVECT(u,q); pw[i] = (pointer)u;
! 292: for ( pu = BDY(u), j = 0; j < q; j++, k++ )
! 293: pu[j] = pv[k];
! 294: }
! 295: }
! 296:
! 297: void Pnewvect(arg,rp)
! 298: NODE arg;
! 299: VECT *rp;
! 300: {
! 301: int len,i,r;
! 302: VECT vect;
! 303: pointer *vb;
! 304: LIST list;
! 305: NODE tn;
! 306:
! 307: asir_assert(ARG0(arg),O_N,"newvect");
! 308: len = QTOS((Q)ARG0(arg));
! 309: if ( len <= 0 )
! 310: error("newvect : invalid size");
! 311: MKVECT(vect,len);
! 312: if ( argc(arg) == 2 ) {
! 313: list = (LIST)ARG1(arg);
! 314: asir_assert(list,O_LIST,"newvect");
! 315: for ( r = 0, tn = BDY(list); tn; r++, tn = NEXT(tn) );
! 316: if ( r > len ) {
! 317: *rp = vect;
! 318: return;
! 319: }
! 320: for ( i = 0, tn = BDY(list), vb = BDY(vect); tn; i++, tn = NEXT(tn) )
! 321: vb[i] = (pointer)BDY(tn);
! 322: }
! 323: *rp = vect;
! 324: }
! 325:
! 326: void Pnewmat(arg,rp)
! 327: NODE arg;
! 328: MAT *rp;
! 329: {
! 330: int row,col;
! 331: int i,j,r,c;
! 332: NODE tn,sn;
! 333: MAT m;
! 334: pointer **mb;
! 335: LIST list;
! 336:
! 337: asir_assert(ARG0(arg),O_N,"newmat");
! 338: asir_assert(ARG1(arg),O_N,"newmat");
! 339: row = QTOS((Q)ARG0(arg)); col = QTOS((Q)ARG1(arg));
! 340: if ( row <= 0 || col <= 0 )
! 341: error("newmat : invalid size");
! 342: MKMAT(m,row,col);
! 343: if ( argc(arg) == 3 ) {
! 344: list = (LIST)ARG2(arg);
! 345: asir_assert(list,O_LIST,"newmat");
! 346: for ( r = 0, c = 0, tn = BDY(list); tn; r++, tn = NEXT(tn) ) {
! 347: for ( j = 0, sn = BDY((LIST)BDY(tn)); sn; j++, sn = NEXT(sn) );
! 348: c = MAX(c,j);
! 349: }
! 350: if ( (r > row) || (c > col) ) {
! 351: *rp = m;
! 352: return;
! 353: }
! 354: for ( i = 0, tn = BDY(list), mb = BDY(m); tn; i++, tn = NEXT(tn) ) {
! 355: asir_assert(BDY(tn),O_LIST,"newmat");
! 356: for ( j = 0, sn = BDY((LIST)BDY(tn)); sn; j++, sn = NEXT(sn) )
! 357: mb[i][j] = (pointer)BDY(sn);
! 358: }
! 359: }
! 360: *rp = m;
! 361: }
! 362:
! 363: void Pvtol(arg,rp)
! 364: NODE arg;
! 365: LIST *rp;
! 366: {
! 367: NODE n,n1;
! 368: VECT v;
! 369: pointer *a;
! 370: int len,i;
! 371:
! 372: asir_assert(ARG0(arg),O_VECT,"vtol");
! 373: v = (VECT)ARG0(arg); len = v->len; a = BDY(v);
! 374: for ( i = len - 1, n = 0; i >= 0; i-- ) {
! 375: MKNODE(n1,a[i],n); n = n1;
! 376: }
! 377: MKLIST(*rp,n);
! 378: }
! 379:
! 380: void Premainder(arg,rp)
! 381: NODE arg;
! 382: Obj *rp;
! 383: {
! 384: Obj a;
! 385: VECT v,w;
! 386: MAT m,l;
! 387: pointer *vb,*wb;
! 388: pointer **mb,**lb;
! 389: int id,i,j,n,row,col,t,smd,sgn;
! 390: Q md,q;
! 391:
! 392: a = (Obj)ARG0(arg); md = (Q)ARG1(arg);
! 393: if ( !a )
! 394: *rp = 0;
! 395: else {
! 396: id = OID(a);
! 397: switch ( id ) {
! 398: case O_N:
! 399: case O_P:
! 400: cmp(md,(P)a,(P *)rp); break;
! 401: case O_VECT:
! 402: smd = QTOS(md);
! 403: v = (VECT)a; n = v->len; vb = v->body;
! 404: MKVECT(w,n); wb = w->body;
! 405: for ( i = 0; i < n; i++ ) {
! 406: if ( q = (Q)vb[i] ) {
! 407: sgn = SGN(q); t = rem(NM(q),smd);
! 408: STOQ(t,q);
! 409: if ( q )
! 410: SGN(q) = sgn;
! 411: }
! 412: wb[i] = (pointer)q;
! 413: }
! 414: *rp = (Obj)w;
! 415: break;
! 416: case O_MAT:
! 417: m = (MAT)a; row = m->row; col = m->col; mb = m->body;
! 418: MKMAT(l,row,col); lb = l->body;
! 419: for ( i = 0; i < row; i++ )
! 420: for ( j = 0, vb = mb[i], wb = lb[i]; j < col; j++ )
! 421: cmp(md,(P)vb[j],(P *)&wb[j]);
! 422: *rp = (Obj)l;
! 423: break;
! 424: default:
! 425: error("remainder : invalid argument");
! 426: }
! 427: }
! 428: }
! 429:
! 430: void Psremainder(arg,rp)
! 431: NODE arg;
! 432: Obj *rp;
! 433: {
! 434: Obj a;
! 435: VECT v,w;
! 436: MAT m,l;
! 437: pointer *vb,*wb;
! 438: pointer **mb,**lb;
! 439: unsigned int t,smd;
! 440: int id,i,j,n,row,col;
! 441: Q md,q;
! 442:
! 443: a = (Obj)ARG0(arg); md = (Q)ARG1(arg);
! 444: if ( !a )
! 445: *rp = 0;
! 446: else {
! 447: id = OID(a);
! 448: switch ( id ) {
! 449: case O_N:
! 450: case O_P:
! 451: cmp(md,(P)a,(P *)rp); break;
! 452: case O_VECT:
! 453: smd = QTOS(md);
! 454: v = (VECT)a; n = v->len; vb = v->body;
! 455: MKVECT(w,n); wb = w->body;
! 456: for ( i = 0; i < n; i++ ) {
! 457: if ( q = (Q)vb[i] ) {
! 458: t = (unsigned int)rem(NM(q),smd);
! 459: if ( SGN(q) < 0 )
! 460: t = (smd - t) % smd;
! 461: UTOQ(t,q);
! 462: }
! 463: wb[i] = (pointer)q;
! 464: }
! 465: *rp = (Obj)w;
! 466: break;
! 467: case O_MAT:
! 468: m = (MAT)a; row = m->row; col = m->col; mb = m->body;
! 469: MKMAT(l,row,col); lb = l->body;
! 470: for ( i = 0; i < row; i++ )
! 471: for ( j = 0, vb = mb[i], wb = lb[i]; j < col; j++ )
! 472: cmp(md,(P)vb[j],(P *)&wb[j]);
! 473: *rp = (Obj)l;
! 474: break;
! 475: default:
! 476: error("remainder : invalid argument");
! 477: }
! 478: }
! 479: }
! 480:
! 481: void Psize(arg,rp)
! 482: NODE arg;
! 483: LIST *rp;
! 484: {
! 485:
! 486: int n,m;
! 487: Q q;
! 488: NODE t,s;
! 489:
! 490: if ( !ARG0(arg) )
! 491: t = 0;
! 492: else {
! 493: switch (OID(ARG0(arg))) {
! 494: case O_VECT:
! 495: n = ((VECT)ARG0(arg))->len;
! 496: STOQ(n,q); MKNODE(t,q,0);
! 497: break;
! 498: case O_MAT:
! 499: n = ((MAT)ARG0(arg))->row; m = ((MAT)ARG0(arg))->col;
! 500: STOQ(m,q); MKNODE(s,q,0); STOQ(n,q); MKNODE(t,q,s);
! 501: break;
! 502: default:
! 503: error("size : invalid argument"); break;
! 504: }
! 505: }
! 506: MKLIST(*rp,t);
! 507: }
! 508:
! 509: void Pdet(arg,rp)
! 510: NODE arg;
! 511: P *rp;
! 512: {
! 513: MAT m;
! 514: int n,i,j,mod;
! 515: P d;
! 516: P **mat,**w;
! 517:
! 518: m = (MAT)ARG0(arg);
! 519: asir_assert(m,O_MAT,"det");
! 520: if ( m->row != m->col )
! 521: error("det : non-square matrix");
! 522: else if ( argc(arg) == 1 )
! 523: detp(CO,(P **)BDY(m),m->row,rp);
! 524: else {
! 525: n = m->row; mod = QTOS((Q)ARG1(arg)); mat = (P **)BDY(m);
! 526: w = (P **)almat_pointer(n,n);
! 527: for ( i = 0; i < n; i++ )
! 528: for ( j = 0; j < n; j++ )
! 529: ptomp(mod,mat[i][j],&w[i][j]);
! 530: detmp(CO,mod,w,n,&d);
! 531: mptop(d,rp);
! 532: }
! 533: }
! 534:
! 535: /*
! 536: input : a row x col matrix A
! 537: A[I] <-> A[I][0]*x_0+A[I][1]*x_1+...
! 538:
! 539: output : [B,R,C]
! 540: B : a rank(A) x col-rank(A) matrix
! 541: R : a vector of length rank(A)
! 542: C : a vector of length col-rank(A)
! 543: B[I] <-> x_{R[I]}+B[I][0]x_{C[0]}+B[I][1]x_{C[1]}+...
! 544: */
! 545:
! 546: void Pgeneric_gauss_elim_mod(arg,rp)
! 547: NODE arg;
! 548: LIST *rp;
! 549: {
! 550: NODE n0;
! 551: MAT m,mat;
! 552: VECT rind,cind;
! 553: Q **tmat;
! 554: int **wmat;
! 555: Q *rib,*cib;
! 556: int *colstat;
! 557: Q q;
! 558: int md,i,j,k,l,row,col,t,n,rank;
! 559:
! 560: asir_assert(ARG0(arg),O_MAT,"generic_gauss_elim_mod");
! 561: asir_assert(ARG1(arg),O_N,"generic_gauss_elim_mod");
! 562: m = (MAT)ARG0(arg); md = QTOS((Q)ARG1(arg));
! 563: row = m->row; col = m->col; tmat = (Q **)m->body;
! 564: wmat = (int **)almat(row,col);
! 565: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
! 566: for ( i = 0; i < row; i++ )
! 567: for ( j = 0; j < col; j++ )
! 568: if ( q = (Q)tmat[i][j] ) {
! 569: t = rem(NM(q),md);
! 570: if ( t && SGN(q) < 0 )
! 571: t = (md - t) % md;
! 572: wmat[i][j] = t;
! 573: } else
! 574: wmat[i][j] = 0;
! 575: rank = generic_gauss_elim_mod(wmat,row,col,md,colstat);
! 576:
! 577: MKMAT(mat,rank,col-rank);
! 578: tmat = (Q **)mat->body;
! 579: for ( i = 0; i < rank; i++ )
! 580: for ( j = k = 0; j < col; j++ )
! 581: if ( !colstat[j] ) {
! 582: UTOQ(wmat[i][j],tmat[i][k]); k++;
! 583: }
! 584:
! 585: MKVECT(rind,rank);
! 586: MKVECT(cind,col-rank);
! 587: rib = (Q *)rind->body; cib = (Q *)cind->body;
! 588: for ( j = k = l = 0; j < col; j++ )
! 589: if ( colstat[j] ) {
! 590: STOQ(j,rib[k]); k++;
! 591: } else {
! 592: STOQ(j,cib[l]); l++;
! 593: }
! 594: n0 = mknode(3,mat,rind,cind);
! 595: MKLIST(*rp,n0);
! 596: }
! 597:
! 598: void Pleqm(arg,rp)
! 599: NODE arg;
! 600: VECT *rp;
! 601: {
! 602: MAT m;
! 603: VECT vect;
! 604: pointer **mat;
! 605: Q *v;
! 606: Q q;
! 607: int **wmat;
! 608: int md,i,j,row,col,t,n,status;
! 609:
! 610: asir_assert(ARG0(arg),O_MAT,"leqm");
! 611: asir_assert(ARG1(arg),O_N,"leqm");
! 612: m = (MAT)ARG0(arg); md = QTOS((Q)ARG1(arg));
! 613: row = m->row; col = m->col; mat = m->body;
! 614: wmat = (int **)almat(row,col);
! 615: for ( i = 0; i < row; i++ )
! 616: for ( j = 0; j < col; j++ )
! 617: if ( q = (Q)mat[i][j] ) {
! 618: t = rem(NM(q),md);
! 619: if ( SGN(q) < 0 )
! 620: t = (md - t) % md;
! 621: wmat[i][j] = t;
! 622: } else
! 623: wmat[i][j] = 0;
! 624: status = gauss_elim_mod(wmat,row,col,md);
! 625: if ( status < 0 )
! 626: *rp = 0;
! 627: else if ( status > 0 )
! 628: *rp = (VECT)ONE;
! 629: else {
! 630: n = col - 1;
! 631: MKVECT(vect,n);
! 632: for ( i = 0, v = (Q *)vect->body; i < n; i++ ) {
! 633: t = (md-wmat[i][n])%md; STOQ(t,v[i]);
! 634: }
! 635: *rp = vect;
! 636: }
! 637: }
! 638:
! 639: int gauss_elim_mod(mat,row,col,md)
! 640: int **mat;
! 641: int row,col,md;
! 642: {
! 643: int i,j,k,inv,a,n;
! 644: int *t,*pivot;
! 645:
! 646: n = col - 1;
! 647: for ( j = 0; j < n; j++ ) {
! 648: for ( i = j; i < row && !mat[i][j]; i++ );
! 649: if ( i == row )
! 650: return 1;
! 651: if ( i != j ) {
! 652: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
! 653: }
! 654: pivot = mat[j];
! 655: inv = invm(pivot[j],md);
! 656: for ( k = j; k <= n; k++ ) {
! 657: /* pivot[k] = dmar(pivot[k],inv,0,md); */
! 658: DMAR(pivot[k],inv,0,md,pivot[k])
! 659: }
! 660: for ( i = 0; i < row; i++ ) {
! 661: t = mat[i];
! 662: if ( i != j && (a = t[j]) )
! 663: for ( k = j, a = md - a; k <= n; k++ ) {
! 664: /* t[k] = dmar(pivot[k],a,t[k],md); */
! 665: DMAR(pivot[k],a,t[k],md,t[k])
! 666: }
! 667: }
! 668: }
! 669: for ( i = n; i < row && !mat[i][n]; i++ );
! 670: if ( i == row )
! 671: return 0;
! 672: else
! 673: return -1;
! 674: }
! 675:
! 676: struct oEGT eg_mod,eg_elim,eg_chrem,eg_gschk,eg_intrat,eg_symb;
! 677:
! 678: int generic_gauss_elim(mat,nm,dn,rindp,cindp)
! 679: MAT mat;
! 680: MAT *nm;
! 681: Q *dn;
! 682: int **rindp,**cindp;
! 683: {
! 684: int **wmat;
! 685: Q **bmat;
! 686: N **tmat;
! 687: Q *bmi;
! 688: N *tmi;
! 689: Q q;
! 690: int *wmi;
! 691: int *colstat,*wcolstat,*rind,*cind;
! 692: int row,col,ind,md,i,j,k,l,t,t1,rank,rank0,inv;
! 693: N m1,m2,m3,s,u;
! 694: MAT r,crmat;
! 695: struct oEGT tmp0,tmp1;
! 696: struct oEGT eg_mod_split,eg_elim_split,eg_chrem_split;
! 697: struct oEGT eg_intrat_split,eg_gschk_split;
! 698: int ret;
! 699:
! 700: init_eg(&eg_mod_split); init_eg(&eg_chrem_split);
! 701: init_eg(&eg_elim_split); init_eg(&eg_intrat_split);
! 702: init_eg(&eg_gschk_split);
! 703: bmat = (Q **)mat->body;
! 704: row = mat->row; col = mat->col;
! 705: wmat = (int **)almat(row,col);
! 706: colstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
! 707: wcolstat = (int *)MALLOC_ATOMIC(col*sizeof(int));
! 708: for ( ind = 0; ; ind++ ) {
! 709: if ( Print )
! 710: fprintf(asir_out,".");
! 711: md = lprime[ind];
! 712: get_eg(&tmp0);
! 713: for ( i = 0; i < row; i++ )
! 714: for ( j = 0, bmi = bmat[i], wmi = wmat[i]; j < col; j++ )
! 715: if ( q = (Q)bmi[j] ) {
! 716: t = rem(NM(q),md);
! 717: if ( t && SGN(q) < 0 )
! 718: t = (md - t) % md;
! 719: wmi[j] = t;
! 720: } else
! 721: wmi[j] = 0;
! 722: get_eg(&tmp1);
! 723: add_eg(&eg_mod,&tmp0,&tmp1);
! 724: add_eg(&eg_mod_split,&tmp0,&tmp1);
! 725: get_eg(&tmp0);
! 726: rank = generic_gauss_elim_mod(wmat,row,col,md,wcolstat);
! 727: get_eg(&tmp1);
! 728: add_eg(&eg_elim,&tmp0,&tmp1);
! 729: add_eg(&eg_elim_split,&tmp0,&tmp1);
! 730: if ( !ind ) {
! 731: RESET:
! 732: UTON(md,m1);
! 733: rank0 = rank;
! 734: bcopy(wcolstat,colstat,col*sizeof(int));
! 735: MKMAT(crmat,rank,col-rank);
! 736: MKMAT(r,rank,col-rank); *nm = r;
! 737: tmat = (N **)crmat->body;
! 738: for ( i = 0; i < rank; i++ )
! 739: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
! 740: if ( !colstat[j] ) {
! 741: UTON(wmi[j],tmi[k]); k++;
! 742: }
! 743: } else {
! 744: if ( rank < rank0 ) {
! 745: if ( Print )
! 746: fprintf(asir_out,"lower rank matrix; continuing...\n");
! 747: continue;
! 748: } else if ( rank > rank0 ) {
! 749: if ( Print )
! 750: fprintf(asir_out,"higher rank matrix; resetting...\n");
! 751: goto RESET;
! 752: } else {
! 753: for ( j = 0; (j<col) && (colstat[j]==wcolstat[j]); j++ );
! 754: if ( j < col ) {
! 755: if ( Print )
! 756: fprintf(asir_out,"inconsitent colstat; resetting...\n");
! 757: goto RESET;
! 758: }
! 759: }
! 760:
! 761: get_eg(&tmp0);
! 762: inv = invm(rem(m1,md),md);
! 763: UTON(md,m2); muln(m1,m2,&m3);
! 764: for ( i = 0; i < rank; i++ )
! 765: for ( j = k = 0, tmi = tmat[i], wmi = wmat[i]; j < col; j++ )
! 766: if ( !colstat[j] ) {
! 767: if ( tmi[k] ) {
! 768: /* f3 = f1+m1*(m1 mod m2)^(-1)*(f2 - f1 mod m2) */
! 769: t = rem(tmi[k],md);
! 770: if ( wmi[j] >= t )
! 771: t = wmi[j]-t;
! 772: else
! 773: t = md-(t-wmi[j]);
! 774: DMAR(t,inv,0,md,t1)
! 775: UTON(t1,u);
! 776: muln(m1,u,&s);
! 777: addn(tmi[k],s,&u); tmi[k] = u;
! 778: } else if ( wmi[j] ) {
! 779: /* f3 = m1*(m1 mod m2)^(-1)*f2 */
! 780: DMAR(wmi[j],inv,0,md,t)
! 781: UTON(t,u);
! 782: muln(m1,u,&s); tmi[k] = s;
! 783: }
! 784: k++;
! 785: }
! 786: m1 = m3;
! 787: get_eg(&tmp1);
! 788: add_eg(&eg_chrem,&tmp0,&tmp1);
! 789: add_eg(&eg_chrem_split,&tmp0,&tmp1);
! 790:
! 791: get_eg(&tmp0);
! 792: ret = intmtoratm(crmat,m1,*nm,dn);
! 793: get_eg(&tmp1);
! 794: add_eg(&eg_intrat,&tmp0,&tmp1);
! 795: add_eg(&eg_intrat_split,&tmp0,&tmp1);
! 796: if ( ret ) {
! 797: *rindp = rind = (int *)MALLOC_ATOMIC(rank*sizeof(int));
! 798: *cindp = cind = (int *)MALLOC_ATOMIC((col-rank)*sizeof(int));
! 799: for ( j = k = l = 0; j < col; j++ )
! 800: if ( colstat[j] )
! 801: rind[k++] = j;
! 802: else
! 803: cind[l++] = j;
! 804: get_eg(&tmp0);
! 805: if ( gensolve_check(mat,*nm,*dn,rind,cind) )
! 806: get_eg(&tmp1);
! 807: add_eg(&eg_gschk,&tmp0,&tmp1);
! 808: add_eg(&eg_gschk_split,&tmp0,&tmp1);
! 809: if ( Print ) {
! 810: print_eg("Mod",&eg_mod_split);
! 811: print_eg("Elim",&eg_elim_split);
! 812: print_eg("ChRem",&eg_chrem_split);
! 813: print_eg("IntRat",&eg_intrat_split);
! 814: print_eg("Check",&eg_gschk_split);
! 815: fflush(asir_out);
! 816: }
! 817: return rank;
! 818: }
! 819: }
! 820: }
! 821: }
! 822:
! 823: int f4_nocheck;
! 824:
! 825: int gensolve_check(mat,nm,dn,rind,cind)
! 826: MAT mat,nm;
! 827: Q dn;
! 828: int *rind,*cind;
! 829: {
! 830: int row,col,rank,clen,i,j,k,l;
! 831: Q s,t,u;
! 832: Q *w;
! 833: Q *mati,*nmk;
! 834:
! 835: if ( f4_nocheck )
! 836: return 1;
! 837: row = mat->row; col = mat->col;
! 838: rank = nm->row; clen = nm->col;
! 839: w = (Q *)MALLOC(clen*sizeof(Q));
! 840: for ( i = 0; i < row; i++ ) {
! 841: mati = (Q *)mat->body[i];
! 842: #if 1
! 843: bzero(w,clen*sizeof(Q));
! 844: for ( k = 0; k < rank; k++ )
! 845: for ( l = 0, nmk = (Q *)nm->body[k]; l < clen; l++ ) {
! 846: mulq(mati[rind[k]],nmk[l],&t);
! 847: addq(w[l],t,&s); w[l] = s;
! 848: }
! 849: for ( j = 0; j < clen; j++ ) {
! 850: mulq(dn,mati[cind[j]],&t);
! 851: if ( cmpq(w[j],t) )
! 852: break;
! 853: }
! 854: #else
! 855: for ( j = 0; j < clen; j++ ) {
! 856: for ( k = 0, s = 0; k < rank; k++ ) {
! 857: mulq(mati[rind[k]],nm->body[k][j],&t);
! 858: addq(s,t,&u); s = u;
! 859: }
! 860: mulq(dn,mati[cind[j]],&t);
! 861: if ( cmpq(s,t) )
! 862: break;
! 863: }
! 864: #endif
! 865: if ( j != clen )
! 866: break;
! 867: }
! 868: if ( i != row )
! 869: return 0;
! 870: else
! 871: return 1;
! 872: }
! 873:
! 874: /* assuming 0 < c < m */
! 875:
! 876: int inttorat(c,m,b,sgnp,nmp,dnp)
! 877: N c,m,b;
! 878: int *sgnp;
! 879: N *nmp,*dnp;
! 880: {
! 881: Q qq,t,u1,v1,r1,nm;
! 882: N q,r,u2,v2,r2;
! 883:
! 884: u1 = 0; v1 = ONE; u2 = m; v2 = c;
! 885: while ( cmpn(v2,b) >= 0 ) {
! 886: divn(u2,v2,&q,&r2); u2 = v2; v2 = r2;
! 887: NTOQ(q,1,qq); mulq(qq,v1,&t); subq(u1,t,&r1); u1 = v1; v1 = r1;
! 888: }
! 889: if ( cmpn(NM(v1),b) >= 0 )
! 890: return 0;
! 891: else {
! 892: *nmp = v2;
! 893: *dnp = NM(v1);
! 894: *sgnp = SGN(v1);
! 895: return 1;
! 896: }
! 897: }
! 898:
! 899: /* mat->body = N ** */
! 900:
! 901: int intmtoratm(mat,md,nm,dn)
! 902: MAT mat;
! 903: N md;
! 904: MAT nm;
! 905: Q *dn;
! 906: {
! 907: N t,s,b;
! 908: Q bound,dn0,dn1,nm1,q,tq;
! 909: int i,j,k,l,row,col;
! 910: Q **rmat;
! 911: N **tmat;
! 912: N *tmi;
! 913: Q *nmk;
! 914: N u,unm,udn;
! 915: int sgn,ret;
! 916:
! 917: row = mat->row; col = mat->col;
! 918: bshiftn(md,1,&t);
! 919: isqrt(t,&s);
! 920: bshiftn(s,64,&b);
! 921: if ( !b )
! 922: b = ONEN;
! 923: dn0 = ONE;
! 924: tmat = (N **)mat->body;
! 925: rmat = (Q **)nm->body;
! 926: for ( i = 0; i < row; i++ )
! 927: for ( j = 0, tmi = tmat[i]; j < col; j++ )
! 928: if ( tmi[j] ) {
! 929: muln(tmi[j],NM(dn0),&s);
! 930: remn(s,md,&u);
! 931: ret = inttorat(u,md,b,&sgn,&unm,&udn);
! 932: if ( !ret )
! 933: return 0;
! 934: else {
! 935: NTOQ(unm,sgn,nm1);
! 936: NTOQ(udn,1,dn1);
! 937: if ( !UNIQ(dn1) ) {
! 938: for ( k = 0; k < i; k++ )
! 939: for ( l = 0, nmk = rmat[k]; l < col; l++ ) {
! 940: mulq(nmk[l],dn1,&q); nmk[l] = q;
! 941: }
! 942: for ( l = 0, nmk = rmat[i]; l < j; l++ ) {
! 943: mulq(nmk[l],dn1,&q); nmk[l] = q;
! 944: }
! 945: }
! 946: rmat[i][j] = nm1;
! 947: mulq(dn0,dn1,&q); dn0 = q;
! 948: }
! 949: }
! 950: *dn = dn0;
! 951: return 1;
! 952: }
! 953:
! 954: int generic_gauss_elim_mod(mat,row,col,md,colstat)
! 955: int **mat;
! 956: int row,col,md;
! 957: int *colstat;
! 958: {
! 959: int i,j,k,l,inv,a,rank;
! 960: int *t,*pivot;
! 961:
! 962: for ( rank = 0, j = 0; j < col; j++ ) {
! 963: for ( i = rank; i < row && !mat[i][j]; i++ );
! 964: if ( i == row ) {
! 965: colstat[j] = 0;
! 966: continue;
! 967: } else
! 968: colstat[j] = 1;
! 969: if ( i != rank ) {
! 970: t = mat[i]; mat[i] = mat[rank]; mat[rank] = t;
! 971: }
! 972: pivot = mat[rank];
! 973: inv = invm(pivot[j],md);
! 974: for ( k = j; k < col; k++ )
! 975: if ( pivot[k] ) {
! 976: DMAR(pivot[k],inv,0,md,pivot[k])
! 977: }
! 978: for ( i = rank+1; i < row; i++ ) {
! 979: t = mat[i];
! 980: if ( a = t[j] )
! 981: for ( k = j, a = md - a; k < col; k++ )
! 982: if ( pivot[k] ) {
! 983: DMAR(pivot[k],a,t[k],md,t[k])
! 984: }
! 985: }
! 986: rank++;
! 987: }
! 988: for ( j = col-1, l = rank-1; j >= 0; j-- )
! 989: if ( colstat[j] ) {
! 990: pivot = mat[l];
! 991: for ( i = 0; i < l; i++ ) {
! 992: t = mat[i];
! 993: if ( a = t[j] )
! 994: for ( k = j, a = md-a; k < col; k++ )
! 995: if ( pivot[k] ) {
! 996: DMAR(pivot[k],a,t[k],md,t[k])
! 997: }
! 998: }
! 999: l--;
! 1000: }
! 1001: return rank;
! 1002: }
! 1003:
! 1004: /* LU decomposition; a[i][i] = 1/U[i][i] */
! 1005:
! 1006: int lu_gfmmat(mat,md,perm)
! 1007: GFMMAT mat;
! 1008: unsigned int md;
! 1009: int *perm;
! 1010: {
! 1011: int row,col;
! 1012: int i,j,k,l;
! 1013: unsigned int *t,*pivot;
! 1014: unsigned int **a;
! 1015: unsigned int inv,m;
! 1016:
! 1017: row = mat->row; col = mat->col;
! 1018: a = mat->body;
! 1019: bzero(perm,row*sizeof(int));
! 1020:
! 1021: for ( i = 0; i < row; i++ )
! 1022: perm[i] = i;
! 1023: for ( k = 0; k < col; k++ ) {
! 1024: for ( i = k; i < row && !a[i][k]; i++ );
! 1025: if ( i == row )
! 1026: return 0;
! 1027: if ( i != k ) {
! 1028: j = perm[i]; perm[i] = perm[k]; perm[k] = j;
! 1029: t = a[i]; a[i] = a[k]; a[k] = t;
! 1030: }
! 1031: pivot = a[k];
! 1032: pivot[k] = inv = invm(pivot[k],md);
! 1033: for ( i = k+1; i < row; i++ ) {
! 1034: t = a[i];
! 1035: if ( m = t[k] ) {
! 1036: DMAR(inv,m,0,md,t[k])
! 1037: for ( j = k+1, m = md - t[k]; j < col; j++ )
! 1038: if ( pivot[j] ) {
! 1039: DMAR(m,pivot[j],t[j],md,t[j])
! 1040: }
! 1041: }
! 1042: }
! 1043: }
! 1044: return 1;
! 1045: }
! 1046:
! 1047: void Pleqm1(arg,rp)
! 1048: NODE arg;
! 1049: VECT *rp;
! 1050: {
! 1051: MAT m;
! 1052: VECT vect;
! 1053: pointer **mat;
! 1054: Q *v;
! 1055: Q q;
! 1056: int **wmat;
! 1057: int md,i,j,row,col,t,n,status;
! 1058:
! 1059: asir_assert(ARG0(arg),O_MAT,"leqm1");
! 1060: asir_assert(ARG1(arg),O_N,"leqm1");
! 1061: m = (MAT)ARG0(arg); md = QTOS((Q)ARG1(arg));
! 1062: row = m->row; col = m->col; mat = m->body;
! 1063: wmat = (int **)almat(row,col);
! 1064: for ( i = 0; i < row; i++ )
! 1065: for ( j = 0; j < col; j++ )
! 1066: if ( q = (Q)mat[i][j] ) {
! 1067: t = rem(NM(q),md);
! 1068: if ( SGN(q) < 0 )
! 1069: t = (md - t) % md;
! 1070: wmat[i][j] = t;
! 1071: } else
! 1072: wmat[i][j] = 0;
! 1073: status = gauss_elim_mod1(wmat,row,col,md);
! 1074: if ( status < 0 )
! 1075: *rp = 0;
! 1076: else if ( status > 0 )
! 1077: *rp = (VECT)ONE;
! 1078: else {
! 1079: n = col - 1;
! 1080: MKVECT(vect,n);
! 1081: for ( i = 0, v = (Q *)vect->body; i < n; i++ ) {
! 1082: t = (md-wmat[i][n])%md; STOQ(t,v[i]);
! 1083: }
! 1084: *rp = vect;
! 1085: }
! 1086: }
! 1087:
! 1088: gauss_elim_mod1(mat,row,col,md)
! 1089: int **mat;
! 1090: int row,col,md;
! 1091: {
! 1092: int i,j,k,inv,a,n;
! 1093: int *t,*pivot;
! 1094:
! 1095: n = col - 1;
! 1096: for ( j = 0; j < n; j++ ) {
! 1097: for ( i = j; i < row && !mat[i][j]; i++ );
! 1098: if ( i == row )
! 1099: return 1;
! 1100: if ( i != j ) {
! 1101: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
! 1102: }
! 1103: pivot = mat[j];
! 1104: inv = invm(pivot[j],md);
! 1105: for ( k = j; k <= n; k++ )
! 1106: pivot[k] = dmar(pivot[k],inv,0,md);
! 1107: for ( i = j+1; i < row; i++ ) {
! 1108: t = mat[i];
! 1109: if ( i != j && (a = t[j]) )
! 1110: for ( k = j, a = md - a; k <= n; k++ )
! 1111: t[k] = dmar(pivot[k],a,t[k],md);
! 1112: }
! 1113: }
! 1114: for ( i = n; i < row && !mat[i][n]; i++ );
! 1115: if ( i == row ) {
! 1116: for ( j = n-1; j >= 0; j-- ) {
! 1117: for ( i = j-1, a = (md-mat[j][n])%md; i >= 0; i-- ) {
! 1118: mat[i][n] = dmar(mat[i][j],a,mat[i][n],md);
! 1119: mat[i][j] = 0;
! 1120: }
! 1121: }
! 1122: return 0;
! 1123: } else
! 1124: return -1;
! 1125: }
! 1126:
! 1127: void Pgeninvm(arg,rp)
! 1128: NODE arg;
! 1129: LIST *rp;
! 1130: {
! 1131: MAT m;
! 1132: pointer **mat;
! 1133: Q **tmat;
! 1134: Q q;
! 1135: unsigned int **wmat;
! 1136: int md,i,j,row,col,t,status;
! 1137: MAT mat1,mat2;
! 1138: NODE node1,node2;
! 1139:
! 1140: asir_assert(ARG0(arg),O_MAT,"leqm1");
! 1141: asir_assert(ARG1(arg),O_N,"leqm1");
! 1142: m = (MAT)ARG0(arg); md = QTOS((Q)ARG1(arg));
! 1143: row = m->row; col = m->col; mat = m->body;
! 1144: wmat = (unsigned int **)almat(row,col+row);
! 1145: for ( i = 0; i < row; i++ ) {
! 1146: bzero((char *)wmat[i],(col+row)*sizeof(int));
! 1147: for ( j = 0; j < col; j++ )
! 1148: if ( q = (Q)mat[i][j] ) {
! 1149: t = rem(NM(q),md);
! 1150: if ( SGN(q) < 0 )
! 1151: t = (md - t) % md;
! 1152: wmat[i][j] = t;
! 1153: }
! 1154: wmat[i][col+i] = 1;
! 1155: }
! 1156: status = gauss_elim_geninv_mod(wmat,row,col,md);
! 1157: if ( status > 0 )
! 1158: *rp = 0;
! 1159: else {
! 1160: MKMAT(mat1,col,row); MKMAT(mat2,row-col,row);
! 1161: for ( i = 0, tmat = (Q **)mat1->body; i < col; i++ )
! 1162: for ( j = 0; j < row; j++ )
! 1163: STOQ(wmat[i][j+col],tmat[i][j]);
! 1164: for ( tmat = (Q **)mat2->body; i < row; i++ )
! 1165: for ( j = 0; j < row; j++ )
! 1166: STOQ(wmat[i][j+col],tmat[i-col][j]);
! 1167: MKNODE(node2,mat2,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
! 1168: }
! 1169: }
! 1170:
! 1171: int gauss_elim_geninv_mod(mat,row,col,md)
! 1172: unsigned int **mat;
! 1173: int row,col,md;
! 1174: {
! 1175: int i,j,k,inv,a,n,m;
! 1176: unsigned int *t,*pivot;
! 1177:
! 1178: n = col; m = row+col;
! 1179: for ( j = 0; j < n; j++ ) {
! 1180: for ( i = j; i < row && !mat[i][j]; i++ );
! 1181: if ( i == row )
! 1182: return 1;
! 1183: if ( i != j ) {
! 1184: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
! 1185: }
! 1186: pivot = mat[j];
! 1187: inv = invm(pivot[j],md);
! 1188: for ( k = j; k < m; k++ )
! 1189: pivot[k] = dmar(pivot[k],inv,0,md);
! 1190: for ( i = j+1; i < row; i++ ) {
! 1191: t = mat[i];
! 1192: if ( a = t[j] )
! 1193: for ( k = j, a = md - a; k < m; k++ )
! 1194: t[k] = dmar(pivot[k],a,t[k],md);
! 1195: }
! 1196: }
! 1197: for ( j = n-1; j >= 0; j-- ) {
! 1198: pivot = mat[j];
! 1199: for ( i = j-1; i >= 0; i-- ) {
! 1200: t = mat[i];
! 1201: if ( a = t[j] )
! 1202: for ( k = j, a = md - a; k < m; k++ )
! 1203: t[k] = dmar(pivot[k],a,t[k],md);
! 1204: }
! 1205: }
! 1206: return 0;
! 1207: }
! 1208:
! 1209: void Psolve_by_lu_gfmmat(arg,rp)
! 1210: NODE arg;
! 1211: VECT *rp;
! 1212: {
! 1213: GFMMAT lu;
! 1214: Q *perm,*rhs,*v;
! 1215: int n,i;
! 1216: unsigned int md;
! 1217: unsigned int *b,*sol;
! 1218: VECT r;
! 1219:
! 1220: lu = (GFMMAT)ARG0(arg);
! 1221: perm = (Q *)BDY((VECT)ARG1(arg));
! 1222: rhs = (Q *)BDY((VECT)ARG2(arg));
! 1223: md = (unsigned int)QTOS((Q)ARG3(arg));
! 1224: n = lu->col;
! 1225: b = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
! 1226: sol = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
! 1227: for ( i = 0; i < n; i++ )
! 1228: b[i] = QTOS(rhs[QTOS(perm[i])]);
! 1229: solve_by_lu_gfmmat(lu,md,b,sol);
! 1230: MKVECT(r,n);
! 1231: for ( i = 0, v = (Q *)r->body; i < n; i++ )
! 1232: STOQ(sol[i],v[i]);
! 1233: *rp = r;
! 1234: }
! 1235:
! 1236: void solve_by_lu_gfmmat(lu,md,b,x)
! 1237: GFMMAT lu;
! 1238: unsigned int md;
! 1239: unsigned int *b;
! 1240: unsigned int *x;
! 1241: {
! 1242: int n;
! 1243: unsigned int **a;
! 1244: unsigned int *y;
! 1245: int i,j;
! 1246: unsigned int t,m;
! 1247:
! 1248: n = lu->col;
! 1249: a = lu->body;
! 1250: y = (unsigned int *)MALLOC_ATOMIC(n*sizeof(int));
! 1251: /* solve Ly=b */
! 1252: for ( i = 0; i < n; i++ ) {
! 1253: for ( t = b[i], j = 0; j < i; j++ )
! 1254: if ( a[i][j] ) {
! 1255: m = md - a[i][j];
! 1256: DMAR(m,y[j],t,md,t)
! 1257: }
! 1258: y[i] = t;
! 1259: }
! 1260: /* solve Ux=y */
! 1261: for ( i = n-1; i >= 0; i-- ) {
! 1262: for ( t = y[i], j =i+1; j < n; j++ )
! 1263: if ( a[i][j] ) {
! 1264: m = md - a[i][j];
! 1265: DMAR(m,x[j],t,md,t)
! 1266: }
! 1267: /* a[i][i] = 1/U[i][i] */
! 1268: DMAR(t,a[i][i],0,md,x[i])
! 1269: }
! 1270: }
! 1271:
! 1272: void Plu_gfmmat(arg,rp)
! 1273: NODE arg;
! 1274: LIST *rp;
! 1275: {
! 1276: MAT m;
! 1277: GFMMAT mm;
! 1278: unsigned int md;
! 1279: int i,row,col,status;
! 1280: int *iperm;
! 1281: Q *v;
! 1282: VECT perm;
! 1283: NODE n0;
! 1284:
! 1285: asir_assert(ARG0(arg),O_MAT,"mat_to_gfmmat");
! 1286: asir_assert(ARG1(arg),O_N,"mat_to_gfmmat");
! 1287: m = (MAT)ARG0(arg); md = (unsigned int)QTOS((Q)ARG1(arg));
! 1288: mat_to_gfmmat(m,md,&mm);
! 1289: row = m->row;
! 1290: col = m->col;
! 1291: iperm = (int *)MALLOC_ATOMIC(row*sizeof(int));
! 1292: status = lu_gfmmat(mm,md,iperm);
! 1293: if ( !status )
! 1294: n0 = 0;
! 1295: else {
! 1296: MKVECT(perm,row);
! 1297: for ( i = 0, v = (Q *)perm->body; i < row; i++ )
! 1298: STOQ(iperm[i],v[i]);
! 1299: n0 = mknode(2,mm,perm);
! 1300: }
! 1301: MKLIST(*rp,n0);
! 1302: }
! 1303:
! 1304: void Pmat_to_gfmmat(arg,rp)
! 1305: NODE arg;
! 1306: GFMMAT *rp;
! 1307: {
! 1308: MAT m;
! 1309: unsigned int md;
! 1310:
! 1311: asir_assert(ARG0(arg),O_MAT,"mat_to_gfmmat");
! 1312: asir_assert(ARG1(arg),O_N,"mat_to_gfmmat");
! 1313: m = (MAT)ARG0(arg); md = (unsigned int)QTOS((Q)ARG1(arg));
! 1314: mat_to_gfmmat(m,md,rp);
! 1315: }
! 1316:
! 1317: void mat_to_gfmmat(m,md,rp)
! 1318: MAT m;
! 1319: unsigned int md;
! 1320: GFMMAT *rp;
! 1321: {
! 1322: unsigned int **wmat;
! 1323: unsigned int t;
! 1324: Q **mat;
! 1325: Q q;
! 1326: int i,j,row,col;
! 1327:
! 1328: row = m->row; col = m->col; mat = (Q **)m->body;
! 1329: wmat = (unsigned int **)almat(row,col);
! 1330: for ( i = 0; i < row; i++ ) {
! 1331: bzero((char *)wmat[i],col*sizeof(unsigned int));
! 1332: for ( j = 0; j < col; j++ )
! 1333: if ( q = mat[i][j] ) {
! 1334: t = (unsigned int)rem(NM(q),md);
! 1335: if ( SGN(q) < 0 )
! 1336: t = (md - t) % md;
! 1337: wmat[i][j] = t;
! 1338: }
! 1339: }
! 1340: TOGFMMAT(row,col,wmat,*rp);
! 1341: }
! 1342:
! 1343: void Pgeninvm_swap(arg,rp)
! 1344: NODE arg;
! 1345: LIST *rp;
! 1346: {
! 1347: MAT m;
! 1348: pointer **mat;
! 1349: Q **tmat;
! 1350: Q *tvect;
! 1351: Q q;
! 1352: unsigned int **wmat,**invmat;
! 1353: int *index;
! 1354: unsigned int t,md;
! 1355: int i,j,row,col,status;
! 1356: MAT mat1;
! 1357: VECT vect1;
! 1358: NODE node1,node2;
! 1359:
! 1360: asir_assert(ARG0(arg),O_MAT,"geninvm_swap");
! 1361: asir_assert(ARG1(arg),O_N,"geninvm_swap");
! 1362: m = (MAT)ARG0(arg); md = QTOS((Q)ARG1(arg));
! 1363: row = m->row; col = m->col; mat = m->body;
! 1364: wmat = (unsigned int **)almat(row,col+row);
! 1365: for ( i = 0; i < row; i++ ) {
! 1366: bzero((char *)wmat[i],(col+row)*sizeof(int));
! 1367: for ( j = 0; j < col; j++ )
! 1368: if ( q = (Q)mat[i][j] ) {
! 1369: t = (unsigned int)rem(NM(q),md);
! 1370: if ( SGN(q) < 0 )
! 1371: t = (md - t) % md;
! 1372: wmat[i][j] = t;
! 1373: }
! 1374: wmat[i][col+i] = 1;
! 1375: }
! 1376: status = gauss_elim_geninv_mod_swap(wmat,row,col,md,&invmat,&index);
! 1377: if ( status > 0 )
! 1378: *rp = 0;
! 1379: else {
! 1380: MKMAT(mat1,col,col);
! 1381: for ( i = 0, tmat = (Q **)mat1->body; i < col; i++ )
! 1382: for ( j = 0; j < col; j++ )
! 1383: UTOQ(invmat[i][j],tmat[i][j]);
! 1384: MKVECT(vect1,row);
! 1385: for ( i = 0, tvect = (Q *)vect1->body; i < row; i++ )
! 1386: STOQ(index[i],tvect[i]);
! 1387: MKNODE(node2,vect1,0); MKNODE(node1,mat1,node2); MKLIST(*rp,node1);
! 1388: }
! 1389: }
! 1390:
! 1391: gauss_elim_geninv_mod_swap(mat,row,col,md,invmatp,indexp)
! 1392: unsigned int **mat;
! 1393: int row,col;
! 1394: unsigned int md;
! 1395: unsigned int ***invmatp;
! 1396: int **indexp;
! 1397: {
! 1398: int i,j,k,inv,a,n,m;
! 1399: unsigned int *t,*pivot,*s;
! 1400: int *index;
! 1401: unsigned int **invmat;
! 1402:
! 1403: n = col; m = row+col;
! 1404: *indexp = index = (int *)MALLOC_ATOMIC(row*sizeof(int));
! 1405: for ( i = 0; i < row; i++ )
! 1406: index[i] = i;
! 1407: for ( j = 0; j < n; j++ ) {
! 1408: for ( i = j; i < row && !mat[i][j]; i++ );
! 1409: if ( i == row ) {
! 1410: *indexp = 0; *invmatp = 0; return 1;
! 1411: }
! 1412: if ( i != j ) {
! 1413: t = mat[i]; mat[i] = mat[j]; mat[j] = t;
! 1414: k = index[i]; index[i] = index[j]; index[j] = k;
! 1415: }
! 1416: pivot = mat[j];
! 1417: inv = (unsigned int)invm(pivot[j],md);
! 1418: for ( k = j; k < m; k++ )
! 1419: if ( pivot[k] )
! 1420: pivot[k] = (unsigned int)dmar(pivot[k],inv,0,md);
! 1421: for ( i = j+1; i < row; i++ ) {
! 1422: t = mat[i];
! 1423: if ( a = t[j] )
! 1424: for ( k = j, a = md - a; k < m; k++ )
! 1425: if ( pivot[k] )
! 1426: t[k] = dmar(pivot[k],a,t[k],md);
! 1427: }
! 1428: }
! 1429: for ( j = n-1; j >= 0; j-- ) {
! 1430: pivot = mat[j];
! 1431: for ( i = j-1; i >= 0; i-- ) {
! 1432: t = mat[i];
! 1433: if ( a = t[j] )
! 1434: for ( k = j, a = md - a; k < m; k++ )
! 1435: if ( pivot[k] )
! 1436: t[k] = dmar(pivot[k],a,t[k],md);
! 1437: }
! 1438: }
! 1439: *invmatp = invmat = (unsigned int **)almat(col,col);
! 1440: for ( i = 0; i < col; i++ )
! 1441: for ( j = 0, s = invmat[i], t = mat[i]; j < col; j++ )
! 1442: s[j] = t[col+index[j]];
! 1443: return 0;
! 1444: }
! 1445:
! 1446: void _addn(N,N,N);
! 1447: int _subn(N,N,N);
! 1448: void _muln(N,N,N);
! 1449:
! 1450: void inner_product_int(a,b,n,r)
! 1451: Q *a,*b;
! 1452: int n;
! 1453: Q *r;
! 1454: {
! 1455: int la,lb,i;
! 1456: int sgn,sgn1;
! 1457: N wm,wma,sum,t;
! 1458:
! 1459: for ( la = lb = 0, i = 0; i < n; i++ ) {
! 1460: if ( a[i] )
! 1461: if ( DN(a[i]) )
! 1462: error("inner_product_int : invalid argument");
! 1463: else
! 1464: la = MAX(PL(NM(a[i])),la);
! 1465: if ( b[i] )
! 1466: if ( DN(b[i]) )
! 1467: error("inner_product_int : invalid argument");
! 1468: else
! 1469: lb = MAX(PL(NM(b[i])),lb);
! 1470: }
! 1471: sgn = 0;
! 1472: sum= NALLOC(la+lb+2);
! 1473: bzero((char *)sum,(la+lb+3)*sizeof(unsigned int));
! 1474: wm = NALLOC(la+lb+2);
! 1475: wma = NALLOC(la+lb+2);
! 1476: for ( i = 0; i < n; i++ ) {
! 1477: if ( !a[i] || !b[i] )
! 1478: continue;
! 1479: _muln(NM(a[i]),NM(b[i]),wm);
! 1480: sgn1 = SGN(a[i])*SGN(b[i]);
! 1481: if ( !sgn ) {
! 1482: sgn = sgn1;
! 1483: t = wm; wm = sum; sum = t;
! 1484: } else if ( sgn == sgn1 ) {
! 1485: _addn(sum,wm,wma);
! 1486: if ( !PL(wma) )
! 1487: sgn = 0;
! 1488: t = wma; wma = sum; sum = t;
! 1489: } else {
! 1490: /* sgn*sum+sgn1*wm = sgn*(sum-wm) */
! 1491: sgn *= _subn(sum,wm,wma);
! 1492: t = wma; wma = sum; sum = t;
! 1493: }
! 1494: }
! 1495: GC_free(wm);
! 1496: GC_free(wma);
! 1497: if ( !sgn ) {
! 1498: GC_free(sum);
! 1499: *r = 0;
! 1500: } else
! 1501: NTOQ(sum,sgn,*r);
! 1502: }
! 1503:
! 1504: void Pmul_mat_vect_int(arg,rp)
! 1505: NODE arg;
! 1506: VECT *rp;
! 1507: {
! 1508: MAT mat;
! 1509: VECT vect,r;
! 1510: int row,col,i;
! 1511:
! 1512: mat = (MAT)ARG0(arg);
! 1513: vect = (VECT)ARG1(arg);
! 1514: row = mat->row;
! 1515: col = mat->col;
! 1516: MKVECT(r,row);
! 1517: for ( i = 0; i < row; i++ )
! 1518: inner_product_int(mat->body[i],vect->body,col,&r->body[i]);
! 1519: *rp = r;
! 1520: }
! 1521:
! 1522: void Pnbpoly_up2(arg,rp)
! 1523: NODE arg;
! 1524: GF2N *rp;
! 1525: {
! 1526: int m,type,ret;
! 1527: UP2 r;
! 1528:
! 1529: m = QTOS((Q)ARG0(arg));
! 1530: type = QTOS((Q)ARG1(arg));
! 1531: ret = generate_ONB_polynomial(&r,m,type);
! 1532: if ( ret == 0 )
! 1533: MKGF2N(r,*rp);
! 1534: else
! 1535: *rp = 0;
! 1536: }
! 1537:
! 1538: void Px962_irredpoly_up2(arg,rp)
! 1539: NODE arg;
! 1540: GF2N *rp;
! 1541: {
! 1542: int m,type,ret,w;
! 1543: GF2N prev;
! 1544: UP2 r;
! 1545:
! 1546: m = QTOS((Q)ARG0(arg));
! 1547: prev = (GF2N)ARG1(arg);
! 1548: if ( !prev ) {
! 1549: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
! 1550: bzero((char *)r->b,w*sizeof(unsigned int));
! 1551: } else {
! 1552: r = prev->body;
! 1553: if ( degup2(r) != m ) {
! 1554: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
! 1555: bzero((char *)r->b,w*sizeof(unsigned int));
! 1556: }
! 1557: }
! 1558: ret = _generate_irreducible_polynomial(r,m,type);
! 1559: if ( ret == 0 )
! 1560: MKGF2N(r,*rp);
! 1561: else
! 1562: *rp = 0;
! 1563: }
! 1564:
! 1565: void Pirredpoly_up2(arg,rp)
! 1566: NODE arg;
! 1567: GF2N *rp;
! 1568: {
! 1569: int m,type,ret,w;
! 1570: GF2N prev;
! 1571: UP2 r;
! 1572:
! 1573: m = QTOS((Q)ARG0(arg));
! 1574: prev = (GF2N)ARG1(arg);
! 1575: if ( !prev ) {
! 1576: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
! 1577: bzero((char *)r->b,w*sizeof(unsigned int));
! 1578: } else {
! 1579: r = prev->body;
! 1580: if ( degup2(r) != m ) {
! 1581: w = (m>>5)+1; NEWUP2(r,w); r->w = 0;
! 1582: bzero((char *)r->b,w*sizeof(unsigned int));
! 1583: }
! 1584: }
! 1585: ret = _generate_good_irreducible_polynomial(r,m,type);
! 1586: if ( ret == 0 )
! 1587: MKGF2N(r,*rp);
! 1588: else
! 1589: *rp = 0;
! 1590: }
! 1591:
! 1592: /*
! 1593: * f = type 'type' normal polynomial of degree m if exists
! 1594: * IEEE P1363 A.7.2
! 1595: *
! 1596: * return value : 0 --- exists
! 1597: * 1 --- does not exist
! 1598: * -1 --- failure (memory allocation error)
! 1599: */
! 1600:
! 1601: int generate_ONB_polynomial(UP2 *rp,int m,int type)
! 1602: {
! 1603: int i,r;
! 1604: int w;
! 1605: UP2 f,f0,f1,f2,t;
! 1606:
! 1607: w = (m>>5)+1;
! 1608: switch ( type ) {
! 1609: case 1:
! 1610: if ( !TypeT_NB_check(m,1) ) return 1;
! 1611: NEWUP2(f,w); *rp = f; f->w = w;
! 1612: /* set all the bits */
! 1613: for ( i = 0; i < w; i++ )
! 1614: f->b[i] = 0xffffffff;
! 1615: /* mask the top word if necessary */
! 1616: if ( r = (m+1)&31 )
! 1617: f->b[w-1] &= (1<<r)-1;
! 1618: return 0;
! 1619: break;
! 1620: case 2:
! 1621: if ( !TypeT_NB_check(m,2) ) return 1;
! 1622: NEWUP2(f,w); *rp = f;
! 1623: W_NEWUP2(f0,w);
! 1624: W_NEWUP2(f1,w);
! 1625: W_NEWUP2(f2,w);
! 1626:
! 1627: /* recursion for genrating Type II normal polynomial */
! 1628:
! 1629: /* f0 = 1, f1 = t+1 */
! 1630: f0->w = 1; f0->b[0] = 1;
! 1631: f1->w = 1; f1->b[0] = 3;
! 1632: for ( i = 2; i <= m; i++ ) {
! 1633: /* f2 = t*f1+f0 */
! 1634: _bshiftup2(f1,-1,f2);
! 1635: _addup2_destructive(f2,f0);
! 1636: /* cyclic change of the variables */
! 1637: t = f0; f0 = f1; f1 = f2; f2 = t;
! 1638: }
! 1639: _copyup2(f1,f);
! 1640: return 0;
! 1641: break;
! 1642: default:
! 1643: return -1;
! 1644: break;
! 1645: }
! 1646: }
! 1647:
! 1648: /*
! 1649: * f = an irreducible trinomial or pentanomial of degree d 'after' f
! 1650: * return value : 0 --- exists
! 1651: * 1 --- does not exist (exhaustion)
! 1652: */
! 1653:
! 1654: int _generate_irreducible_polynomial(UP2 f,int d)
! 1655: {
! 1656: int ret,i,j,k,nz,i0,j0,k0;
! 1657: int w;
! 1658: unsigned int *fd;
! 1659:
! 1660: /*
! 1661: * if f = x^d+x^i+1 then i0 <- i, j0 <- 0, k0 <-0.
! 1662: * if f = x^d+x^k+x^j+x^i+1 (k>j>i) then i0 <- i, j0 <- j, k0 <-k.
! 1663: * otherwise i0,j0,k0 is set to 0.
! 1664: */
! 1665:
! 1666: fd = f->b;
! 1667: w = (d>>5)+1;
! 1668: if ( f->w && (d==degup2(f)) ) {
! 1669: for ( nz = 0, i = d; i >= 0; i-- )
! 1670: if ( fd[i>>5]&(1<<(i&31)) ) nz++;
! 1671: switch ( nz ) {
! 1672: case 3:
! 1673: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
! 1674: /* reset i0-th bit */
! 1675: fd[i0>>5] &= ~(1<<(i0&31));
! 1676: j0 = k0 = 0;
! 1677: break;
! 1678: case 5:
! 1679: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
! 1680: /* reset i0-th bit */
! 1681: fd[i0>>5] &= ~(1<<(i0&31));
! 1682: for ( j0 = i0+1; !(fd[j0>>5]&(1<<(j0&31))) ; j0++ );
! 1683: /* reset j0-th bit */
! 1684: fd[j0>>5] &= ~(1<<(j0&31));
! 1685: for ( k0 = j0+1; !(fd[k0>>5]&(1<<(k0&31))) ; k0++ );
! 1686: /* reset k0-th bit */
! 1687: fd[k0>>5] &= ~(1<<(k0&31));
! 1688: break;
! 1689: default:
! 1690: f->w = 0; break;
! 1691: }
! 1692: } else
! 1693: f->w = 0;
! 1694:
! 1695: if ( !f->w ) {
! 1696: fd = f->b;
! 1697: f->w = w; fd[0] |= 1; fd[d>>5] |= (1<<(d&31));
! 1698: i0 = j0 = k0 = 0;
! 1699: }
! 1700: /* if j0 > 0 then f is already a pentanomial */
! 1701: if ( j0 > 0 ) goto PENTA;
! 1702:
! 1703: /* searching for an irreducible trinomial */
! 1704:
! 1705: for ( i = 1; 2*i <= d; i++ ) {
! 1706: /* skip the polynomials 'before' f */
! 1707: if ( i < i0 ) continue;
! 1708: if ( i == i0 ) { i0 = 0; continue; }
! 1709: /* set i-th bit */
! 1710: fd[i>>5] |= (1<<(i&31));
! 1711: ret = irredcheck_dddup2(f);
! 1712: if ( ret == 1 ) return 0;
! 1713: /* reset i-th bit */
! 1714: fd[i>>5] &= ~(1<<(i&31));
! 1715: }
! 1716:
! 1717: /* searching for an irreducible pentanomial */
! 1718: PENTA:
! 1719: for ( i = 1; i < d; i++ ) {
! 1720: /* skip the polynomials 'before' f */
! 1721: if ( i < i0 ) continue;
! 1722: if ( i == i0 ) i0 = 0;
! 1723: /* set i-th bit */
! 1724: fd[i>>5] |= (1<<(i&31));
! 1725: for ( j = i+1; j < d; j++ ) {
! 1726: /* skip the polynomials 'before' f */
! 1727: if ( j < j0 ) continue;
! 1728: if ( j == j0 ) j0 = 0;
! 1729: /* set j-th bit */
! 1730: fd[j>>5] |= (1<<(j&31));
! 1731: for ( k = j+1; k < d; k++ ) {
! 1732: /* skip the polynomials 'before' f */
! 1733: if ( k < k0 ) continue;
! 1734: else if ( k == k0 ) { k0 = 0; continue; }
! 1735: /* set k-th bit */
! 1736: fd[k>>5] |= (1<<(k&31));
! 1737: ret = irredcheck_dddup2(f);
! 1738: if ( ret == 1 ) return 0;
! 1739: /* reset k-th bit */
! 1740: fd[k>>5] &= ~(1<<(k&31));
! 1741: }
! 1742: /* reset j-th bit */
! 1743: fd[j>>5] &= ~(1<<(j&31));
! 1744: }
! 1745: /* reset i-th bit */
! 1746: fd[i>>5] &= ~(1<<(i&31));
! 1747: }
! 1748: /* exhausted */
! 1749: return 1;
! 1750: }
! 1751:
! 1752: /*
! 1753: * f = an irreducible trinomial or pentanomial of degree d 'after' f
! 1754: *
! 1755: * searching strategy:
! 1756: * trinomial x^d+x^i+1:
! 1757: * i is as small as possible.
! 1758: * trinomial x^d+x^i+x^j+x^k+1:
! 1759: * i is as small as possible.
! 1760: * For such i, j is as small as possible.
! 1761: * For such i and j, 'k' is as small as possible.
! 1762: *
! 1763: * return value : 0 --- exists
! 1764: * 1 --- does not exist (exhaustion)
! 1765: */
! 1766:
! 1767: int _generate_good_irreducible_polynomial(UP2 f,int d)
! 1768: {
! 1769: int ret,i,j,k,nz,i0,j0,k0;
! 1770: int w;
! 1771: unsigned int *fd;
! 1772:
! 1773: /*
! 1774: * if f = x^d+x^i+1 then i0 <- i, j0 <- 0, k0 <-0.
! 1775: * if f = x^d+x^k+x^j+x^i+1 (k>j>i) then i0 <- i, j0 <- j, k0 <-k.
! 1776: * otherwise i0,j0,k0 is set to 0.
! 1777: */
! 1778:
! 1779: fd = f->b;
! 1780: w = (d>>5)+1;
! 1781: if ( f->w && (d==degup2(f)) ) {
! 1782: for ( nz = 0, i = d; i >= 0; i-- )
! 1783: if ( fd[i>>5]&(1<<(i&31)) ) nz++;
! 1784: switch ( nz ) {
! 1785: case 3:
! 1786: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
! 1787: /* reset i0-th bit */
! 1788: fd[i0>>5] &= ~(1<<(i0&31));
! 1789: j0 = k0 = 0;
! 1790: break;
! 1791: case 5:
! 1792: for ( i0 = 1; !(fd[i0>>5]&(1<<(i0&31))) ; i0++ );
! 1793: /* reset i0-th bit */
! 1794: fd[i0>>5] &= ~(1<<(i0&31));
! 1795: for ( j0 = i0+1; !(fd[j0>>5]&(1<<(j0&31))) ; j0++ );
! 1796: /* reset j0-th bit */
! 1797: fd[j0>>5] &= ~(1<<(j0&31));
! 1798: for ( k0 = j0+1; !(fd[k0>>5]&(1<<(k0&31))) ; k0++ );
! 1799: /* reset k0-th bit */
! 1800: fd[k0>>5] &= ~(1<<(k0&31));
! 1801: break;
! 1802: default:
! 1803: f->w = 0; break;
! 1804: }
! 1805: } else
! 1806: f->w = 0;
! 1807:
! 1808: if ( !f->w ) {
! 1809: fd = f->b;
! 1810: f->w = w; fd[0] |= 1; fd[d>>5] |= (1<<(d&31));
! 1811: i0 = j0 = k0 = 0;
! 1812: }
! 1813: /* if j0 > 0 then f is already a pentanomial */
! 1814: if ( j0 > 0 ) goto PENTA;
! 1815:
! 1816: /* searching for an irreducible trinomial */
! 1817:
! 1818: for ( i = 1; 2*i <= d; i++ ) {
! 1819: /* skip the polynomials 'before' f */
! 1820: if ( i < i0 ) continue;
! 1821: if ( i == i0 ) { i0 = 0; continue; }
! 1822: /* set i-th bit */
! 1823: fd[i>>5] |= (1<<(i&31));
! 1824: ret = irredcheck_dddup2(f);
! 1825: if ( ret == 1 ) return 0;
! 1826: /* reset i-th bit */
! 1827: fd[i>>5] &= ~(1<<(i&31));
! 1828: }
! 1829:
! 1830: /* searching for an irreducible pentanomial */
! 1831: PENTA:
! 1832: for ( i = 3; i < d; i++ ) {
! 1833: /* skip the polynomials 'before' f */
! 1834: if ( i < i0 ) continue;
! 1835: if ( i == i0 ) i0 = 0;
! 1836: /* set i-th bit */
! 1837: fd[i>>5] |= (1<<(i&31));
! 1838: for ( j = 2; j < i; j++ ) {
! 1839: /* skip the polynomials 'before' f */
! 1840: if ( j < j0 ) continue;
! 1841: if ( j == j0 ) j0 = 0;
! 1842: /* set j-th bit */
! 1843: fd[j>>5] |= (1<<(j&31));
! 1844: for ( k = 1; k < j; k++ ) {
! 1845: /* skip the polynomials 'before' f */
! 1846: if ( k < k0 ) continue;
! 1847: else if ( k == k0 ) { k0 = 0; continue; }
! 1848: /* set k-th bit */
! 1849: fd[k>>5] |= (1<<(k&31));
! 1850: ret = irredcheck_dddup2(f);
! 1851: if ( ret == 1 ) return 0;
! 1852: /* reset k-th bit */
! 1853: fd[k>>5] &= ~(1<<(k&31));
! 1854: }
! 1855: /* reset j-th bit */
! 1856: fd[j>>5] &= ~(1<<(j&31));
! 1857: }
! 1858: /* reset i-th bit */
! 1859: fd[i>>5] &= ~(1<<(i&31));
! 1860: }
! 1861: /* exhausted */
! 1862: return 1;
! 1863: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>