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