Annotation of OpenXM_contrib2/asir2000/engine/up2.c, Revision 1.1
1.1 ! noro 1: /* $OpenXM: OpenXM/src/asir99/engine/up2.c,v 1.1.1.1 1999/11/10 08:12:26 noro Exp $ */
! 2: #include "ca.h"
! 3: #include "base.h"
! 4:
! 5: void find_root_up2();
! 6:
! 7: #define INLINE
! 8:
! 9: #if defined(VISUAL)
! 10: #undef INLINE
! 11: #define INLINE __inline
! 12: #endif
! 13:
! 14: #if defined(linux)
! 15: #undef INLINE
! 16: #define INLINE inline
! 17: #endif
! 18:
! 19: static int up2_bbtab_initialized;
! 20: static unsigned short up2_sqtab[256];
! 21: static unsigned short up2_bbtab[65536];
! 22:
! 23: int up2_kara_mag = 10;
! 24: V up2_var;
! 25:
! 26: extern GEN_UP2 current_mod_gf2n;
! 27: extern int lm_lazy;
! 28:
! 29: #define GCD_COEF(q,p1,p2,p3,q1,q2,q3)\
! 30: switch (q){\
! 31: case 2:(p3)=(p1)^((p2)<<1);(q3)=(q1)^((q2)<<1);break;\
! 32: case 3:(p3)=(p1)^((p2)<<1)^(p2);(q3)=(q1)^((q2)<<1)^(q2);break;\
! 33: case 4:(p3)=(p1)^((p2)<<2);(q3)=(q1)^((q2)<<2);break;\
! 34: case 5:(p3)=(p1)^((p2)<<2)^(p2);(q3)=(q1)^((q2)<<2)^(q2);break;\
! 35: case 6:(p3)=(p1)^((p2)<<2)^((p2)<<1);(q3)=(q1)^((q2)<<2)^((q2)<<1);break;\
! 36: case 7:(p3)=(p1)^((p2)<<2)^((p2)<<1)^(p2);(q3)=(q1)^((q2)<<2)^((q2)<<1)^(q2);break;\
! 37: default:(p3)=(p1)^mulup2_bb((p2),(q));(q3)=(q1)^mulup2_bb((q2),(q));break;\
! 38: }\
! 39:
! 40: #if defined(P5)
! 41:
! 42: #define GF2M_MUL_1_HALF(high,low,a,b) (low)=NNgf2m_mul_1h(&(high),a,b);
! 43: #define GF2M_MUL_1(high,low,a,b) (low)=NNgf2m_mul_11(&(high),a,b);
! 44:
! 45: #else
! 46:
! 47: /*
! 48: * 32bit x 16bit -> 64bit (48bit); for b <= 0xffff
! 49: * a short-cut version of GF2M_MUL_1
! 50: */
! 51:
! 52: #define GF2M_MUL_1_HALF(high,low,a,b)\
! 53: {\
! 54: unsigned int _a,_b,_c,_d,_t,_s;\
! 55: unsigned int _ll,_cc;\
! 56: _a = (a);\
! 57: _b = (b);\
! 58: _c = _a&0xff00ff00; /* c = a4 0 a2 0 */\
! 59: _a ^= _c; /* a = 0 a3 0 a1 */\
! 60: _d = _b&0xff00ff00; /* d = 0 0 b2 0 */\
! 61: _b ^= _d; /* b = 0 0 0 b1 */\
! 62: _c |= (_d>>8); /* c = a4 00 a2 b2 */\
! 63: _b |= (_a<<8); /* b = a3 00 a1 b1 */\
! 64: _a = (_c>>16); /* a = a4 00 */\
! 65: _c &= 0xffff; /* c = a2 b2 */\
! 66: _d = (_b>>16); /* d = a3 00 */\
! 67: _b &= 0xffff; /* b = a1 b1 */\
! 68: _t = up2_bbtab[_c]; _s = up2_bbtab[_b];\
! 69: _ll = ((_t^_s^up2_bbtab[_c^_b])<<8)^(_t<<16)^_s;\
! 70: _a ^= _c; _d^= _b;\
! 71: _t = up2_bbtab[_a]; _s = up2_bbtab[_d];\
! 72: _cc = ((_t^_s^up2_bbtab[_a^_d])<<8)^(_t<<16)^_s;\
! 73: _cc ^= _ll;\
! 74: (low) = (unsigned int)(_ll^(_cc<<16));\
! 75: (high) = (unsigned int)(_cc>>16);\
! 76: }
! 77:
! 78: /*
! 79: * 32bit x 32bit -> 64bit
! 80: * This is an inline expansion of 4byte x 4byte Karatsuba multiplication
! 81: * Necessary indices for up2_bbtab are efficiently generated.
! 82: */
! 83:
! 84: #define GF2M_MUL_1(high,low,a,b)\
! 85: {\
! 86: unsigned int _a,_b,_c,_d,_t,_s;\
! 87: unsigned int _uu,_ll,_cc;\
! 88: _a = (a);\
! 89: _b = (b);\
! 90: _c = _a&0xff00ff00; /* _c = a4 0 a2 0 */\
! 91: _a ^= _c; /* a = 0 a3 0 a1 */\
! 92: _d = _b&0xff00ff00; /* _d = b4 0 b2 0 */\
! 93: _b ^= _d; /* b = 0 b3 0 b1 */\
! 94: _c |= (_d>>8); /* _c = a4 b4 a2 b2 */\
! 95: _b |= (_a<<8); /* b = a3 b3 a1 b1 */\
! 96: _a = (_c>>16); /* a = a4 b4 */\
! 97: _c &= 0xffff; /* _c = a2 b2 */\
! 98: _d = (_b>>16); /* _d = a3 b3 */\
! 99: _b &= 0xffff; /* b = a1 b1 */\
! 100: _t = up2_bbtab[_a]; _s = up2_bbtab[_d];\
! 101: _uu = ((_t^_s^up2_bbtab[_a^_d])<<8)^(_t<<16)^_s;\
! 102: _t = up2_bbtab[_c]; _s = up2_bbtab[_b];\
! 103: _ll = ((_t^_s^up2_bbtab[_c^_b])<<8)^(_t<<16)^_s;\
! 104: _a ^= _c; _d^= _b;\
! 105: _t = up2_bbtab[_a]; _s = up2_bbtab[_d];\
! 106: _cc = ((_t^_s^up2_bbtab[_a^_d])<<8)^(_t<<16)^_s;\
! 107: _cc ^= (_ll^_uu);\
! 108: (low) = (unsigned int)(_ll^(_cc<<16));\
! 109: (high) = (unsigned int)(_uu^(_cc>>16));\
! 110: }
! 111: #endif
! 112:
! 113: #define REMUP2_ONESTEP(a,q,s,n,w)\
! 114: if ( !s ) a[q] ^= w;\
! 115: else {\
! 116: a[q] ^= (w<<s);\
! 117: if ( q+1 <= n )\
! 118: a[q+1] ^= (w>>(32-s));\
! 119: }
! 120:
! 121: void ptoup2(n,nr)
! 122: P n;
! 123: UP2 *nr;
! 124: {
! 125: DCP dc;
! 126: UP2 r,s;
! 127: int d,w,i;
! 128:
! 129: if ( !n )
! 130: *nr = 0;
! 131: else if ( OID(n) == O_N )
! 132: if ( EVENN(NM((Q)n)) )
! 133: *nr = 0;
! 134: else
! 135: *nr = ONEUP2;
! 136: else {
! 137: d = UDEG(n); w = (d+1)/BSH + ((d+1)%BSH?1:0);
! 138: up2_var = VR(n);
! 139: W_NEWUP2(r,w);
! 140: for ( dc = DC(n); dc; dc = NEXT(dc) )
! 141: if ( !EVENN(NM((Q)COEF(dc))) ) {
! 142: i = QTOS(DEG(dc));
! 143: r->b[i/BSH] |= 1<<(i%BSH);
! 144: }
! 145: for ( i = w-1; i >= 0 && !r->b[i]; i-- );
! 146: r->w = i+1;
! 147: NEWUP2(s,r->w); *nr = s;
! 148: _copyup2(r,s);
! 149: }
! 150: }
! 151:
! 152: void ptoup2_sparse(n,nr)
! 153: P n;
! 154: UP2 *nr;
! 155: {
! 156: DCP dc;
! 157: UP2 s;
! 158: int d,i;
! 159:
! 160: if ( !n )
! 161: *nr = 0;
! 162: else if ( OID(n) == O_N )
! 163: if ( EVENN(NM((Q)n)) )
! 164: *nr = 0;
! 165: else {
! 166: NEWUP2(s,1); s->w = 1; s->b[0] = 0;
! 167: *nr = s;
! 168: }
! 169: else {
! 170: d = UDEG(n);
! 171: for ( dc = DC(n), i = 0; dc; dc = NEXT(dc) )
! 172: if ( !EVENN(NM((Q)COEF(dc))) )
! 173: i++;
! 174: NEWUP2(s,i); s->w = i; *nr = s;
! 175: for ( dc = DC(n), i = 0; dc; dc = NEXT(dc) )
! 176: if ( !EVENN(NM((Q)COEF(dc))) )
! 177: s->b[i++] = QTOS(DEG(dc));
! 178: }
! 179: }
! 180:
! 181: void up2top(n,nr)
! 182: UP2 n;
! 183: P *nr;
! 184: {
! 185: int i,d;
! 186: DCP dc0,dc;
! 187:
! 188: if ( !n )
! 189: *nr = 0;
! 190: else if ( !(d = degup2(n)) )
! 191: *nr = (P)ONE;
! 192: else {
! 193: for ( i = d, dc0 = 0; i >= 0; i-- )
! 194: if ( n->b[i/BSH] & (1<<(i%BSH)) ) {
! 195: NEXTDC(dc0,dc); STOQ(i,DEG(dc)); COEF(dc) = (P)ONE;
! 196: }
! 197: if ( !up2_var )
! 198: up2_var = CO->v;
! 199: MKP(up2_var,dc0,*nr);
! 200: }
! 201: }
! 202:
! 203: void up2tovect(n,nr)
! 204: UP2 n;
! 205: VECT *nr;
! 206: {
! 207: int i,d;
! 208: VECT v;
! 209:
! 210: if ( !n )
! 211: *nr = 0;
! 212: else {
! 213: d = degup2(n);
! 214: MKVECT(v,d+1); *nr = v;
! 215: for ( i = d; i >= 0; i-- )
! 216: if ( n->b[i/BSH] & (1<<(i%BSH)) )
! 217: v->body[i] = (pointer)ONE;
! 218: }
! 219: }
! 220:
! 221: void up2ton(p,n)
! 222: UP2 p;
! 223: Q *n;
! 224: {
! 225: N nm;
! 226: int w;
! 227:
! 228: if ( !p )
! 229: *n = 0;
! 230: else {
! 231: w = p->w;
! 232: nm = NALLOC(w);
! 233: nm->p = w;
! 234: bcopy(p->b,nm->b,w*sizeof(unsigned int));
! 235: NTOQ(nm,1,*n);
! 236: }
! 237: }
! 238:
! 239: void ntoup2(n,p)
! 240: Q n;
! 241: UP2 *p;
! 242: {
! 243: N nm;
! 244: UP2 t;
! 245: int w;
! 246:
! 247: if ( !n )
! 248: *p = 0;
! 249: else {
! 250: nm = NM(n); w = nm->p;
! 251: NEWUP2(t,w); *p = t; t->w = w;
! 252: bcopy(nm->b,t->b,w*sizeof(unsigned int));
! 253: }
! 254: }
! 255:
! 256: void gen_simpup2(p,m,r)
! 257: UP2 p;
! 258: GEN_UP2 m;
! 259: UP2 *r;
! 260: {
! 261: if ( lm_lazy || !m )
! 262: *r = p;
! 263: else if ( m->id == UP2_DENSE )
! 264: remup2(p,m->dense,r);
! 265: else
! 266: remup2_sparse(p,m->sparse,r);
! 267: if ( *r && !((*r)->w) )
! 268: *r = 0;
! 269: }
! 270:
! 271: void gen_simpup2_destructive(p,m)
! 272: UP2 p;
! 273: GEN_UP2 m;
! 274: {
! 275: UP2 t;
! 276:
! 277: if ( lm_lazy || !m )
! 278: return;
! 279: else if ( m->id == UP2_DENSE ) {
! 280: remup2(p,m->dense,&t);
! 281: _copyup2(t,p);
! 282: } else
! 283: remup2_sparse_destructive(p,m->sparse);
! 284: }
! 285:
! 286: void gen_invup2(p,m,r)
! 287: UP2 p;
! 288: GEN_UP2 m;
! 289: UP2 *r;
! 290: {
! 291: if ( !m )
! 292: error("gen_invup2 : invalid modulus");
! 293: else
! 294: invup2(p,m->dense,r);
! 295: }
! 296:
! 297: void gen_pwrmodup2(a,b,m,c)
! 298: UP2 a;
! 299: Q b;
! 300: GEN_UP2 m;
! 301: UP2 *c;
! 302: {
! 303: if ( !m )
! 304: pwrmodup2(a,b,0,c);
! 305: else if ( m->id == UP2_DENSE )
! 306: pwrmodup2(a,b,m->dense,c);
! 307: else
! 308: pwrmodup2_sparse(a,b,m->sparse,c);
! 309: }
! 310:
! 311: void simpup2(p,m,r)
! 312: UP2 p,m;
! 313: UP2 *r;
! 314: {
! 315: if ( !lm_lazy && m )
! 316: remup2(p,m,r);
! 317: else
! 318: *r = p;
! 319: }
! 320:
! 321: int degup2(a)
! 322: UP2 a;
! 323: {
! 324: unsigned int l,i,t;
! 325:
! 326: if ( !a || !a->w )
! 327: return -1;
! 328: else {
! 329: l = a->w; t = a->b[l-1];
! 330: for ( i = 0; t; t>>=1, i++);
! 331: return i+(l-1)*BSH-1;
! 332: }
! 333: }
! 334:
! 335: int degup2_sparse(a)
! 336: UP2 a;
! 337: {
! 338: if ( !a || !a->w )
! 339: return -1;
! 340: else
! 341: return a->b[0];
! 342: }
! 343:
! 344: int degup2_1(a)
! 345: unsigned int a;
! 346: {
! 347: int i;
! 348:
! 349: for ( i = 0; a; a>>=1, i++);
! 350: return i-1;
! 351: }
! 352:
! 353: void addup2(a,b,c)
! 354: UP2 a,b;
! 355: UP2 *c;
! 356: {
! 357: int i;
! 358: UP2 t;
! 359: int w,wa,wb;
! 360:
! 361: if ( !a )
! 362: *c = b;
! 363: else if ( !b )
! 364: *c = a;
! 365: else {
! 366: wa = a->w; wb = b->w;
! 367: if ( wa < wb ) {
! 368: t = a; a = b; b = t;
! 369: w = wa; wa = wb; wb = w;
! 370: }
! 371: NEWUP2(t,wa);
! 372: for ( i = 0; i < wb; i++ )
! 373: t->b[i] = a->b[i]^b->b[i];
! 374: for ( ; i < wa; i++ )
! 375: t->b[i] = a->b[i];
! 376: for ( i = wa-1; i >= 0 && !t->b[i]; i-- );
! 377: if ( i < 0 )
! 378: *c = 0;
! 379: else {
! 380: t->w = i+1;
! 381: *c = t;
! 382: }
! 383: }
! 384: }
! 385:
! 386: void subup2(a,b,c)
! 387: UP2 a,b;
! 388: UP2 *c;
! 389: {
! 390: addup2(a,b,c);
! 391: }
! 392:
! 393:
! 394: /*
! 395: s[w-1] ... s[0]
! 396: x m
! 397: ---------------------
! 398: t[w]t[w-1] ... t[0]
! 399: + r[w]r[w-1] ... r[0]
! 400: ---------------------
! 401: */
! 402:
! 403: INLINE void mulup2_n1(s,w,m,r)
! 404: unsigned int *s,*r;
! 405: int w;
! 406: unsigned int m;
! 407: {
! 408: int i;
! 409: unsigned int _u,_l,t;
! 410:
! 411: for ( i = 0; i < w; i++ )
! 412: if ( t = s[i] ) {
! 413: GF2M_MUL_1(_u,_l,t,m);
! 414: r[i] ^= _l; r[i+1] ^= _u;
! 415: }
! 416: }
! 417:
! 418: INLINE void mulup2_nh(s,w,m,r)
! 419: unsigned int *s,*r;
! 420: int w;
! 421: unsigned int m; /* 0 <= b <= 0xffff */
! 422: {
! 423: int i;
! 424: unsigned int u,l;
! 425:
! 426: for ( i = 0, r[0] = 0; i < w; i++ ) {
! 427: GF2M_MUL_1_HALF(u,l,s[i],m);
! 428: r[i] ^= l; r[i+1] = u;
! 429: }
! 430: }
! 431:
! 432: void _mulup2_1(a,b,c)
! 433: UP2 a,c;
! 434: unsigned int b;
! 435: {
! 436: int w;
! 437:
! 438: if ( !a || !a->w || !b )
! 439: c->w = 0;
! 440: else if ( b <= 0xffff )
! 441: _mulup2_h(a,b,c);
! 442: else {
! 443: w = a->w;
! 444: bzero((char *)c->b,(w+1)*sizeof(unsigned int));
! 445: mulup2_n1(a->b,w,b,c->b);
! 446: c->w = c->b[w] ? w+1 : w;
! 447: }
! 448: }
! 449:
! 450: void _mulup2_h(a,b,c)
! 451: UP2 a,c;
! 452: unsigned int b; /* 0 <= b <= 0xffff */
! 453: {
! 454: int w;
! 455:
! 456: if ( !a || !a->w || !b )
! 457: c->w = 0;
! 458: else {
! 459: w = a->w;
! 460: mulup2_nh(a->b,w,b,c->b);
! 461: c->w = c->b[w] ? w+1 : w;
! 462: }
! 463: }
! 464:
! 465: void mulup2(a,b,c)
! 466: UP2 a,b;
! 467: UP2 *c;
! 468: {
! 469: UP2 t;
! 470: int wa,wb,w;
! 471:
! 472: if ( !a || !b )
! 473: *c = 0;
! 474: else if ( a->w==1 && a->b[0]==1 ) {
! 475: NEWUP2(t,b->w); *c = t; _copyup2(b,t);
! 476: } else if ( b->w==1 && b->b[0]==1 ) {
! 477: NEWUP2(t,a->w); *c = t; _copyup2(a,t);
! 478: } else {
! 479: wa = a->w; wb = b->w;
! 480: if ( wa != wb ) {
! 481: if ( wb > wa ) {
! 482: t = a; a = b; b = t;
! 483: w = wa; wa = wb; wb = w;
! 484: }
! 485: W_NEWUP2(t,wa);
! 486: _copyup2(b,t);
! 487: bzero((char *)(t->b+wb),(wa-wb)*sizeof(unsigned int));
! 488: t->w = wa;
! 489: b = t;
! 490: }
! 491: NEWUP2(t,2*wa);
! 492: _kmulup2_(a->b,b->b,wa,t->b);
! 493: t->w = 2*wa; _adjup2(t);
! 494: *c = t;
! 495: }
! 496: }
! 497:
! 498: void _kmulup2_(a,b,w,c)
! 499: unsigned int *a,*b,*c;
! 500: int w;
! 501: {
! 502: switch ( w ) {
! 503: case 1: GF2M_MUL_1(c[1],c[0],*a,*b); break;
! 504: case 2: _mulup2_22(a,b,c); break;
! 505: case 3: _mulup2_33(a,b,c); break;
! 506: case 4: _mulup2_44(a,b,c); break;
! 507: case 5: _mulup2_55(a,b,c); break;
! 508: case 6: _mulup2_66(a,b,c); break;
! 509: default: _mulup2_nn(a,b,w,c); break;
! 510: }
! 511: }
! 512:
! 513: void _mulup2_nn(a,b,w,c)
! 514: unsigned int *a,*b,*c;
! 515: int w;
! 516: {
! 517: int wlow,whigh;
! 518: struct _oUP2 ablow,abhigh,alow,ahigh,blow,bhigh,aa,bb,mid,cmid;
! 519:
! 520: /* wlow >= whigh */
! 521: wlow = (w+1)/2; whigh = w-wlow;
! 522:
! 523: alow.w = wlow; alow.b = a;
! 524: ahigh.w = whigh; ahigh.b = a+wlow;
! 525:
! 526: blow.w = wlow; blow.b = b;
! 527: bhigh.w = whigh; bhigh.b = b+wlow;
! 528:
! 529: ablow.b = c;
! 530: abhigh.b = c+wlow*2;
! 531:
! 532: _kmulup2_(a,b,wlow,ablow.b); ablow.w = 2*wlow;
! 533: _kmulup2_(a+wlow,b+wlow,whigh,abhigh.b); abhigh.w = 2*whigh;
! 534:
! 535: W_NEW_UP2(aa,wlow);
! 536: _addup2_(&alow,&ahigh,&aa); aa.w = wlow;
! 537:
! 538: W_NEW_UP2(bb,wlow);
! 539: _addup2_(&blow,&bhigh,&bb); bb.w = wlow;
! 540:
! 541: W_NEW_UP2(mid,2*wlow);
! 542: _kmulup2_(aa.b,bb.b,wlow,mid.b); mid.w = 2*wlow;
! 543:
! 544: _addtoup2_(&ablow,&mid); _addtoup2_(&abhigh,&mid);
! 545:
! 546: cmid.w = 2*wlow; cmid.b = c+wlow;
! 547: _addtoup2_(&mid,&cmid);
! 548: }
! 549:
! 550: void _mulup2(a,b,c)
! 551: UP2 a,b,c;
! 552: {
! 553: int wa,wb,w;
! 554: int i;
! 555: unsigned int *ba,*bb;
! 556: unsigned int mul;
! 557:
! 558: if ( !a || !b || !a->w || !b->w ) {
! 559: c->w = 0; return;
! 560: }
! 561: wa = a->w; wb = b->w;
! 562: w = wa + wb;
! 563: bzero((char *)c->b,w*sizeof(unsigned int));
! 564: for ( i = 0, ba = a->b, bb = b->b; i < b->w; i++, bb++ )
! 565: if ( mul = *bb )
! 566: mulup2_n1(ba,wa,mul,c->b+i);
! 567: c->w = w;
! 568: _adjup2(c);
! 569: }
! 570:
! 571: void _mulup2_(a,b,c)
! 572: _UP2 a,b,c;
! 573: {
! 574: int wa,wb,w;
! 575: int i;
! 576: unsigned int *ba,*bb;
! 577: unsigned int mul;
! 578:
! 579: if ( !a || !b || !a->w || !b->w ) {
! 580: c->w = 0; return;
! 581: }
! 582: wa = a->w; wb = b->w;
! 583: w = wa + wb;
! 584: bzero((char *)c->b,w*sizeof(unsigned int));
! 585: for ( i = 0, ba = a->b, bb = b->b; i < b->w; i++, bb++ )
! 586: if ( mul = *bb )
! 587: mulup2_n1(ba,wa,mul,c->b+i);
! 588: c->w = w;
! 589: _adjup2_(c);
! 590: }
! 591:
! 592: void squareup2(n,nr)
! 593: UP2 n;
! 594: UP2 *nr;
! 595: {
! 596: int w,w2,i;
! 597: unsigned int s;
! 598: unsigned int *tb,*nb;
! 599: UP2 t;
! 600:
! 601: if ( !n )
! 602: *nr = 0;
! 603: else {
! 604: w = n->w; w2 = 2*w;
! 605: NEWUP2(t,w2); *nr = t;
! 606: tb = t->b;
! 607: nb = n->b;
! 608: for ( i = 0; i < w; i++ ) {
! 609: s = nb[i];
! 610: tb[2*i] = up2_sqtab[s&0xff]|(up2_sqtab[(s>>8)&0xff]<<16);
! 611: tb[2*i+1] = up2_sqtab[(s>>16)&0xff]|(up2_sqtab[s>>24]<<16);
! 612: }
! 613: t->w = tb[w2-1]?w2:w2-1;
! 614: }
! 615: }
! 616:
! 617: void _squareup2(n,nr)
! 618: UP2 n;
! 619: UP2 nr;
! 620: {
! 621: int w,w2,i;
! 622: unsigned int s;
! 623: unsigned int *tb,*nb;
! 624: UP2 t;
! 625:
! 626: if ( !n )
! 627: nr->w = 0;
! 628: else {
! 629: w = n->w; w2 = 2*w;
! 630: t = nr;
! 631: tb = t->b;
! 632: nb = n->b;
! 633: for ( i = 0; i < w; i++ ) {
! 634: s = nb[i];
! 635: tb[2*i] = up2_sqtab[s&0xff]|(up2_sqtab[(s>>8)&0xff]<<16);
! 636: tb[2*i+1] = up2_sqtab[(s>>16)&0xff]|(up2_sqtab[s>>24]<<16);
! 637: }
! 638: t->w = tb[w2-1]?w2:w2-1;
! 639: }
! 640: }
! 641:
! 642: void _adjup2(n)
! 643: UP2 n;
! 644: {
! 645: int i;
! 646: unsigned int *nb;
! 647:
! 648: nb = n->b;
! 649: for ( i = n->w - 1; i >= 0 && !nb[i]; i-- );
! 650: i++;
! 651: n->w = i;
! 652: }
! 653:
! 654: void _adjup2_(n)
! 655: _UP2 n;
! 656: {
! 657: int i;
! 658: unsigned int *nb;
! 659:
! 660: nb = n->b;
! 661: for ( i = n->w - 1; i >= 0 && !nb[i]; i-- );
! 662: i++;
! 663: n->w = i;
! 664: }
! 665:
! 666: void _addup2(a,b,c)
! 667: UP2 a,b,c;
! 668: {
! 669: int i,wa,wb,w;
! 670: UP2 t;
! 671: unsigned int *ab,*bb,*cb;
! 672:
! 673: if ( !a || !a->w ) {
! 674: _copyup2(b,c); return;
! 675: } else if ( !b || !b->w ) {
! 676: _copyup2(a,c); return;
! 677: }
! 678: wa = a->w; wb = b->w;
! 679: if ( wa < wb ) {
! 680: t = a; a = b; b = t;
! 681: w = wa; wa = wb; wb = w;
! 682: }
! 683: ab = a->b; bb = b->b; cb = c->b;
! 684: for ( i = 0; i < wb; i++ )
! 685: *cb++ = (*ab++)^(*bb++);
! 686: for ( ; i < wa; i++ )
! 687: *cb++ = *ab++;
! 688: c->w = wa;
! 689: _adjup2(c);
! 690: }
! 691:
! 692: /* a += b */
! 693:
! 694: void _addup2_destructive(a,b)
! 695: UP2 a,b;
! 696: {
! 697: int i,wa,wb;
! 698: unsigned int *ab,*bb;
! 699:
! 700: if ( !a->w ) {
! 701: _copyup2(b,a); return;
! 702: } else if ( !b->w )
! 703: return;
! 704: else {
! 705: wa = a->w; wb = b->w;
! 706: ab = a->b; bb = b->b;
! 707: if ( wa >= wb ) {
! 708: for ( i = 0; i < wb; i++ )
! 709: *ab++ ^= *bb++;
! 710: } else {
! 711: for ( i = 0; i < wa; i++ )
! 712: *ab++ ^= *bb++;
! 713: for ( ; i < wb; i++ )
! 714: *ab++ = *bb++;
! 715: a->w = wb;
! 716: }
! 717: _adjup2(a);
! 718: }
! 719: }
! 720:
! 721: void _addup2_(a,b,c)
! 722: _UP2 a,b,c;
! 723: {
! 724: int i,wa,wb,w;
! 725: _UP2 t;
! 726: unsigned int *ab,*bb,*cb;
! 727:
! 728: wa = a->w; wb = b->w;
! 729: if ( wa < wb ) {
! 730: t = a; a = b; b = t;
! 731: w = wa; wa = wb; wb = w;
! 732: }
! 733: ab = a->b; bb = b->b; cb = c->b;
! 734: for ( i = 0; i < wb; i++ )
! 735: *cb++ = (*ab++)^(*bb++);
! 736: for ( ; i < wa; i++ )
! 737: *cb++ = *ab++;
! 738: c->w = wa;
! 739: }
! 740:
! 741: void _addtoup2_(a,b)
! 742: _UP2 a,b;
! 743: {
! 744: int i,wa;
! 745: unsigned int *ab,*bb;
! 746:
! 747: wa = a->w;
! 748: ab = a->b; bb = b->b;
! 749: for ( i = 0; i < wa; i++ )
! 750: *bb++ ^= *ab++;
! 751: }
! 752:
! 753: /* 8bit x 8bit; also works if deg(a*b) < 32 */
! 754:
! 755: unsigned int mulup2_bb(a,b)
! 756: unsigned int a,b;
! 757: {
! 758: unsigned int t;
! 759:
! 760: if ( !a || !b )
! 761: return 0;
! 762: else {
! 763: t = 0;
! 764: while ( b ) {
! 765: if ( b & 1 )
! 766: t ^= a;
! 767: a <<= 1;
! 768: b >>= 1;
! 769: }
! 770: return t;
! 771: }
! 772: }
! 773:
! 774: void init_up2_tab()
! 775: {
! 776: unsigned int i,j;
! 777:
! 778: for ( i = 0; i < 256; i++ )
! 779: for ( j = 0; j <= i; j++ ) {
! 780: up2_bbtab[i<<8|j] = mulup2_bb(i,j);
! 781: up2_bbtab[j<<8|i] = up2_bbtab[i<<8|j];
! 782: }
! 783: for ( i = 0; i < 256; i++ )
! 784: up2_sqtab[i] = mulup2_bb(i,i);
! 785: }
! 786:
! 787: /*
! 788: compute q s.t. a*x^(BSH-1) = b*q+r
! 789: deg(b)=BSH-1, deg(a)<=BSH-1 => deg(q)<=BSH-1, deg(r)<=BSH-2
! 790: */
! 791:
! 792: INLINE unsigned int quoup2_11(a,b)
! 793: unsigned int a,b;
! 794: {
! 795: unsigned int q,i;
! 796:
! 797: q = 0;
! 798: for ( i = ((unsigned int)1)<<(BSH-1); i; i >>=1, b >>= 1 )
! 799: if ( i & a ) {
! 800: a ^= b;
! 801: q |= i;
! 802: }
! 803: return q;
! 804: }
! 805:
! 806: void divup2_1(a1,a2,e1,e2,qp,rp)
! 807: unsigned int a1,a2;
! 808: int e1,e2;
! 809: unsigned int *qp,*rp;
! 810: {
! 811: int i;
! 812: unsigned t,q;
! 813:
! 814: for ( i=e1-e2, t=1<<e1, a2<<=i, q = 0; i>=0; i--, t>>=1, a2>>=1 ) {
! 815: q<<=1;
! 816: if ( a1 & t ) {
! 817: q |= 1;
! 818: a1 ^= a2;
! 819: }
! 820: }
! 821: *qp = q; *rp = a1;
! 822: }
! 823:
! 824: void qrup2(a,b,q,r)
! 825: UP2 a,b;
! 826: UP2 *q,*r;
! 827: {
! 828: unsigned int msa,msb,t,q0;
! 829: int s,i,wq,wb;
! 830: UP2 as,bs,_q;
! 831:
! 832: if ( !b )
! 833: error("qrup2 : division by 0");
! 834: else if ( !a ) {
! 835: *q = 0; *r = 0; return;
! 836: } else if ( degup2(a) < degup2(b) ) {
! 837: *q = 0; *r = a; return;
! 838: }
! 839: msb = b->b[b->w-1];
! 840: for ( t = msb, s = 0; t; t>>=1, s++ );
! 841: s = BSH-s;
! 842:
! 843: W_NEWUP2(as,a->w+2); W_NEWUP2(bs,b->w+1);
! 844: _bshiftup2(a,-s,as); _bshiftup2(b,-s,bs);
! 845: as->b[as->w] = 0;
! 846:
! 847: wb = bs->w;
! 848: wq = as->w-wb;
! 849: NEWUP2(_q,wq+1); *q = _q;
! 850:
! 851: msb = bs->b[bs->w-1];
! 852: for ( i = wq; i >= 0; i-- ) {
! 853: msa = (as->b[wb+i]<<1) | (as->b[wb+i-1]>>(BSH-1));
! 854: if ( msa ) {
! 855: q0 = quoup2_11(msa,msb);
! 856: mulup2_n1(bs->b,wb,q0,as->b+i);
! 857: } else
! 858: q0 = 0;
! 859: _q->b[i] = q0;
! 860: }
! 861: for ( i = wq; i >= 0 && !_q->b[i]; i-- );
! 862: _q->w = i+1;
! 863:
! 864: for ( i = wb-1; i >= 0 && !as->b[i]; i-- );
! 865: if ( i < 0 )
! 866: *r = 0;
! 867: else {
! 868: as->w = i+1;
! 869: NEWUP2(*r,as->w);
! 870: _bshiftup2(as,s,*r);
! 871: }
! 872: }
! 873:
! 874: /* q->w >= a->w-b->w+2, r->w >= b->w */
! 875:
! 876: void _qrup2(a,b,q,r)
! 877: UP2 a,b;
! 878: UP2 q,r;
! 879: {
! 880: unsigned int msa,msb,t,q0;
! 881: int s,i,wq,wb;
! 882:
! 883: if ( !b || !b->w )
! 884: error("_qrup2 : division by 0");
! 885: else if ( !a || !a->w ) {
! 886: q->w = 0; r->w = 0; return;
! 887: } else if ( degup2(a) < degup2(b) ) {
! 888: q->w = 0; _copyup2(a,r); return;
! 889: }
! 890: msb = b->b[b->w-1];
! 891: for ( t = msb, s = BSH; t; t>>=1, s-- );
! 892:
! 893: _copyup2(a,r);
! 894: wb = b->w;
! 895: wq = r->w-wb;
! 896: r->b[r->w] = 0;
! 897:
! 898: msb = (b->b[b->w-1]<<s)|(b->w==1||!s?0:b->b[b->w-2]>>(BSH-s));
! 899: for ( i = wq; i >= 0; i-- ) {
! 900: msa = (s==BSH-1?0:r->b[wb+i]<<(s+1))|(wb+i-1<0?0:r->b[wb+i-1]>>(BSH-1-s));
! 901: if ( msa ) {
! 902: q0 = quoup2_11(msa,msb);
! 903: mulup2_n1(b->b,wb,q0,r->b+i);
! 904: } else
! 905: q0 = 0;
! 906: q->b[i] = q0;
! 907: }
! 908: for ( i = wq; i >= 0 && !q->b[i]; i-- );
! 909: q->w = i+1;
! 910:
! 911: for ( i = wb-1; i >= 0 && !r->b[i]; i-- );
! 912: if ( i < 0 )
! 913: r->w = 0;
! 914: else
! 915: r->w = i+1;
! 916: }
! 917:
! 918: void remup2(a,b,c)
! 919: UP2 a,b;
! 920: UP2 *c;
! 921: {
! 922: unsigned int msa,msb,t,q;
! 923: int s,i,wq,wb;
! 924: UP2 as,bs,r;
! 925:
! 926: if ( !b || !b->w )
! 927: error("remup2 : division by 0");
! 928: else if ( !a || !a->w ) {
! 929: *c = 0; return;
! 930: } else if ( degup2(a) < degup2(b) ) {
! 931: *c = a; return;
! 932: }
! 933: msb = b->b[b->w-1];
! 934: for ( t = msb, s = 0; t; t>>=1, s++ );
! 935: s = BSH-s;
! 936:
! 937: W_NEWUP2(as,a->w+2); W_NEWUP2(bs,b->w+1);
! 938: _bshiftup2(a,-s,as); _bshiftup2(b,-s,bs);
! 939: as->b[as->w] = 0;
! 940:
! 941: wb = bs->w;
! 942: wq = as->w-wb;
! 943: msb = bs->b[bs->w-1];
! 944: for ( i = wq; i >= 0; i-- ) {
! 945: msa = (as->b[wb+i]<<1) | (as->b[wb+i-1]>>(BSH-1));
! 946: if ( msa ) {
! 947: q = quoup2_11(msa,msb);
! 948: mulup2_n1(bs->b,wb,q,as->b+i);
! 949: }
! 950: }
! 951: for ( i = wb-1; i >= 0 && !as->b[i]; i-- );
! 952: if ( i < 0 )
! 953: *c = 0;
! 954: else {
! 955: as->w = i+1;
! 956: NEWUP2(r,as->w); *c = r;
! 957: _bshiftup2(as,s,r);
! 958: }
! 959: }
! 960:
! 961: void _remup2(a,b,c)
! 962: UP2 a,b,c;
! 963: {
! 964: unsigned int msa,msb,t,q;
! 965: int s,i,wq,wb;
! 966: UP2 as,bs;
! 967:
! 968: if ( !b || !b->w )
! 969: error("_remup2 : division by 0");
! 970: else if ( !a || !a->w ) {
! 971: c->w = 0; return;
! 972: } else if ( degup2(a) < degup2(b) ) {
! 973: _copyup2(a,c); return;
! 974: }
! 975: msb = b->b[b->w-1];
! 976: for ( t = msb, s = 0; t; t>>=1, s++ );
! 977: s = BSH-s;
! 978:
! 979: W_NEWUP2(as,a->w+2); W_NEWUP2(bs,b->w+1);
! 980: _bshiftup2(a,-s,as); _bshiftup2(b,-s,bs);
! 981: as->b[as->w] = 0;
! 982:
! 983: wb = bs->w;
! 984: wq = as->w-wb;
! 985: msb = bs->b[bs->w-1];
! 986: for ( i = wq; i >= 0; i-- ) {
! 987: msa = (as->b[wb+i]<<1) | (as->b[wb+i-1]>>(BSH-1));
! 988: if ( msa ) {
! 989: q = quoup2_11(msa,msb);
! 990: mulup2_n1(bs->b,wb,q,as->b+i);
! 991: }
! 992: }
! 993: for ( i = wb-1; i >= 0 && !as->b[i]; i-- );
! 994: if ( i < 0 )
! 995: c->w = 0;
! 996: else {
! 997: as->w = i+1;
! 998: _bshiftup2(as,s,c);
! 999: }
! 1000: }
! 1001:
! 1002: /* b = b->w|b->b[0]|b->b[1]|... -> b = x^b->[0]+x^b->[1]+... (b->w terms) */
! 1003:
! 1004: void remup2_sparse(a,b,c)
! 1005: UP2 a,b;
! 1006: UP2 *c;
! 1007: {
! 1008: int i,j,k,wa,wb,d,ds,db,dr,r;
! 1009: unsigned int ha,hb;
! 1010: unsigned int *tb;
! 1011:
! 1012: UP2 t,s;
! 1013:
! 1014: if ( !b )
! 1015: error("remup2_sparse : division by 0");
! 1016: else if ( !a ) {
! 1017: *c = 0; return;
! 1018: } else if ( degup2(a) < (db = degup2_sparse(b)) ) {
! 1019: *c = a; return;
! 1020: } else if ( b->w == (int)(b->b[0])+1 ) {
! 1021: NEWUP2(*c,a->w);
! 1022: _copyup2(a,*c);
! 1023: remup2_type1_destructive(*c,b->b[0]);
! 1024: if ( (*c)->w <= 0 )
! 1025: *c = 0;
! 1026: } else {
! 1027: W_NEWUP2(t,a->w); _copyup2(a,t);
! 1028: wa = a->w; wb = b->w; tb = t->b;
! 1029: for ( i = wa-1; (ds = BSH*i-db) >= 0; ) {
! 1030: if ( !(ha = tb[i]) )
! 1031: i--;
! 1032: else {
! 1033: tb[i] = 0;
! 1034: for ( j = 1; j < wb; j++ ) {
! 1035: d = ds+b->b[j];
! 1036: k = d/BSH; r = d%BSH;
! 1037: if ( !r )
! 1038: tb[k] ^= ha;
! 1039: else {
! 1040: tb[k] ^= (ha<<r);
! 1041: if ( k+1 <= i )
! 1042: tb[k+1] ^= (ha>>(BSH-r));
! 1043: }
! 1044: }
! 1045: if ( !tb[i] )
! 1046: i--;
! 1047: }
! 1048: }
! 1049: dr = db%BSH;
! 1050: hb = 1<<dr;
! 1051: i = db/BSH;
! 1052: while ( (ha=tb[i]) >= hb ) {
! 1053: ha >>= dr;
! 1054: t->b[i] &= (hb-1);
! 1055: for ( j = 1; j < wb; j++ ) {
! 1056: d = b->b[j];
! 1057: k = d/BSH; r = d%BSH;
! 1058: if ( !r )
! 1059: tb[k] ^= ha;
! 1060: else {
! 1061: tb[k] ^= (ha<<r);
! 1062: if ( k+1 <= i )
! 1063: tb[k+1] ^= (ha>>(BSH-r));
! 1064: }
! 1065: }
! 1066: }
! 1067: t->w = i+1;
! 1068: _adjup2(t);
! 1069: if ( t->w == 0 )
! 1070: *c = 0;
! 1071: else {
! 1072: NEWUP2(s,t->w); *c = s;
! 1073: _copyup2(t,s);
! 1074: }
! 1075: }
! 1076: }
! 1077:
! 1078: void remup2_sparse_destructive(a,b)
! 1079: UP2 a,b;
! 1080: {
! 1081: int i,j,k,wb,d,ds,db,dr,r;
! 1082: unsigned int ha,hb;
! 1083: unsigned int *ab,*bb;
! 1084:
! 1085: if ( !b )
! 1086: error("remup2_sparse_destructive : division by 0");
! 1087: else if ( !a || !a->w || ( degup2(a) < (db = degup2_sparse(b)) ) )
! 1088: return;
! 1089: else if ( b->w == 3 )
! 1090: remup2_3_destructive(a,b);
! 1091: else if ( b->w == 5 )
! 1092: remup2_5_destructive(a,b);
! 1093: else if ( b->w == (int)(b->b[0])+1 )
! 1094: remup2_type1_destructive(a,b->b[0]);
! 1095: else {
! 1096: wb = b->w; ab = a->b; bb = b->b;
! 1097: for ( i = a->w-1; (ds = (i<<5)-db) >= 0; ) {
! 1098: if ( !(ha = ab[i]) )
! 1099: i--;
! 1100: else {
! 1101: ab[i] = 0;
! 1102: for ( j = 1; j < wb; j++ ) {
! 1103: d = ds+bb[j]; k = d>>5; r = d&31;
! 1104: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1105: }
! 1106: if ( !ab[i] )
! 1107: i--;
! 1108: }
! 1109: }
! 1110: i = db>>5; dr = db&31;
! 1111: for ( hb = (1<<dr)-1; (ha=ab[i]) > hb; ) {
! 1112: ha >>= dr;
! 1113: ab[i] &= hb;
! 1114: for ( j = 1; j < wb; j++ ) {
! 1115: d = bb[j]; k = d>>5; r = d&31;
! 1116: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1117: }
! 1118: }
! 1119: a->w = i+1;
! 1120: _adjup2(a);
! 1121: }
! 1122: }
! 1123:
! 1124: /* b = x^d+x^(d-1)+...+1 */
! 1125:
! 1126: void remup2_type1_destructive(a,d)
! 1127: UP2 a;
! 1128: int d;
! 1129: {
! 1130: int i,k,ds,db,dr;
! 1131: unsigned int ha,hb,r;
! 1132: unsigned int *ab;
! 1133:
! 1134: ab = a->b; db = d+1;
! 1135: for ( i = a->w-1; (ds = (i<<5)-db) >= 0; ) {
! 1136: if ( !(ha = ab[i]) ) i--;
! 1137: else {
! 1138: ab[i] = 0;
! 1139: k = ds>>5; r = ds&31;
! 1140: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1141: if ( !ab[i] ) i--;
! 1142: }
! 1143: }
! 1144: i = db>>5; dr = db&31;
! 1145: for ( hb = (1<<dr)-1; (ha=ab[i]) > hb; ) {
! 1146: ha >>= dr; ab[i] &= hb; ab[0] ^= ha;
! 1147: }
! 1148: i = d>>5; hb = 1<<(d&31);
! 1149: if ( ab[i]&hb ) {
! 1150: ab[i] = (ab[i]^hb)^(hb-1);
! 1151: for ( k = i-1; k >= 0; k-- ) ab[k] ^= 0xffffffff;
! 1152: }
! 1153: a->w = i+1;
! 1154: _adjup2(a);
! 1155: }
! 1156:
! 1157: /* b = x^b->b[0]+x^b->b[1]+1 */
! 1158:
! 1159: void remup2_3_destructive(a,b)
! 1160: UP2 a,b;
! 1161: {
! 1162: int i,k,d,ds,db,db1,dr;
! 1163: unsigned int ha,hb,r;
! 1164: unsigned int *ab,*bb;
! 1165:
! 1166: ab = a->b; bb = b->b;
! 1167: db = bb[0]; db1 = bb[1];
! 1168: for ( i = a->w-1; (ds = (i<<5)-db) >= 0; ) {
! 1169: if ( !(ha = ab[i]) )
! 1170: i--;
! 1171: else {
! 1172: ab[i] = 0;
! 1173: d = ds+db1; k = d>>5; r = d&31;
! 1174: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1175: d = ds; k = d>>5; r = d&31;
! 1176: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1177: if ( !ab[i] )
! 1178: i--;
! 1179: }
! 1180: }
! 1181: i = db>>5; dr = db&31;
! 1182: k = db1>>5; r = db1&31;
! 1183: for ( hb = (1<<dr)-1; (ha=ab[i]) > hb; ) {
! 1184: ha >>= dr;
! 1185: ab[i] &= hb;
! 1186: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1187: ab[0] ^= ha;
! 1188: }
! 1189: a->w = i+1;
! 1190: _adjup2(a);
! 1191: }
! 1192:
! 1193: /* b = x^b->b[0]+x^b->b[1]+x^b->b[2]+x^b->b[3]+1 */
! 1194:
! 1195: void remup2_5_destructive(a,b)
! 1196: UP2 a,b;
! 1197: {
! 1198: int i,d,ds,db,db1,db2,db3,dr;
! 1199: int k,k1,k2,k3;
! 1200: unsigned int ha,hb,r,r1,r2,r3;
! 1201: unsigned int *ab,*bb;
! 1202:
! 1203: ab = a->b; bb = b->b;
! 1204: db = bb[0]; db1 = bb[1]; db2 = bb[2]; db3 = bb[3];
! 1205: for ( i = a->w-1; (ds = (i<<5)-db) >= 0; ) {
! 1206: if ( !(ha = ab[i]) )
! 1207: i--;
! 1208: else {
! 1209: ab[i] = 0;
! 1210: d = ds+db1; k = d>>5; r = d&31;
! 1211: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1212: d = ds+db2; k = d>>5; r = d&31;
! 1213: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1214: d = ds+db3; k = d>>5; r = d&31;
! 1215: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1216: d = ds; k = d>>5; r = d&31;
! 1217: REMUP2_ONESTEP(ab,k,r,i,ha)
! 1218: if ( !ab[i] )
! 1219: i--;
! 1220: }
! 1221: }
! 1222: i = db>>5; dr = db&31;
! 1223: k1 = db1>>5; r1 = db1&31;
! 1224: k2 = db2>>5; r2 = db2&31;
! 1225: k3 = db3>>5; r3 = db3&31;
! 1226: for ( hb = (1<<dr)-1; (ha=ab[i]) > hb; ) {
! 1227: ha >>= dr;
! 1228: ab[i] &= hb;
! 1229: REMUP2_ONESTEP(ab,k1,r1,i,ha)
! 1230: REMUP2_ONESTEP(ab,k2,r2,i,ha)
! 1231: REMUP2_ONESTEP(ab,k3,r3,i,ha)
! 1232: ab[0] ^= ha;
! 1233: }
! 1234: a->w = i+1;
! 1235: _adjup2(a);
! 1236: }
! 1237:
! 1238: void _invup2_1(f1,f2,a1,b1)
! 1239: unsigned int f1,f2,*a1,*b1;
! 1240: {
! 1241: unsigned int p1,p2,p3,q1,q2,q3,g1,g2,q,r;
! 1242: int d1,d2;
! 1243:
! 1244: p1 = 1; p2 = 0;
! 1245: q1 = 0; q2 = 1;
! 1246: g1 = f1; g2 = f2;
! 1247: d1 = degup2_1(g1); d2 = degup2_1(g2);
! 1248: while ( g2 ) {
! 1249: divup2_1(g1,g2,d1,d2,&q,&r);
! 1250: g1 = g2; g2 = r;
! 1251: GCD_COEF(q,p1,p2,p3,q1,q2,q3)
! 1252: p1 = p2; p2 = p3;
! 1253: q1 = q2; q2 = q3;
! 1254: d1 = d2; d2 = degup2_1(g2);
! 1255: }
! 1256: *a1 = p1; *b1 = q1;
! 1257: }
! 1258:
! 1259: void _gcdup2_1(f1,f2,gcd)
! 1260: unsigned int f1,f2,*gcd;
! 1261: {
! 1262: unsigned int g1,g2,q,r;
! 1263: int d1,d2;
! 1264:
! 1265: if ( !f1 )
! 1266: *gcd = f2;
! 1267: else if ( !f2 )
! 1268: *gcd = f1;
! 1269: else {
! 1270: g1 = f1; g2 = f2;
! 1271: d1 = degup2_1(g1); d2 = degup2_1(g2);
! 1272: while ( 1 ) {
! 1273: divup2_1(g1,g2,d1,d2,&q,&r);
! 1274: if ( !r ) {
! 1275: *gcd = g2;
! 1276: return;
! 1277: }
! 1278: g1 = g2; g2 = r;
! 1279: d1 = d2; d2 = degup2_1(g2);
! 1280: }
! 1281: }
! 1282: }
! 1283:
! 1284: static struct oEGT eg_a,eg_b;
! 1285:
! 1286: void up2_init_eg() {
! 1287: init_eg(&eg_a); init_eg(&eg_b);
! 1288: }
! 1289:
! 1290: void up2_show_eg() {
! 1291: print_eg("A",&eg_a);
! 1292: print_eg("B",&eg_b);
! 1293: printf("\n");
! 1294: }
! 1295:
! 1296: void invup2(a,m,inv)
! 1297: UP2 a,m;
! 1298: UP2 *inv;
! 1299: {
! 1300: int w,e1,e2,d1,d2;
! 1301: UP2 g1,g2,g3,a1,a2,a3,q,r,w1,w2,t;
! 1302: unsigned int p1,p2,p3,q0,q1,q2,q3,h1,h2,h3;
! 1303:
! 1304: if ( degup2(a) >= degup2(m) ) {
! 1305: remup2(a,m,&t); a = t;
! 1306: }
! 1307: w = m->w+2;
! 1308: W_NEWUP2(g1,w); W_NEWUP2(g2,w); W_NEWUP2(g3,w);
! 1309: W_NEWUP2(q,w); W_NEWUP2(r,w);
! 1310: W_NEWUP2(a1,w); W_NEWUP2(a2,w); W_NEWUP2(a3,w);
! 1311: W_NEWUP2(w1,w); W_NEWUP2(w2,w);
! 1312:
! 1313: a1->w = 1; a1->b[0] = 1;
! 1314: a2->w = 0;
! 1315: _copyup2(a,g1); _copyup2(m,g2);
! 1316:
! 1317: while ( 1 ) {
! 1318: d1 = degup2(g1); d2 = degup2(g2);
! 1319: if ( d1 < d2 ) {
! 1320: t = g1; g1 = g2; g2 = t;
! 1321: t = a1; a1 = a2; a2 = t;
! 1322: } else if ( d1 < 32 ) {
! 1323: _invup2_1(g1->b[0],g2->b[0],&p1,&p2);
! 1324: _mulup2_1(a1,p1,w1);
! 1325: _mulup2_1(a2,p2,w2);
! 1326: addup2(w1,w2,inv);
! 1327: return;
! 1328: } else if ( d1-d2 >= 16 ) {
! 1329: _qrup2(g1,g2,q,g3);
! 1330: t = g1; g1 = g2;
! 1331: if ( !g3->w ) {
! 1332: NEWUP2(t,a2->w); *inv = t;
! 1333: _copyup2(a2,t);
! 1334: return;
! 1335: } else {
! 1336: g2 = g3; g3 = t;
! 1337: }
! 1338: _mulup2(a2,q,w1); _addup2(a1,w1,a3);
! 1339: t = a1; a1 = a2; a2 = a3; a3 = t;
! 1340: } else {
! 1341: _bshiftup2(g1,d1-31,w1); h1 = w1->b[0];
! 1342: _bshiftup2(g2,d1-31,w2); h2 = w2->b[0];
! 1343: p1 = 1; p2 = 0;
! 1344: q1 = 0; q2 = 1;
! 1345: /* get_eg(&eg0); */
! 1346: e1 = degup2_1(h1); /* e1 must be 31 */
! 1347: while ( 1 ) {
! 1348: e2 = degup2_1(h2);
! 1349: if ( e2 <= 15 )
! 1350: break;
! 1351: divup2_1(h1,h2,e1,e2,&q0,&h3);
! 1352: GCD_COEF(q0,p1,p2,p3,q1,q2,q3)
! 1353: p1 = p2; p2 = p3;
! 1354: q1 = q2; q2 = q3;
! 1355: h1 = h2; h2 = h3;
! 1356: e1 = e2;
! 1357: }
! 1358: /* get_eg(&eg1); */
! 1359: _mulup2_1(g1,p1,w1); _mulup2_1(g2,q1,w2); _addup2(w1,w2,g3);
! 1360: _mulup2_1(g1,p2,w1); _mulup2_1(g2,q2,w2); _addup2(w1,w2,g2);
! 1361: t = g1; g1 = g3; g3 = t;
! 1362: _mulup2_1(a1,p1,w1); _mulup2_1(a2,q1,w2); _addup2(w1,w2,a3);
! 1363: _mulup2_1(a1,p2,w1); _mulup2_1(a2,q2,w2); _addup2(w1,w2,a2);
! 1364: t = a1; a1 = a3; a3 = t;
! 1365: /* get_eg(&eg2); */
! 1366: /* add_eg(&eg_a,&eg0,&eg1); */
! 1367: /* add_eg(&eg_b,&eg1,&eg2); */
! 1368: }
! 1369: }
! 1370: }
! 1371:
! 1372: void gcdup2(a,m,gcd)
! 1373: UP2 a,m;
! 1374: UP2 *gcd;
! 1375: {
! 1376: int w,e1,e2,d1,d2;
! 1377: UP2 g1,g2,g3,q,r,w1,w2,t;
! 1378: unsigned int p1,p2,p3,q0,q1,q2,q3,h1,h2,h3;
! 1379:
! 1380: if ( !a ) {
! 1381: *gcd = m; return;
! 1382: } else if ( !m ) {
! 1383: *gcd = a; return;
! 1384: }
! 1385: if ( degup2(a) >= degup2(m) ) {
! 1386: remup2(a,m,&t); a = t;
! 1387: if ( !a ) {
! 1388: *gcd = m; return;
! 1389: }
! 1390: }
! 1391: w = m->w+2;
! 1392: W_NEWUP2(g1,w); W_NEWUP2(g2,w); W_NEWUP2(g3,w);
! 1393: W_NEWUP2(q,w); W_NEWUP2(r,w);
! 1394: W_NEWUP2(w1,w); W_NEWUP2(w2,w);
! 1395:
! 1396: _copyup2(a,g1); _copyup2(m,g2);
! 1397:
! 1398: while ( 1 ) {
! 1399: d1 = degup2(g1); d2 = degup2(g2);
! 1400: if ( d1 < d2 ) {
! 1401: t = g1; g1 = g2; g2 = t;
! 1402: } else if ( d2 < 0 ) {
! 1403: NEWUP2(t,g1->w); *gcd = t;
! 1404: _copyup2(g1,t);
! 1405: return;
! 1406: } else if ( d1 < 32 ) {
! 1407: NEWUP2(t,1); t->w = 1; *gcd = t;
! 1408: _gcdup2_1(g1->b[0],g2->b[0],&t->b[0]);
! 1409: return;
! 1410: } else if ( d1-d2 >= 16 ) {
! 1411: _qrup2(g1,g2,q,g3);
! 1412: t = g1; g1 = g2;
! 1413: if ( !g3->w ) {
! 1414: NEWUP2(t,g2->w); *gcd = t;
! 1415: _copyup2(g2,t);
! 1416: return;
! 1417: } else {
! 1418: g2 = g3; g3 = t;
! 1419: }
! 1420: } else {
! 1421: _bshiftup2(g1,d1-31,w1); h1 = w1->b[0];
! 1422: _bshiftup2(g2,d1-31,w2); h2 = w2->b[0];
! 1423: p1 = 1; p2 = 0;
! 1424: q1 = 0; q2 = 1;
! 1425: e1 = degup2_1(h1); /* e1 must be 31 */
! 1426: while ( 1 ) {
! 1427: e2 = degup2_1(h2);
! 1428: if ( e2 <= 15 )
! 1429: break;
! 1430: divup2_1(h1,h2,e1,e2,&q0,&h3);
! 1431: GCD_COEF(q0,p1,p2,p3,q1,q2,q3)
! 1432: p1 = p2; p2 = p3;
! 1433: q1 = q2; q2 = q3;
! 1434: h1 = h2; h2 = h3;
! 1435: e1 = e2;
! 1436: }
! 1437: _mulup2_h(g1,p1,w1); _mulup2_h(g2,q1,w2); _addup2(w1,w2,g3);
! 1438: _mulup2_h(g1,p2,w1); _mulup2_h(g2,q2,w2); _addup2(w1,w2,g2);
! 1439: t = g1; g1 = g3; g3 = t;
! 1440: }
! 1441: }
! 1442: }
! 1443:
! 1444: void chsgnup2(a,c)
! 1445: UP2 a,*c;
! 1446: {
! 1447: *c = a;
! 1448: }
! 1449:
! 1450: void pwrmodup2(a,b,m,c)
! 1451: UP2 a;
! 1452: Q b;
! 1453: UP2 m;
! 1454: UP2 *c;
! 1455: {
! 1456: N n;
! 1457: UP2 y,t,t1;
! 1458: int k;
! 1459:
! 1460: if ( !b )
! 1461: *c = (UP2)ONEUP2;
! 1462: else if ( !a )
! 1463: *c = 0;
! 1464: else {
! 1465: y = (UP2)ONEUP2;
! 1466: n = NM(b);
! 1467: if ( !m )
! 1468: for ( k = n_bits(n)-1; k >= 0; k-- ) {
! 1469: squareup2(y,&t);
! 1470: if ( n->b[k/BSH] & (1<<(k%BSH)) )
! 1471: mulup2(t,a,&y);
! 1472: else
! 1473: y = t;
! 1474: }
! 1475: else
! 1476: for ( k = n_bits(n)-1; k >= 0; k-- ) {
! 1477: squareup2(y,&t);
! 1478: remup2(t,m,&t1); t = t1;
! 1479: if ( n->b[k/BSH] & (1<<(k%BSH)) ) {
! 1480: mulup2(t,a,&y);
! 1481: remup2(y,m,&t1); y = t1;
! 1482: }
! 1483: else
! 1484: y = t;
! 1485: }
! 1486: *c = y;
! 1487: }
! 1488: }
! 1489:
! 1490: void pwrmodup2_sparse(a,b,m,c)
! 1491: UP2 a;
! 1492: Q b;
! 1493: UP2 m;
! 1494: UP2 *c;
! 1495: {
! 1496: N n;
! 1497: UP2 y,t,t1;
! 1498: int k;
! 1499:
! 1500: if ( !b )
! 1501: *c = (UP2)ONEUP2;
! 1502: else if ( !a )
! 1503: *c = 0;
! 1504: else {
! 1505: y = (UP2)ONEUP2;
! 1506: n = NM(b);
! 1507: if ( !m )
! 1508: for ( k = n_bits(n)-1; k >= 0; k-- ) {
! 1509: squareup2(y,&t);
! 1510: if ( n->b[k/BSH] & (1<<(k%BSH)) )
! 1511: mulup2(t,a,&y);
! 1512: else
! 1513: y = t;
! 1514: }
! 1515: else
! 1516: for ( k = n_bits(n)-1; k >= 0; k-- ) {
! 1517: squareup2(y,&t);
! 1518: remup2_sparse(t,m,&t1); t = t1;
! 1519: if ( n->b[k/BSH] & (1<<(k%BSH)) ) {
! 1520: mulup2(t,a,&y);
! 1521: remup2_sparse(y,m,&t1); y = t1;
! 1522: }
! 1523: else
! 1524: y = t;
! 1525: }
! 1526: *c = y;
! 1527: }
! 1528: }
! 1529:
! 1530: int compup2(n1,n2)
! 1531: UP2 n1,n2;
! 1532: {
! 1533: int i;
! 1534: unsigned int *m1,*m2;
! 1535:
! 1536: if ( !n1 )
! 1537: if ( !n2 )
! 1538: return 0;
! 1539: else
! 1540: return -1;
! 1541: else if ( !n2 )
! 1542: return 1;
! 1543: else if ( n1->w > n2->w )
! 1544: return 1;
! 1545: else if ( n1->w < n2->w )
! 1546: return -1;
! 1547: else {
! 1548: for ( i = n1->w-1, m1 = n1->b+i, m2 = n2->b+i;
! 1549: i >= 0; i--, m1--, m2-- )
! 1550: if ( *m1 > *m2 )
! 1551: return 1;
! 1552: else if ( *m1 < *m2 )
! 1553: return -1;
! 1554: return 0;
! 1555: }
! 1556: }
! 1557:
! 1558: void _copyup2(n,r)
! 1559: UP2 n,r;
! 1560: {
! 1561: r->w = n->w;
! 1562: bcopy(n->b,r->b,n->w*sizeof(unsigned int));
! 1563: }
! 1564:
! 1565: void _bshiftup2(n,b,r)
! 1566: UP2 n;
! 1567: int b;
! 1568: UP2 r;
! 1569: {
! 1570: int w,l,nl,i,j;
! 1571: unsigned int msw;
! 1572: unsigned int *p,*pr;
! 1573:
! 1574: if ( b == 0 ) {
! 1575: _copyup2(n,r); return;
! 1576: }
! 1577: if ( b > 0 ) { /* >> */
! 1578: w = b / BSH; l = n->w-w;
! 1579: if ( l <= 0 ) {
! 1580: r->w = 0; return;
! 1581: }
! 1582: b %= BSH; p = n->b+w;
! 1583: if ( !b ) {
! 1584: r->w = l;
! 1585: bcopy(p,r->b,l*sizeof(unsigned int));
! 1586: return;
! 1587: }
! 1588: msw = p[l-1];
! 1589: for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
! 1590: if ( b >= i ) {
! 1591: l--;
! 1592: if ( !l ) {
! 1593: r->w = 0; return;
! 1594: }
! 1595: r->w = l; pr = r->b;
! 1596: for ( j = 0; j < l; j++, p++ )
! 1597: *pr++ = (*(p+1)<<(BSH-b))|(*p>>b);
! 1598: } else {
! 1599: r->w = l; pr = r->b;
! 1600: for ( j = 1; j < l; j++, p++ )
! 1601: *pr++ = (*(p+1)<<(BSH-b))|(*p>>b);
! 1602: *pr = *p>>b;
! 1603: }
! 1604: } else { /* << */
! 1605: b = -b;
! 1606: w = b / BSH; b %= BSH; l = n->w; p = n->b;
! 1607: if ( !b ) {
! 1608: nl = l+w; r->w = nl;
! 1609: bzero((char *)r->b,w*sizeof(unsigned int));
! 1610: bcopy(p,r->b+w,l*sizeof(unsigned int));
! 1611: return;
! 1612: }
! 1613: msw = p[l-1];
! 1614: for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
! 1615: if ( b + i > BSH ) {
! 1616: nl = l+w+1;
! 1617: r->w = nl; pr = r->b+w;
! 1618: bzero((char *)r->b,w*sizeof(unsigned int));
! 1619: *pr++ = *p++<<b;
! 1620: for ( j = 1; j < l; j++, p++ )
! 1621: *pr++ = (*p<<b)|(*(p-1)>>(BSH-b));
! 1622: *pr = *(p-1)>>(BSH-b);
! 1623: } else {
! 1624: nl = l+w;
! 1625: r->w = nl; pr = r->b+w;
! 1626: bzero((char *)r->b,w*sizeof(unsigned int));
! 1627: *pr++ = *p++<<b;
! 1628: for ( j = 1; j < l; j++, p++ )
! 1629: *pr++ = (*p<<b)|(*(p-1)>>(BSH-b));
! 1630: }
! 1631: }
! 1632: }
! 1633:
! 1634: void _bshiftup2_destructive(n,b)
! 1635: UP2 n;
! 1636: int b;
! 1637: {
! 1638: int w,l,nl,i,j;
! 1639: unsigned int msw;
! 1640: unsigned int *p,*pr;
! 1641:
! 1642: if ( b == 0 || !n->w )
! 1643: return;
! 1644: if ( b > 0 ) { /* >> */
! 1645: w = b / BSH; l = n->w-w;
! 1646: if ( l <= 0 ) {
! 1647: n->w = 0; return;
! 1648: }
! 1649: b %= BSH; p = n->b+w;
! 1650: if ( !b ) {
! 1651: n->w = l;
! 1652: bcopy(p,n->b,l*sizeof(unsigned int));
! 1653: return;
! 1654: }
! 1655: msw = p[l-1];
! 1656: for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
! 1657: if ( b >= i ) {
! 1658: l--;
! 1659: if ( !l ) {
! 1660: n->w = 0; return;
! 1661: }
! 1662: n->w = l; pr = n->b;
! 1663: for ( j = 0; j < l; j++, p++ )
! 1664: *pr++ = (*(p+1)<<(BSH-b))|(*p>>b);
! 1665: } else {
! 1666: n->w = l; pr = n->b;
! 1667: for ( j = 1; j < l; j++, p++ )
! 1668: *pr++ = (*(p+1)<<(BSH-b))|(*p>>b);
! 1669: *pr = *p>>b;
! 1670: }
! 1671: } else { /* << */
! 1672: b = -b;
! 1673: w = b / BSH; b %= BSH; l = n->w; p = n->b;
! 1674: if ( !b ) {
! 1675: nl = l+w; n->w = nl;
! 1676: bcopy(p,n->b+w,l*sizeof(unsigned int));
! 1677: bzero((char *)n->b,w*sizeof(unsigned int));
! 1678: return;
! 1679: }
! 1680: msw = p[l-1];
! 1681: for ( i = BSH-1; !(msw&(((unsigned int)1)<<i)); i-- ); i++;
! 1682: if ( b + i > BSH ) {
! 1683: nl = l+w+1;
! 1684: n->w = nl; p = n->b+l-1; pr = n->b+w+l;
! 1685: *pr-- = *p>>(BSH-b);
! 1686: for ( j = l-1; j >= 1; j--, p-- )
! 1687: *pr-- = (*p<<b)|(*(p-1)>>(BSH-b));
! 1688: *pr = *p<<b;
! 1689: bzero((char *)n->b,w*sizeof(unsigned int));
! 1690: } else {
! 1691: nl = l+w;
! 1692: n->w = nl; p = n->b+l-1; pr = n->b+w+l-1;
! 1693: for ( j = l-1; j >= 1; j--, p-- )
! 1694: *pr-- = (*p<<b)|(*(p-1)>>(BSH-b));
! 1695: *pr = *p<<b;
! 1696: bzero((char *)n->b,w*sizeof(unsigned int));
! 1697: }
! 1698: }
! 1699: }
! 1700:
! 1701: void diffup2(f,r)
! 1702: UP2 f;
! 1703: UP2 *r;
! 1704: {
! 1705: int d,i,w;
! 1706: UP2 t;
! 1707:
! 1708: d = degup2(f);
! 1709: w = f->w;
! 1710: NEWUP2(t,w);
! 1711: _bshiftup2(f,1,t);
! 1712: for ( i = 0; i < d; i++ )
! 1713: if ( i%2 )
! 1714: t->b[i/BSH] &= ~(1<<(i%BSH));
! 1715: for ( i = w-1; i >= 0 && !t->b[i]; i-- );
! 1716: if ( i < 0 )
! 1717: *r = 0;
! 1718: else {
! 1719: *r = t;
! 1720: t->w = i+1;
! 1721: }
! 1722: }
! 1723:
! 1724: int sqfrcheckup2(f)
! 1725: UP2 f;
! 1726: {
! 1727: UP2 df,g;
! 1728:
! 1729: diffup2(f,&df);
! 1730: gcdup2(f,df,&g);
! 1731: if ( degup2(g) >= 1 )
! 1732: return 0;
! 1733: else
! 1734: return 1;
! 1735: }
! 1736:
! 1737: int irredcheckup2(f)
! 1738: UP2 f;
! 1739: {
! 1740: int n,w,i,j,k,hcol;
! 1741: unsigned int hbit;
! 1742: unsigned int *u;
! 1743: unsigned int **mat;
! 1744: UP2 p,t;
! 1745:
! 1746: if ( !sqfrcheckup2(f) )
! 1747: return 0;
! 1748: n = degup2(f);
! 1749: w = n/BSH + (n%BSH?1:0);
! 1750: mat = (unsigned int **)almat(n,w);
! 1751: W_NEWUP2(p,w+1);
! 1752: W_NEWUP2(t,w+1);
! 1753: p->w = 1; p->b[0] = 1; /* p = 1 mod f */
! 1754: for ( i = 1; i < n; i++ ) {
! 1755: _bshiftup2(p,-2,t); _remup2(t,f,p);
! 1756: _copy_up2bits(p,mat,i);
! 1757:
! 1758: }
! 1759: /* _print_frobmat(mat,n,w); */
! 1760: for ( j = 1; j < n; j++ ) {
! 1761: hcol = j/BSH; hbit = 1<<(j%BSH);
! 1762: for ( i = j-1; i < n; i++ )
! 1763: if ( mat[i][hcol] & hbit )
! 1764: break;
! 1765: if ( i == n )
! 1766: return 0;
! 1767: if ( i != j-1 ) {
! 1768: u = mat[i]; mat[i] = mat[j-1]; mat[j-1] = u;
! 1769: }
! 1770: for ( i = j; i < n; i++ )
! 1771: if ( mat[i][hcol] & hbit )
! 1772: for ( k = hcol; k < w; k++ )
! 1773: mat[i][k] ^= mat[j-1][k];
! 1774: }
! 1775: return 1;
! 1776: }
! 1777:
! 1778: int irredcheck_dddup2(f)
! 1779: UP2 f;
! 1780: {
! 1781: UP2 x,u,t,s,gcd;
! 1782: int n,i;
! 1783:
! 1784: if ( !sqfrcheckup2(f) )
! 1785: return -1;
! 1786: n = degup2(f);
! 1787:
! 1788: W_NEWUP2(u,1); u->w = 1; u->b[0] = 2; /* u = x mod f */
! 1789: x = u;
! 1790: for ( i = 1; 2*i <= n; i++ ) {
! 1791: squareup2(u,&t); remup2(t,f,&u); addup2(u,x,&s);
! 1792: gcdup2(f,s,&gcd);
! 1793: if ( degup2(gcd) > 0 )
! 1794: return 0;
! 1795: }
! 1796: return 1;
! 1797: }
! 1798:
! 1799: void _copy_up2bits(p,mat,pos)
! 1800: UP2 p;
! 1801: unsigned int **mat;
! 1802: int pos;
! 1803: {
! 1804: int d,col,j,jcol,jsh;
! 1805: unsigned int bit;
! 1806:
! 1807: d = degup2(p);
! 1808: col = pos/BSH; bit = 1<<(pos%BSH);
! 1809:
! 1810: for ( j = 0; j <= d; j++ ) {
! 1811: jcol = j/BSH; jsh = j%BSH;
! 1812: if ( p->b[jcol]&(1<<jsh) )
! 1813: mat[j][col] |= bit;
! 1814: }
! 1815: mat[pos][col] ^= bit;
! 1816: }
! 1817:
! 1818: int compute_multiplication_matrix(p0,mp)
! 1819: P p0;
! 1820: GF2MAT *mp;
! 1821: {
! 1822: UP2 p;
! 1823: int n,w,i,j,k,l;
! 1824: unsigned int **a,**b,**c,**d,**t,**m;
! 1825: GF2MAT am,bm;
! 1826:
! 1827: ptoup2(p0,&p);
! 1828: n = degup2(p);
! 1829: w = p->w;
! 1830: if ( !compute_representation_conversion_matrix(p0,&am,&bm) )
! 1831: return 0;
! 1832: a = am->body; b = bm->body;
! 1833: /* _print_frobmat(a,n,w); printf("\n"); */
! 1834: /* _print_frobmat(b,n,w); printf("\n"); */
! 1835: c = (unsigned int **)almat(n,w);
! 1836: for ( i = 0; i < n-1; i++ ) {
! 1837: j = i+1;
! 1838: c[i][j/BSH] |= 1<<(j%BSH);
! 1839: }
! 1840: bcopy(p->b,c[n-1],p->w*sizeof(unsigned int));
! 1841:
! 1842: /* _print_frobmat(b,n,w); printf("\n"); */
! 1843: t = (unsigned int **)almat(n,w);
! 1844: mulgf2mat(n,a,c,t);
! 1845: d = (unsigned int **)almat(n,w);
! 1846: mulgf2mat(n,t,b,d);
! 1847: /* _print_frobmat(d,n,w); printf("\n"); */
! 1848:
! 1849: m = (unsigned int **)almat(n,w);
! 1850: for ( i = 0; i < n; i++ )
! 1851: for ( j = 0; j < n; j++ ) {
! 1852: k = (n-1-(j-i))%n; l = (n-1+i)%n;
! 1853: if ( d[k][l/BSH] & 1<<(l%BSH) )
! 1854: m[n-1-i][(n-1-j)/BSH] |= 1<<((n-1-j)%BSH);
! 1855: }
! 1856: /* _print_frobmat(m,n,w); printf("\n"); */
! 1857: TOGF2MAT(n,n,m,*mp);
! 1858: return 1;
! 1859: }
! 1860:
! 1861: #define GF2N_PBTOPB 0
! 1862: #define GF2N_NBTOPB 1
! 1863:
! 1864: void compute_change_of_basis_matrix_with_root(P,P,int,GF2N,GF2MAT *,GF2MAT *);
! 1865:
! 1866: /*
! 1867: * if 'to' = GF2N_NBTOPB then p0 must be a normal poly.
! 1868: * rep0 x m01 -> rep1, rep1 x m10 -> rep0
! 1869: */
! 1870:
! 1871: void compute_change_of_basis_matrix(p0,p1,to,m01,m10)
! 1872: P p0,p1;
! 1873: int to;
! 1874: GF2MAT *m01,*m10;
! 1875: {
! 1876: UP2 up0;
! 1877: int n,w;
! 1878: unsigned int **p01,**p10;
! 1879: GF2N root;
! 1880:
! 1881: setmod_gf2n(p1);
! 1882:
! 1883: ptoup2(p0,&up0);
! 1884: n = degup2(up0); w = up0->w;
! 1885: find_root_up2(up0,&root);
! 1886: compute_change_of_basis_matrix_with_root(p0,p1,to,root,m01,m10);
! 1887: }
! 1888:
! 1889: void compute_change_of_basis_matrix_with_root(p0,p1,to,root,m01,m10)
! 1890: P p0,p1;
! 1891: int to;
! 1892: GF2N root;
! 1893: GF2MAT *m01,*m10;
! 1894: {
! 1895: UP2 up0,t,u,s;
! 1896: int n,w,i;
! 1897: unsigned int **a,**b,**g,**h;
! 1898: unsigned int **p01,**p10;
! 1899: P tmp;
! 1900:
! 1901: setmod_gf2n(p1);
! 1902:
! 1903: ptoup2(p0,&up0);
! 1904: n = degup2(up0); w = up0->w;
! 1905: substp(CO,p0,p0->v,(P)root,&tmp);
! 1906: if ( tmp )
! 1907: error("error in find_root_up2");
! 1908: u = root->body;
! 1909:
! 1910: p01 = (unsigned int **)almat(n,w);
! 1911: p10 = (unsigned int **)almat(n,w);
! 1912: if ( to == GF2N_PBTOPB ) {
! 1913: t = ONEUP2;
! 1914: bcopy(t->b,p01[0],t->w*sizeof(unsigned int));
! 1915: for ( i = 1; i < n; i++ ) {
! 1916: mulup2(t,u,&s); gen_simpup2_destructive(s,current_mod_gf2n); t = s;
! 1917: bcopy(t->b,p01[i],t->w*sizeof(unsigned int));
! 1918: }
! 1919: } else {
! 1920: t = u;
! 1921: bcopy(t->b,p01[n-1],t->w*sizeof(unsigned int));
! 1922: for ( i = 1; i < n; i++ ) {
! 1923: squareup2(t,&s); gen_simpup2_destructive(s,current_mod_gf2n); t = s;
! 1924: bcopy(t->b,p01[n-1-i],t->w*sizeof(unsigned int));
! 1925: }
! 1926: }
! 1927: if ( !invgf2mat(n,p01,p10) )
! 1928: error("compute_change_of_basis_matrix : something is wrong");
! 1929: TOGF2MAT(n,n,p01,*m01);
! 1930: TOGF2MAT(n,n,p10,*m10);
! 1931: }
! 1932:
! 1933: /*
! 1934: *
! 1935: * computation of representation conversion matrix
! 1936: * repn x np -> repp, repp x pn -> repn
! 1937: *
! 1938: */
! 1939:
! 1940: int compute_representation_conversion_matrix(p0,np,pn)
! 1941: P p0;
! 1942: GF2MAT *np,*pn;
! 1943: {
! 1944: UP2 x,s;
! 1945: int n,w,i;
! 1946: unsigned int **ntop,**pton;
! 1947:
! 1948: setmod_gf2n(p0);
! 1949:
! 1950: n = UDEG(p0); w = n/BSH + (n%BSH?1:0);
! 1951:
! 1952: /* x = alpha */
! 1953: NEWUP2(x,1); x->w = 1; x->b[0]=2;
! 1954: gen_simpup2_destructive(x,current_mod_gf2n);
! 1955:
! 1956: ntop = (unsigned int **)almat(n,w);
! 1957: pton = (unsigned int **)almat(n,w);
! 1958:
! 1959: bcopy(x->b,ntop[n-1],x->w*sizeof(unsigned int));
! 1960: for ( i = 1; i < n; i++ ) {
! 1961: squareup2(x,&s); gen_simpup2_destructive(s,current_mod_gf2n); x = s;
! 1962: bcopy(x->b,ntop[n-1-i],x->w*sizeof(unsigned int));
! 1963: }
! 1964: if ( !invgf2mat(n,ntop,pton) )
! 1965: return 0;
! 1966: TOGF2MAT(n,n,ntop,*np);
! 1967: TOGF2MAT(n,n,pton,*pn);
! 1968: return 1;
! 1969: }
! 1970:
! 1971: void mul_nb(mat,a,b,c)
! 1972: GF2MAT mat;
! 1973: unsigned int *a,*b,*c;
! 1974: {
! 1975: int n,w,i;
! 1976: unsigned int *wa,*wb,*t;
! 1977: unsigned int **m;
! 1978:
! 1979: n = mat->row;
! 1980: m = mat->body;
! 1981: w = n/BSH + (n%BSH?1:0);
! 1982: wa = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
! 1983: wb = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
! 1984: t = (unsigned int *)ALLOCA(w*sizeof(unsigned int));
! 1985: bcopy(a,wa,w*sizeof(unsigned int));
! 1986: bcopy(b,wb,w*sizeof(unsigned int));
! 1987: bzero((char *)c,w*sizeof(unsigned int));
! 1988: for ( i = n-1; i >= 0; i-- ) {
! 1989: mulgf2vectmat(n,wa,m,t);
! 1990: if ( mulgf2vectvect(n,t,wb) )
! 1991: c[i/BSH] |= 1<<(i%BSH);
! 1992: leftshift(wa,n);
! 1993: leftshift(wb,n);
! 1994: }
! 1995: }
! 1996:
! 1997:
! 1998: /*
! 1999: a=(c0,c1,...,c{n-1})->(c1,c2,...,c{n-1},c0)
! 2000: */
! 2001:
! 2002: void leftshift(a,n)
! 2003: unsigned int *a;
! 2004: int n;
! 2005: {
! 2006: int r,w,i;
! 2007: unsigned int msb;
! 2008:
! 2009: r = n%BSH;
! 2010: w = n/BSH + (r?1:0);
! 2011: msb = a[(n-1)/BSH]&(1<<((n-1)%BSH));
! 2012: for ( i = w-1; i > 0; i-- )
! 2013: a[i] = (a[i]<<1)|(a[i-1]>>(BSH-1));
! 2014: a[0] = (a[0]<<1)|(msb?1:0);
! 2015: if ( r )
! 2016: a[w-1] &= (1<<r)-1;
! 2017: }
! 2018:
! 2019: void mat_to_gf2mat(a,b)
! 2020: MAT a;
! 2021: unsigned int ***b;
! 2022: {
! 2023: int n,w,i,j;
! 2024: unsigned int **m;
! 2025:
! 2026: n = a->row;
! 2027: w = n/BSH + (n%BSH?1:0);
! 2028: *b = m = (unsigned int **)almat(n,w);
! 2029: for ( i = 0; i < n; i++ )
! 2030: for ( j = 0; j < n; j++ )
! 2031: if ( a->body[i][j] )
! 2032: m[i][j/BSH] |= 1<<(j%BSH);
! 2033: }
! 2034:
! 2035: void gf2mat_to_mat(a,n,b)
! 2036: unsigned int **a;
! 2037: MAT *b;
! 2038: {
! 2039: int w,i,j;
! 2040: MAT m;
! 2041:
! 2042: MKMAT(m,n,n); *b = m;
! 2043: w = n/BSH + (n%BSH?1:0);
! 2044: for ( i = 0; i < n; i++ )
! 2045: for ( j = 0; j < n; j++ )
! 2046: if ( a[i][j/BSH] & 1<<(j%BSH) )
! 2047: m->body[i][j] = (pointer)ONE;
! 2048: }
! 2049:
! 2050: void mulgf2mat(n,a,b,c)
! 2051: int n;
! 2052: unsigned int **a,**b,**c;
! 2053: {
! 2054: int i,j,k,w;
! 2055:
! 2056: w = n/BSH + (n%BSH?1:0);
! 2057: for ( i = 0; i < n; i++ ) {
! 2058: bzero((char *)c[i],w*sizeof(unsigned int));
! 2059: for ( j = 0; j < n; j++ )
! 2060: if ( a[i][j/BSH] & 1<<(j%BSH) )
! 2061: for ( k = 0; k < w; k++ )
! 2062: c[i][k] ^= b[j][k];
! 2063: }
! 2064: }
! 2065:
! 2066: /* c = a*b; where a, c are row vectors */
! 2067:
! 2068: void mulgf2vectmat(n,a,b,c)
! 2069: int n;
! 2070: unsigned int *a;
! 2071: unsigned int **b;
! 2072: unsigned int *c;
! 2073: {
! 2074: int j,k,w;
! 2075:
! 2076: w = n/BSH + (n%BSH?1:0);
! 2077: bzero((char *)c,w*sizeof(unsigned int));
! 2078: for ( j = 0; j < n; j++ )
! 2079: if ( a[j/BSH] & 1<<(j%BSH) )
! 2080: for ( k = 0; k < w; k++ )
! 2081: c[k] ^= b[j][k];
! 2082: }
! 2083:
! 2084: int mulgf2vectvect(n,a,b)
! 2085: int n;
! 2086: unsigned int *a,*b;
! 2087: {
! 2088: unsigned int t,r;
! 2089: int i,w;
! 2090:
! 2091: w = n/BSH + (n%BSH?1:0);
! 2092: for ( i = 0, r = 0; i < w; i++ )
! 2093: for ( t = a[i]&b[i]; t; t >>=1 )
! 2094: r ^= (t&1);
! 2095: return r;
! 2096: }
! 2097:
! 2098: int invgf2mat(n,a,b)
! 2099: int n;
! 2100: unsigned int **a,**b;
! 2101: {
! 2102: int i,j,k,hcol,hbit,w;
! 2103: unsigned int *u;
! 2104: unsigned int **s;
! 2105:
! 2106: w = n/BSH + (n%BSH?1:0);
! 2107: s = (unsigned int **)almat(n,w);
! 2108: for ( i = 0; i < n; i++ )
! 2109: bcopy(a[i],s[i],w*sizeof(unsigned int));
! 2110:
! 2111: for ( i = 0; i < n; i++ )
! 2112: b[i][i/BSH] |= 1<<(i%BSH);
! 2113:
! 2114: for ( j = 0; j < n; j++ ) {
! 2115: hcol = j/BSH; hbit = 1<<(j%BSH);
! 2116: for ( i = j; i < n; i++ )
! 2117: if ( s[i][hcol] & hbit )
! 2118: break;
! 2119: if ( i == n )
! 2120: return 0;
! 2121: if ( i != j ) {
! 2122: u = s[i]; s[i] = s[j]; s[j] = u;
! 2123: u = b[i]; b[i] = b[j]; b[j] = u;
! 2124: }
! 2125: for ( i = 0; i < n; i++ ) {
! 2126: if ( i == j )
! 2127: continue;
! 2128: if ( s[i][hcol] & hbit ) {
! 2129: for ( k = hcol; k < w; k++ )
! 2130: s[i][k] ^= s[j][k];
! 2131: for ( k = 0; k < w; k++ )
! 2132: b[i][k] ^= b[j][k];
! 2133: }
! 2134: }
! 2135: }
! 2136: return 1;
! 2137: }
! 2138:
! 2139: INLINE void _mulup2_11(a1,a2,ar)
! 2140: unsigned int a1,a2;
! 2141: unsigned int *ar;
! 2142: {
! 2143: GF2M_MUL_1(ar[1],ar[0],a1,a2);
! 2144: }
! 2145:
! 2146: void _mulup2_22(a1,a2,ar)
! 2147: unsigned int *a1,*a2,*ar;
! 2148: {
! 2149: unsigned int m[2];
! 2150:
! 2151: _mulup2_11(*a1,*a2,ar);
! 2152: _mulup2_11(*(a1+1),*(a2+1),ar+2);
! 2153: _mulup2_11(a1[0]^a1[1],a2[0]^a2[1],m);
! 2154: m[0] ^= ar[0]^ar[2]; m[1] ^= ar[1]^ar[3];
! 2155:
! 2156: ar[1] ^= m[0]; ar[2] ^= m[1];
! 2157: }
! 2158:
! 2159: #if 0
! 2160: void _mulup2_33(a1,a2,ar)
! 2161: unsigned int *a1,*a2,*ar;
! 2162: {
! 2163: unsigned int m[4];
! 2164: unsigned int c1[2],c2[2];
! 2165:
! 2166: c1[0] = a1[2]^a1[0]; c1[1] = a1[1];
! 2167: c2[0] = a2[2]^a2[0]; c2[1] = a2[1];
! 2168:
! 2169: _mulup2_22(a1,a2,ar);
! 2170: _mulup2_11(*(a1+2),*(a2+2),ar+4);
! 2171: _mulup2_22(c1,c2,m);
! 2172:
! 2173: m[0] ^= ar[0]^ar[4]; m[1] ^= ar[1]^ar[5];
! 2174: m[2] ^= ar[2]; m[3] ^= ar[3];
! 2175:
! 2176: ar[2] ^= m[0]; ar[3] ^= m[1]; ar[4] ^= m[2]; ar[5] ^= m[3];
! 2177: }
! 2178: #else
! 2179: /* (ar[5]...ar[0]) = (a1[2]a1[1]a1[0])*(a2[2]a2[1]a2[0]) */
! 2180:
! 2181: void _mulup2_33(a1,a2,ar)
! 2182: unsigned int *a1,*a2,*ar;
! 2183: {
! 2184: unsigned int m[4];
! 2185: unsigned int c[2];
! 2186: unsigned int t,s;
! 2187:
! 2188: /* (ar[1],ar[0]) = a1[0]*a2[0] */
! 2189: _mulup2_11(a1[0],a2[0],ar);
! 2190:
! 2191: /* (ar[3],ar[2]) = hi(m) = a1[1]*a1[1] */
! 2192: _mulup2_11(a1[1],a2[1],ar+2); m[2] = ar[2]; m[3] = ar[3];
! 2193:
! 2194: /* (ar[5],ar[4]) = a1[2]*a2[2] */
! 2195: _mulup2_11(a1[2],a2[2],ar+4);
! 2196:
! 2197: /*
! 2198: * (ar[3],ar[2],ar[1],ar[0]) = (a1[1],a1[0])*(a2[1],a2[0])
! 2199: * a1[1]*a2[1] is already in (ar[3],ar[2])
! 2200: */
! 2201: /* c = (a1[1]+a1[0])*(a2[1]+a2[0]) */
! 2202: t = a1[1]^a1[0]; s = a2[1]^a2[0]; _mulup2_11(t,s,c);
! 2203: /* c += (ar[1],ar[0])+(ar[3],ar[2]) */
! 2204: c[0] ^= ar[2]^ar[0]; c[1] ^= ar[3]^ar[1];
! 2205: /* (ar[2],ar[1]) += c */
! 2206: ar[1] ^= c[0]; ar[2] ^= c[1];
! 2207:
! 2208: /*
! 2209: * m = (a1[1],a1[2]+a1[0])*(a2[1],a2[2]+a2[0])
! 2210: * a1[1]*a2[1] is already in hi(m)
! 2211: *
! 2212: */
! 2213: /* low(m) = (a1[0]+a1[2])*(a2[0]+a2[2]) */
! 2214: t = a1[2]^a1[0]; s = a2[2]^a2[0]; _mulup2_11(t,s,m);
! 2215: /* c = (a1[1]+(a1[0]+a1[2]))*(a2[1]+(a2[0]+a2[2])) */
! 2216: t ^= a1[1]; s ^= a2[1]; _mulup2_11(t,s,c);
! 2217: /* c += low(m)+hi(m) */
! 2218: c[0] ^= m[2]^m[0]; c[1] ^= m[3]^m[1];
! 2219: /* mid(m) += c */
! 2220: m[1] ^= c[0]; m[2] ^= c[1];
! 2221:
! 2222: /* m += (ar[3],ar[2],ar[1],ar[0])+(ar[5],ar[4]) */
! 2223: m[0] ^= ar[0]^ar[4]; m[1] ^= ar[1]^ar[5];
! 2224: m[2] ^= ar[2]; m[3] ^= ar[3];
! 2225:
! 2226: /* (ar[5],ar[4],ar[3],ar[2]) += m */
! 2227: ar[2] ^= m[0]; ar[3] ^= m[1]; ar[4] ^= m[2]; ar[5] ^= m[3];
! 2228: }
! 2229: #endif
! 2230:
! 2231: void _mulup2_44(a1,a2,ar)
! 2232: unsigned int *a1,*a2,*ar;
! 2233: {
! 2234: unsigned int m[4];
! 2235: unsigned int c1[2],c2[2];
! 2236:
! 2237: c1[0] = a1[2]^a1[0]; c1[1] = a1[3]^a1[1];
! 2238: c2[0] = a2[2]^a2[0]; c2[1] = a2[3]^a2[1];
! 2239:
! 2240: _mulup2_22(a1,a2,ar);
! 2241: _mulup2_22(a1+2,a2+2,ar+4);
! 2242: _mulup2_22(c1,c2,m);
! 2243:
! 2244: m[0] ^= ar[0]^ar[4]; m[1] ^= ar[1]^ar[5];
! 2245: m[2] ^= ar[2]^ar[6]; m[3] ^= ar[3]^ar[7];
! 2246:
! 2247: ar[2] ^= m[0]; ar[3] ^= m[1]; ar[4] ^= m[2]; ar[5] ^= m[3];
! 2248: }
! 2249:
! 2250: void _mulup2_55(a1,a2,ar)
! 2251: unsigned int *a1,*a2,*ar;
! 2252: {
! 2253: unsigned int m[6];
! 2254: unsigned int c1[3],c2[3];
! 2255:
! 2256: c1[0]=a1[3]^a1[0]; c1[1]=a1[4]^a1[1]; c1[2]=a1[2];
! 2257: c2[0]=a2[3]^a2[0]; c2[1]=a2[4]^a2[1]; c2[2]=a2[2];
! 2258:
! 2259: _mulup2_33(a1,a2,ar);
! 2260: _mulup2_22(a1+3,a2+3,ar+6);
! 2261: _mulup2_33(c1,c2,m);
! 2262:
! 2263: m[0] ^= ar[0]^ar[6]; m[1] ^= ar[1]^ar[7]; m[2] ^= ar[2]^ar[8];
! 2264: m[3] ^= ar[3]^ar[9]; m[4] ^= ar[4]; m[5] ^= ar[5];
! 2265:
! 2266: ar[3] ^= m[0]; ar[4] ^= m[1]; ar[5] ^= m[2];
! 2267: ar[6] ^= m[3]; ar[7] ^= m[4]; ar[8] ^= m[5];
! 2268: }
! 2269:
! 2270: void _mulup2_66(a1,a2,ar)
! 2271: unsigned int *a1,*a2,*ar;
! 2272: {
! 2273: unsigned int m[6];
! 2274: unsigned int c1[3],c2[3];
! 2275:
! 2276: c1[0]=a1[3]^a1[0]; c1[1]=a1[4]^a1[1]; c1[2]=a1[5]^a1[2];
! 2277: c2[0]=a2[3]^a2[0]; c2[1]=a2[4]^a2[1]; c2[2]=a2[5]^a2[2];
! 2278:
! 2279: _mulup2_33(a1,a2,ar);
! 2280: _mulup2_33(a1+3,a2+3,ar+6);
! 2281: _mulup2_33(c1,c2,m);
! 2282:
! 2283: m[0] ^= ar[0]^ar[6]; m[1] ^= ar[1]^ar[7]; m[2] ^= ar[2]^ar[8];
! 2284: m[3] ^= ar[3]^ar[9]; m[4] ^= ar[4]^ar[10]; m[5] ^= ar[5]^ar[11];
! 2285:
! 2286: ar[3] ^= m[0]; ar[4] ^= m[1]; ar[5] ^= m[2];
! 2287: ar[6] ^= m[3]; ar[7] ^= m[4]; ar[8] ^= m[5];
! 2288: }
! 2289:
! 2290: #if 0
! 2291: void printup2_(f,l)
! 2292: unsigned int *f;
! 2293: int l;
! 2294: {
! 2295: int i;
! 2296:
! 2297: for ( i = 32*l-1; i >= 0; i-- ) {
! 2298: if ( f[i>>5]&(1<<(i&31)) )
! 2299: fprintf(stderr,"+x^%d",i);
! 2300: }
! 2301: fprintf(stderr,"\n");
! 2302: }
! 2303: #endif
! 2304:
! 2305: void type1_bin_invup2(a,n,inv)
! 2306: UP2 a;
! 2307: int n;
! 2308: UP2 *inv;
! 2309: {
! 2310: int lf,lg,i,j,k,lg2,df,dg,l,w;
! 2311: unsigned int r;
! 2312: UP2 wf,wg,wb,wc,ret,t;
! 2313: unsigned int *p;
! 2314:
! 2315: lf = a->w;
! 2316: lg = (n>>5)+1;
! 2317:
! 2318: W_NEWUP2(wf,lf+1); _copyup2(a,wf);
! 2319: W_NEWUP2(wg,lg+1); wg->w = lg;
! 2320: for ( i = lg-1, p = wg->b; i>=0; i-- )
! 2321: p[i] = 0xffffffff;
! 2322: if ( r = (n+1)&31 )
! 2323: p[lg-1] &= (1<<r)-1;
! 2324: lg2 = lg*2;
! 2325: W_NEWUP2(wb,lg2+2); wb->w = 1; wb->b[0] = 1;
! 2326: W_NEWUP2(wc,lg2+2); wc->w = 0;
! 2327: k = 0;
! 2328: df = degup2(wf); dg = degup2(wg);
! 2329: while ( 1 ) {
! 2330: lf = wf->w;
! 2331: p = wf->b;
! 2332: for ( j = 0; j < lf && !p[j]; j++ );
! 2333: for ( l = j<<5, w = p[j]; !(w&1); w >>=1, l++ );
! 2334: _bshiftup2_destructive(wf,l);
! 2335: _bshiftup2_destructive(wc,-l);
! 2336: k += l;
! 2337: df -= l;
! 2338: if ( wf->w == 1 && wf->b[0] == 1 ) {
! 2339: k %= (n+1);
! 2340: if ( k != 1 ) {
! 2341: _bshiftup2_destructive(wb,k-(n+1));
! 2342: remup2_type1_destructive(wb,n);
! 2343: }
! 2344: NEWUP2(ret,wb->w);
! 2345: _copyup2(wb,ret);
! 2346: *inv = ret;
! 2347: return;
! 2348: }
! 2349: if ( df < dg ) {
! 2350: i = df; df = dg; dg = i;
! 2351: t = wf; wf = wg; wg = t;
! 2352: t = wb; wb = wc; wc = t;
! 2353: }
! 2354: /* df >= dg */
! 2355: _addup2_destructive(wf,wg);
! 2356: df = degup2(wf);
! 2357: _addup2_destructive(wb,wc);
! 2358: }
! 2359: }
! 2360:
! 2361: UP2 *compute_tab_gf2n(f)
! 2362: UP2 f;
! 2363: {
! 2364: GEN_UP2 mod;
! 2365: int m,n,w,i;
! 2366: UP2 t;
! 2367: UP2 *tab;
! 2368:
! 2369: mod = current_mod_gf2n;
! 2370: m = degup2(mod->dense);
! 2371: n = degup2(f);
! 2372: w = f->w;
! 2373: tab = (UP2 *)CALLOC(m,sizeof(UP2));
! 2374: NEWUP2(tab[0],w); tab[0]->w = 1; tab[0]->b[0] = 2;
! 2375: for ( i = 1; i < m; i++ ) {
! 2376: squareup2(tab[i-1],&t); remup2(t,f,&tab[i]);
! 2377: }
! 2378: return tab;
! 2379: }
! 2380:
! 2381: UP compute_trace_gf2n(tab,c,n)
! 2382: UP2 *tab;
! 2383: GF2N c;
! 2384: int n;
! 2385: {
! 2386: GEN_UP2 mod;
! 2387: int w,m,i,j;
! 2388: UP2 *trace;
! 2389: UP2 c1,c2,s,t;
! 2390: UP r;
! 2391: GF2N a;
! 2392:
! 2393: mod = current_mod_gf2n;
! 2394: w = mod->dense->w;
! 2395: m = degup2(mod->dense);
! 2396: trace = (UP2 *)ALLOCA(n*sizeof(UP2));
! 2397: for ( i = 0; i < n; i++ ) {
! 2398: W_NEWUP2(trace[i],w); trace[i]->w = 0;
! 2399: }
! 2400: W_NEWUP2(c1,2*w); _copyup2(c->body,c1);
! 2401: W_NEWUP2(c2,2*w);
! 2402:
! 2403: for ( i = 0; i < m; i++ ) {
! 2404: t = tab[i];
! 2405: /* trace += c^(2^i)*tab[i] */
! 2406: for ( j = degup2(t); j >= 0; j-- )
! 2407: if ( t->b[j/BSH] & (1<<(j%BSH)) )
! 2408: _addup2_destructive(trace[j],c1);
! 2409: _squareup2(c1,c2); gen_simpup2_destructive(c2,mod);
! 2410: t = c1; c1 = c2; c2 = t;
! 2411: }
! 2412: for ( i = n-1; i >= 0 && !trace[i]->w; i-- );
! 2413: if ( i < 0 )
! 2414: r = 0;
! 2415: else {
! 2416: r = UPALLOC(i); r->d = i;
! 2417: for ( j = 0; j <= i; j++ )
! 2418: if ( t = trace[j] ) {
! 2419: NEWUP2(s,t->w); _copyup2(t,s);
! 2420: MKGF2N(s,a); r->c[j] = (Num)a;
! 2421: }
! 2422: }
! 2423: return r;
! 2424: }
! 2425:
! 2426: void up2toup(f,r)
! 2427: UP2 f;
! 2428: UP *r;
! 2429: {
! 2430: int d,i;
! 2431: UP2 c;
! 2432: UP t;
! 2433: GF2N a;
! 2434:
! 2435: if ( !f || !f->w )
! 2436: *r = 0;
! 2437: else {
! 2438: d = degup2(f);
! 2439: t = UPALLOC(d); *r = t;
! 2440: t->d = d;
! 2441: for ( i = 0; i <= d; i++ ) {
! 2442: if ( f->b[i/BSH] & (1<<(i%BSH)) ) {
! 2443: NEWUP2(c,1);
! 2444: c->w = 1; c->b[0] = 1;
! 2445: MKGF2N(c,a);
! 2446: t->c[i] = (Num)a;
! 2447: }
! 2448: }
! 2449: }
! 2450: }
! 2451:
! 2452: void find_root_up2(f,r)
! 2453: UP2 f;
! 2454: GF2N *r;
! 2455: {
! 2456: int n;
! 2457: UP2 *tab;
! 2458: UP uf,trace,gcd,quo,rem;
! 2459: GF2N c;
! 2460: int i;
! 2461:
! 2462: /* computeation of tab : tab[i] = t^(2^i) mod f (i=0,...,n-1) */
! 2463: n = degup2(f);
! 2464: tab = compute_tab_gf2n(f);
! 2465: up2toup(f,&uf);
! 2466: while ( uf->d > 1 ) {
! 2467: randomgf2n(&c);
! 2468: if ( !c )
! 2469: continue;
! 2470: /* trace = (ct)+(ct)^2+...+(ct)^(2^(n-1)) */
! 2471: trace = compute_trace_gf2n(tab,c,n);
! 2472: gcdup(trace,uf,&gcd);
! 2473: if ( gcd->d > 0 && gcd->d < uf->d ) {
! 2474: /* fprintf(stderr,"deg(GCD)=%d\n",gcd->d); */
! 2475: if ( 2*gcd->d > uf->d ) {
! 2476: qrup(uf,gcd,&quo,&rem);
! 2477: uf = quo;
! 2478: } else {
! 2479: uf = gcd;
! 2480: }
! 2481: }
! 2482: }
! 2483: /* now deg(uf) = 1. The root of uf is ug->c[0]/uf->c[1] */
! 2484: divgf2n((GF2N)uf->c[0],(GF2N)uf->c[1],r);
! 2485: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>