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