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