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