[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.6

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>