[BACK]Return to up2.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / asir2000 / engine

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>