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