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

Annotation of OpenXM_contrib2/asir2000/engine/up.c, Revision 1.1.1.1

1.1       noro        1: /* $OpenXM: OpenXM/src/asir99/engine/up.c,v 1.1.1.1 1999/11/10 08:12:26 noro Exp $ */
                      2: #include "ca.h"
                      3: #include <math.h>
                      4:
                      5: struct oEGT eg_chrem,eg_fore,eg_back;
                      6:
                      7: /*
                      8: int up_kara_mag=15;
                      9: int up_tkara_mag=15;
                     10: */
                     11: /*
                     12: int up_kara_mag=30;
                     13: int up_tkara_mag=20;
                     14: */
                     15: int up_kara_mag=20;
                     16: int up_tkara_mag=15;
                     17:
                     18: #if defined(sparc)
                     19: int up_fft_mag=50;
                     20: #else
                     21: int up_fft_mag=80;
                     22: #endif
                     23:
                     24: int up_rem_mag=1;
                     25: int debug_up;
                     26: int up_lazy;
                     27: extern int lm_lazy;
                     28: extern int current_ff;
                     29: extern int GC_dont_gc;
                     30:
                     31: void monicup(a,b)
                     32: UP a;
                     33: UP *b;
                     34: {
                     35:        UP w;
                     36:
                     37:        if ( !a )
                     38:                *b = 0;
                     39:        else {
                     40:                w = W_UPALLOC(0); w->d = 0;
                     41:                divnum(0,(Num)ONE,(Num)a->c[a->d],(Num *)&w->c[0]);
                     42:                mulup(a,w,b);
                     43:        }
                     44: }
                     45:
                     46: void simpup(a,b)
                     47: UP a;
                     48: UP *b;
                     49: {
                     50:        int i,d;
                     51:        UP c;
                     52:
                     53:        if ( !a )
                     54:                *b = 0;
                     55:        else {
                     56:                d = a->d;
                     57:                c = UPALLOC(d);
                     58:
                     59:                for ( i = 0; i <= d; i++ )
                     60:                        simpnum(a->c[i],&c->c[i]);
                     61:                for ( i = d; i >= 0 && !c->c[i]; i-- );
                     62:                if ( i < 0 )
                     63:                        *b = 0;
                     64:                else {
                     65:                        c->d = i;
                     66:                        *b = c;
                     67:                }
                     68:        }
                     69: }
                     70:
                     71: void simpnum(a,b)
                     72: Num a;
                     73: Num *b;
                     74: {
                     75:        LM lm;
                     76:        GF2N gf;
                     77:        GFPN gfpn;
                     78:
                     79:        if ( !a )
                     80:                *b = 0;
                     81:        else
                     82:                switch ( NID(a) ) {
                     83:                        case N_LM:
                     84:                                simplm((LM)a,&lm); *b = (Num)lm; break;
                     85:                        case N_GF2N:
                     86:                                simpgf2n((GF2N)a,&gf); *b = (Num)gf; break;
                     87:                        case N_GFPN:
                     88:                                simpgfpn((GFPN)a,&gfpn); *b = (Num)gfpn; break;
                     89:                        default:
                     90:                                *b = a; break;
                     91:                }
                     92: }
                     93:
                     94: void uremp(p1,p2,rp)
                     95: P p1,p2;
                     96: P *rp;
                     97: {
                     98:        UP n1,n2,r;
                     99:
                    100:        if ( !p1 || NUM(p1) )
                    101:                *rp = p1;
                    102:        else {
                    103:                ptoup(p1,&n1); ptoup(p2,&n2);
                    104:                remup(n1,n2,&r);
                    105:                uptop(r,rp);
                    106:        }
                    107: }
                    108:
                    109: void ugcdp(p1,p2,rp)
                    110: P p1,p2;
                    111: P *rp;
                    112: {
                    113:        UP n1,n2,r;
                    114:
                    115:        ptoup(p1,&n1); ptoup(p2,&n2);
                    116:        gcdup(n1,n2,&r);
                    117:        uptop(r,rp);
                    118: }
                    119:
                    120: void reversep(p1,d,rp)
                    121: P p1;
                    122: Q d;
                    123: P *rp;
                    124: {
                    125:        UP n1,r;
                    126:
                    127:        if ( !p1 )
                    128:                *rp = 0;
                    129:        else {
                    130:                ptoup(p1,&n1);
                    131:                reverseup(n1,QTOS(d),&r);
                    132:                uptop(r,rp);
                    133:        }
                    134: }
                    135:
                    136: void invmodp(p1,d,rp)
                    137: P p1;
                    138: Q d;
                    139: P *rp;
                    140: {
                    141:        UP n1,r;
                    142:
                    143:        if ( !p1 )
                    144:                error("invmodp : invalid input");
                    145:        else {
                    146:                ptoup(p1,&n1);
                    147:                invmodup(n1,QTOS(d),&r);
                    148:                uptop(r,rp);
                    149:        }
                    150: }
                    151:
                    152: void addup(n1,n2,nr)
                    153: UP n1,n2;
                    154: UP *nr;
                    155: {
                    156:        UP r,t;
                    157:        int i,d1,d2;
                    158:        Num *c,*c1,*c2;
                    159:
                    160:        if ( !n1 ) {
                    161:                *nr = n2;
                    162:        } else if ( !n2 ) {
                    163:                *nr = n1;
                    164:        } else {
                    165:                if ( n2->d > n1->d ) {
                    166:                        t = n1; n1 = n2; n2 = t;
                    167:                }
                    168:                d1 = n1->d; d2 = n2->d;
                    169:                *nr = r = UPALLOC(d1);
                    170:                c1 = n1->c; c2 = n2->c; c = r->c;
                    171:                for ( i = 0; i <= d2; i++ )
                    172:                        addnum(0,*c1++,*c2++,c++);
                    173:                for ( ; i <= d1; i++ )
                    174:                        *c++ = *c1++;
                    175:                for ( i = d1, c = r->c; i >=0 && !c[i]; i-- );
                    176:                if ( i < 0 )
                    177:                        *nr = 0;
                    178:                else
                    179:                        r->d = i;
                    180:        }
                    181: }
                    182:
                    183: void subup(n1,n2,nr)
                    184: UP n1,n2;
                    185: UP *nr;
                    186: {
                    187:        UP r;
                    188:        int i,d1,d2,d;
                    189:        Num *c,*c1,*c2;
                    190:
                    191:        if ( !n1 ) {
                    192:                chsgnup(n2,nr);
                    193:        } else if ( !n2 ) {
                    194:                *nr = n1;
                    195:        } else {
                    196:                d1 = n1->d; d2 = n2->d; d = MAX(d1,d2);
                    197:                *nr = r = UPALLOC(d);
                    198:                c1 = n1->c; c2 = n2->c; c = r->c;
                    199:                if ( d1 >= d2 ) {
                    200:                        for ( i = 0; i <= d2; i++ )
                    201:                                subnum(0,*c1++,*c2++,c++);
                    202:                        for ( ; i <= d1; i++ )
                    203:                                *c++ = *c1++;
                    204:                } else {
                    205:                        for ( i = 0; i <= d1; i++ )
                    206:                                subnum(0,*c1++,*c2++,c++);
                    207:                        for ( ; i <= d2; i++ )
                    208:                                chsgnnum(*c2++,c++);
                    209:                }
                    210:                for ( i = d, c = r->c; i >=0 && !c[i]; i-- );
                    211:                if ( i < 0 )
                    212:                        *nr = 0;
                    213:                else
                    214:                        r->d = i;
                    215:        }
                    216: }
                    217:
                    218: void chsgnup(n1,nr)
                    219: UP n1;
                    220: UP *nr;
                    221: {
                    222:        UP r;
                    223:        int d1,i;
                    224:        Num *c1,*c;
                    225:
                    226:        if ( !n1 ) {
                    227:                *nr = 0;
                    228:        } else {
                    229:                d1 = n1->d;
                    230:                *nr = r = UPALLOC(d1); r->d = d1;
                    231:                c1 = n1->c; c = r->c;
                    232:                for ( i = 0; i <= d1; i++ )
                    233:                        chsgnnum(*c1++,c++);
                    234:        }
                    235: }
                    236:
                    237: void hybrid_mulup(ff,n1,n2,nr)
                    238: int ff;
                    239: UP n1,n2;
                    240: UP *nr;
                    241: {
                    242:        if ( !n1 || !n2 )
                    243:                *nr = 0;
                    244:        else if ( MAX(n1->d,n2->d) < up_fft_mag )
                    245:                kmulup(n1,n2,nr);
                    246:        else
                    247:                switch ( ff ) {
                    248:                        case FF_GFP:
                    249:                                fft_mulup_lm(n1,n2,nr); break;
                    250:                        case FF_GF2N:
                    251:                                kmulup(n1,n2,nr); break;
                    252:                        default:
                    253:                                fft_mulup(n1,n2,nr); break;
                    254:                }
                    255: }
                    256:
                    257: void hybrid_squareup(ff,n1,nr)
                    258: int ff;
                    259: UP n1;
                    260: UP *nr;
                    261: {
                    262:        if ( !n1 )
                    263:                *nr = 0;
                    264:        else if ( n1->d < up_fft_mag )
                    265:                ksquareup(n1,nr);
                    266:        else
                    267:                switch ( ff ) {
                    268:                        case FF_GFP:
                    269:                                fft_squareup_lm(n1,nr); break;
                    270:                        case FF_GF2N:
                    271:                                ksquareup(n1,nr); break;
                    272:                        default:
                    273:                                fft_squareup(n1,nr); break;
                    274:                }
                    275: }
                    276:
                    277: void hybrid_tmulup(ff,n1,n2,d,nr)
                    278: int ff;
                    279: UP n1,n2;
                    280: int d;
                    281: UP *nr;
                    282: {
                    283:        if ( !n1 || !n2 )
                    284:                *nr = 0;
                    285:        else if ( MAX(n1->d,n2->d) < up_fft_mag )
                    286:                tkmulup(n1,n2,d,nr);
                    287:        else
                    288:                switch ( ff ) {
                    289:                        case FF_GFP:
                    290:                                trunc_fft_mulup_lm(n1,n2,d,nr); break;
                    291:                        case FF_GF2N:
                    292:                                tkmulup(n1,n2,d,nr); break;
                    293:                        default:
                    294:                                trunc_fft_mulup(n1,n2,d,nr); break;
                    295:                }
                    296: }
                    297:
                    298: void mulup(n1,n2,nr)
                    299: UP n1,n2;
                    300: UP *nr;
                    301: {
                    302:        UP r;
                    303:        Num *pc1,*pc,*c1,*c2,*c;
                    304:        Num mul,t,s;
                    305:        int i,j,d1,d2;
                    306:
                    307:        if ( !n1 || !n2 )
                    308:                *nr = 0;
                    309:        else {
                    310:                d1 = n1->d; d2 = n2->d;
                    311:                *nr = r = UPALLOC(d1+d2); r->d = d1+d2;
                    312:                c1 = n1->c; c2 = n2->c; c = r->c;
                    313:                lm_lazy = 1;
                    314:                for ( i = 0; i <= d2; i++, c++ )
                    315:                        if ( mul = *c2++ )
                    316:                                for ( j = 0, pc1 = c1, pc = c; j <= d1; j++ ) {
                    317:                                        mulnum(0,*pc1++,mul,&t); addnum(0,*pc,t,&s); *pc++ = s;
                    318:                        }
                    319:                lm_lazy = 0;
                    320:                if ( !up_lazy )
                    321:                        for ( i = 0, c = r->c; i <= r->d; i++ ) {
                    322:                                simpnum(c[i],&t); c[i] = t;
                    323:                        }
                    324:        }
                    325: }
                    326:
                    327: /* nr = c*n1 */
                    328:
                    329: void mulcup(c,n1,nr)
                    330: Num c;
                    331: UP n1;
                    332: UP *nr;
                    333: {
                    334:        int d;
                    335:        UP r;
                    336:        Num t;
                    337:        Num *c1,*cr;
                    338:        int i;
                    339:
                    340:        if ( !c || !n1 )
                    341:                *nr = 0;
                    342:        else {
                    343:                d = n1->d;
                    344:                *nr = r = UPALLOC(d); r->d = d;
                    345:                c1 = n1->c; cr = r->c;
                    346:                lm_lazy = 1;
                    347:                for ( i = 0; i <= d; i++ )
                    348:                        mulnum(0,c1[i],c,&cr[i]);
                    349:                lm_lazy = 0;
                    350:                if ( !up_lazy )
                    351:                        for ( i = 0; i <= d; i++ ) {
                    352:                                simpnum(cr[i],&t); cr[i] = t;
                    353:                        }
                    354:        }
                    355: }
                    356:
                    357: void tmulup(n1,n2,d,nr)
                    358: UP n1,n2;
                    359: int d;
                    360: UP *nr;
                    361: {
                    362:        UP r;
                    363:        Num *pc1,*pc,*c1,*c2,*c;
                    364:        Num mul,t,s;
                    365:        int i,j,d1,d2,dr;
                    366:
                    367:        if ( !n1 || !n2 )
                    368:                *nr = 0;
                    369:        else {
                    370:                d1 = n1->d; d2 = n2->d;
                    371:                dr = MAX(d-1,d1+d2);
                    372:                *nr = r = UPALLOC(dr);
                    373:                c1 = n1->c; c2 = n2->c; c = r->c;
                    374:                lm_lazy = 1;
                    375:                for ( i = 0; i <= d2; i++, c++ )
                    376:                        if ( mul = *c2++ )
                    377:                                for ( j = 0, pc1 = c1, pc = c; (j <= d1) && (i+j < d); j++ ) {
                    378:                                        mulnum(0,*pc1++,mul,&t); addnum(0,*pc,t,&s); *pc++ = s;
                    379:                        }
                    380:                lm_lazy = 0;
                    381:                c = r->c;
                    382:                if ( !up_lazy )
                    383:                        for ( i = 0; i < d; i++ ) {
                    384:                                simpnum(c[i],&t); c[i] = t;
                    385:                        }
                    386:                for ( i = d-1; i >= 0 && !c[i]; i-- );
                    387:                if ( i < 0 )
                    388:                        *nr = 0;
                    389:                else
                    390:                        r->d = i;
                    391:        }
                    392: }
                    393:
                    394: void squareup(n1,nr)
                    395: UP n1;
                    396: UP *nr;
                    397: {
                    398:        UP r;
                    399:        Num *c1,*c;
                    400:        Num t,s,u;
                    401:        int i,j,h,d1,d;
                    402:
                    403:        if ( !n1 )
                    404:                *nr = 0;
                    405:        else if ( !n1->d ) {
                    406:                *nr = r = UPALLOC(0); r->d = 0;
                    407:                mulnum(0,n1->c[0],n1->c[0],&r->c[0]);
                    408:        } else {
                    409:                d1 = n1->d;
                    410:                d = 2*d1;
                    411:                *nr = r = UPALLOC(2*d); r->d = d;
                    412:                c1 = n1->c; c = r->c;
                    413:                lm_lazy = 1;
                    414:                for ( i = 0; i <= d1; i++ )
                    415:                        mulnum(0,c1[i],c1[i],&c[2*i]);
                    416:                for ( j = 1; j < d; j++ ) {
                    417:                        h = (j-1)/2;
                    418:                        for ( i = MAX(j-d1,0), s = 0; i <= h; i++ ) {
                    419:                                mulnum(0,c1[i],c1[j-i],&t); addnum(0,t,s,&u); s = u;
                    420:                        }
                    421:                        addnum(0,s,s,&t); addnum(0,t,c[j],&u); c[j] = u;
                    422:                }
                    423:                lm_lazy = 0;
                    424:                if ( !up_lazy )
                    425:                        for ( i = 0, c = r->c; i <= d; i++ ) {
                    426:                                simpnum(c[i],&t); c[i] = t;
                    427:                        }
                    428:        }
                    429: }
                    430:
                    431: void remup(n1,n2,nr)
                    432: UP n1,n2;
                    433: UP *nr;
                    434: {
                    435:        UP w,r;
                    436:
                    437:        if ( !n2 )
                    438:                error("remup : division by 0");
                    439:        else if ( !n1 || !n2->d )
                    440:                *nr = 0;
                    441:        else if ( n1->d < n2->d )
                    442:                *nr = n1;
                    443:        else {
                    444:                w = W_UPALLOC(n1->d); copyup(n1,w);
                    445:                remup_destructive(w,n2);
                    446:                if ( w->d < 0 )
                    447:                        *nr = 0;
                    448:                else {
                    449:                        *nr = r = UPALLOC(w->d); copyup(w,r);
                    450:                }
                    451:        }
                    452: }
                    453:
                    454: void remup_destructive(n1,n2)
                    455: UP n1,n2;
                    456: {
                    457:        Num *c1,*c2;
                    458:        int d1,d2,i,j;
                    459:        Num m,t,s,mhc;
                    460:
                    461:        c1 = n1->c; c2 = n2->c;
                    462:        d1 = n1->d; d2 = n2->d;
                    463:        chsgnnum(c2[d2],&mhc);
                    464:        for ( i = d1; i >= d2; i-- ) {
                    465:                simpnum(c1[i],&t); c1[i] = t;
                    466:                if ( !c1[i] )
                    467:                        continue;
                    468:                divnum(0,c1[i],mhc,&m);
                    469:                lm_lazy = 1;
                    470:                for ( j = d2; j >= 0; j-- ) {
                    471:                        mulnum(0,c2[j],m,&t); addnum(0,c1[i+j-d2],t,&s);
                    472:                        c1[i+j-d2] = s;
                    473:                }
                    474:                lm_lazy = 0;
                    475:        }
                    476:        for ( i = 0; i < d2; i++ ) {
                    477:                simpnum(c1[i],&t); c1[i] = t;
                    478:        }
                    479:        for ( i = d2-1; i >= 0 && !c1[i]; i-- );
                    480:        n1->d = i;
                    481: }
                    482:
                    483: void qrup(n1,n2,nq,nr)
                    484: UP n1,n2;
                    485: UP *nq,*nr;
                    486: {
                    487:        UP w,r,q;
                    488:        struct oUP t;
                    489:        Num m;
                    490:        int d;
                    491:
                    492:        if ( !n2 )
                    493:                error("qrup : division by 0");
                    494:        else if ( !n1 ) {
                    495:                *nq = 0; *nr = 0;
                    496:        } else if ( !n2->d )
                    497:                if ( !n1->d ) {
                    498:                        divnum(0,n1->c[0],n2->c[0],(Num *)nq); *nr = 0;
                    499:                } else {
                    500:                        divnum(0,(Num)ONE,n2->c[0],&m);
                    501:                        t.d = 0; t.c[0] = m;
                    502:                        mulup(n1,&t,nq); *nr = 0;
                    503:                }
                    504:        else if ( n1->d < n2->d ) {
                    505:                *nq = 0; *nr = n1;
                    506:        } else {
                    507:                w = W_UPALLOC(n1->d); copyup(n1,w);
                    508:                qrup_destructive(w,n2);
                    509:                d = n1->d-n2->d;
                    510:                *nq = q = UPALLOC(d); q->d = d;
                    511:                bcopy(w->c+n2->d,q->c,(d+1)*sizeof(Num));
                    512:                if ( w->d < 0 )
                    513:                        *nr = 0;
                    514:                else {
                    515:                        *nr = r = UPALLOC(w->d); copyup(w,r);
                    516:                }
                    517:        }
                    518: }
                    519:
                    520: void qrup_destructive(n1,n2)
                    521: UP n1,n2;
                    522: {
                    523:        Num *c1,*c2;
                    524:        int d1,d2,i,j;
                    525:        Num q,t,s,hc;
                    526:
                    527:        c1 = n1->c; c2 = n2->c;
                    528:        d1 = n1->d; d2 = n2->d;
                    529:        hc = c2[d2];
                    530:        for ( i = d1; i >= d2; i-- ) {
                    531:                simpnum(c1[i],&t); c1[i] = t;
                    532:                if ( c1[i] ) {
                    533:                        divnum(0,c1[i],hc,&q);
                    534:                        lm_lazy = 1;
                    535:                        for ( j = d2; j >= 0; j-- ) {
                    536:                                mulnum(0,c2[j],q,&t); subnum(0,c1[i+j-d2],t,&s);
                    537:                                c1[i+j-d2] = s;
                    538:                        }
                    539:                        lm_lazy = 0;
                    540:                } else
                    541:                        q = 0;
                    542:                c1[i] = q;
                    543:        }
                    544:        for ( i = 0; i < d2; i++ ) {
                    545:                simpnum(c1[i],&t); c1[i] = t;
                    546:        }
                    547:        for ( i = d2-1; i >= 0 && !c1[i]; i-- );
                    548:        n1->d = i;
                    549: }
                    550:
                    551: void gcdup(n1,n2,nr)
                    552: UP n1,n2;
                    553: UP *nr;
                    554: {
                    555:        UP w1,w2,t,r;
                    556:        int d1,d2;
                    557:
                    558:        if ( !n1 )
                    559:                *nr = n2;
                    560:        else if ( !n2 )
                    561:                *nr = n1;
                    562:        else if ( !n1->d || !n2->d ) {
                    563:                *nr = r = UPALLOC(0); r->d = 0;
                    564:                divnum(0,n1->c[n1->d],n1->c[n1->d],&r->c[0]);
                    565:        } else {
                    566:                d1 = n1->d; d2 = n2->d;
                    567:                if ( d2 > d1 ) {
                    568:                        w1 = W_UPALLOC(d2); copyup(n2,w1);
                    569:                        w2 = W_UPALLOC(d1); copyup(n1,w2);
                    570:                } else {
                    571:                        w1 = W_UPALLOC(d1); copyup(n1,w1);
                    572:                        w2 = W_UPALLOC(d2); copyup(n2,w2);
                    573:                }
                    574:                d1 = w1->d; d2 = w2->d;
                    575:                while ( 1 ) {
                    576:                        remup_destructive(w1,w2);
                    577:                        if ( w1->d < 0 ) {
                    578:                                *nr = r = UPALLOC(w2->d); copyup(w2,r); return;
                    579:                        } else if ( !w1->d ) {
                    580:                                *nr = r = UPALLOC(0); r->d = 0;
                    581:                                divnum(0,n1->c[n1->d],n1->c[n1->d],&r->c[0]); return;
                    582:                        } else {
                    583:                                t = w1; w1 = w2; w2 = t;
                    584:                        }
                    585:                }
                    586:        }
                    587: }
                    588:
                    589: /* compute r s.t. a*r = 1 mod m */
                    590:
                    591: void extended_gcdup(a,m,r)
                    592: UP a,m;
                    593: UP *r;
                    594: {
                    595:        UP one,g1,g2,a1,a2,a3,b1,b2,b3,inv,quo,rem,t;
                    596:        Num i;
                    597:
                    598:        one = UPALLOC(0); one->d = 0; one->c[0] = (Num)ONELM;
                    599:        g1 = m; g2 = a;
                    600:        a1 = one; a2 = 0;
                    601:        b1 = 0; b2 = one;
                    602:        /* a2*m+b2*a = g2 always holds */
                    603:        while ( g2->d ) {
                    604:                qrup(g1,g2,&quo,&rem); g1 = g2; g2 = rem;
                    605:                mulup(a2,quo,&t); subup(a1,t,&a3); a1 = a2; a2 = a3;
                    606:                mulup(b2,quo,&t); subup(b1,t,&b3); b1 = b2; b2 = b3;
                    607:        }
                    608:        /* now a2*m+b2*a = g2 (const) */
                    609:        divnum(0,(Num)ONE,g2->c[0],&i);
                    610:        inv = UPALLOC(0); inv->d = 0; inv->c[0] = i;
                    611:        mulup(b2,inv,r);
                    612: }
                    613:
                    614: void reverseup(n1,d,nr)
                    615: UP n1;
                    616: int d;
                    617: UP *nr;
                    618: {
                    619:        Num *c1,*c;
                    620:        int i,d1;
                    621:        UP r;
                    622:
                    623:        if ( !n1 )
                    624:                *nr = 0;
                    625:        else if ( d < (d1 = n1->d) )
                    626:                error("reverseup : invalid input");
                    627:        else {
                    628:                *nr = r = UPALLOC(d);
                    629:                c = r->c;
                    630:                bzero((char *)c,(d+1)*sizeof(Num));
                    631:                c1 = n1->c;
                    632:                for ( i = 0; i <= d1; i++ )
                    633:                        c[d-i] = c1[i];
                    634:                for ( i = d; i >= 0 && !c[i]; i-- );
                    635:                r->d = i;
                    636:                if ( i < 0 )
                    637:                        *nr = 0;
                    638:        }
                    639: }
                    640:
                    641: void invmodup(n1,d,nr)
                    642: UP n1;
                    643: int d;
                    644: UP *nr;
                    645: {
                    646:        UP r;
                    647:        Num s,t,u,hinv;
                    648:        int i,j,dmin;
                    649:        Num *w,*c,*cr;
                    650:
                    651:        if ( !n1 || !n1->c[0] )
                    652:                error("invmodup : invalid input");
                    653:        else if ( !n1->d ) {
                    654:                *nr = r = UPALLOC(0); r->d = 0;
                    655:                divnum(0,(Num)ONE,n1->c[0],&r->c[0]);
                    656:        } else {
                    657:                *nr = r = UPALLOC(d);
                    658:                w = (Num *)ALLOCA((d+1)*sizeof(Q));
                    659:                bzero((char *)w,(d+1)*sizeof(Q));
                    660:                dmin = MIN(d,n1->d);
                    661:                divnum(0,(Num)ONE,n1->c[0],&hinv);
                    662:                for ( i = 0, c = n1->c; i <= dmin; i++ )
                    663:                        mulnum(0,c[i],hinv,&w[i]);
                    664:                cr = r->c;
                    665:                cr[0] = w[0];
                    666:                for ( i = 1; i <= d; i++ ) {
                    667:                        for ( j = 1, s = w[i]; j < i; j++ ) {
                    668:                                mulnum(0,cr[j],w[i-j],&t);
                    669:                                addnum(0,s,t,&u);
                    670:                                s = u;
                    671:                        }
                    672:                        chsgnnum(s,&cr[i]);
                    673:                }
                    674:                for ( i = 0; i <= d; i++ ) {
                    675:                        mulnum(0,cr[i],hinv,&t); cr[i] = t;
                    676:                }
                    677:                for ( i = d; i >= 0 && !cr[i]; i-- );
                    678:                r->d = i;
                    679:        }
                    680: }
                    681:
                    682: void pwrup(n,e,nr)
                    683: UP n;
                    684: Q e;
                    685: UP *nr;
                    686: {
                    687:        UP y,z,t;
                    688:        N en,qn;
                    689:        int r;
                    690:
                    691:        y = UPALLOC(0); y->d = 0; y->c[0] = (Num)ONE;
                    692:        z = n;
                    693:        if ( !e )
                    694:                *nr = y;
                    695:        else if ( UNIQ(e) )
                    696:                *nr = n;
                    697:        else {
                    698:                en = NM(e);
                    699:                while ( 1 ) {
                    700:                        r = divin(en,2,&qn); en = qn;
                    701:                        if ( r ) {
                    702:                                mulup(z,y,&t); y = t;
                    703:                                if ( !en ) {
                    704:                                        *nr = y;
                    705:                                        return;
                    706:                                }
                    707:                        }
                    708:                        mulup(z,z,&t); z = t;
                    709:                }
                    710:        }
                    711: }
                    712:
                    713: int compup(n1,n2)
                    714: UP n1,n2;
                    715: {
                    716:        int i,r;
                    717:
                    718:        if ( !n1 )
                    719:                return n2 ? -1 : 0;
                    720:        else if ( !n2 )
                    721:                return 1;
                    722:        else if ( n1->d > n2->d )
                    723:                return 1;
                    724:        else if ( n1->d < n2->d )
                    725:                return -1;
                    726:        else {
                    727:                for ( i = n1->d; i >= 0; i-- ) {
                    728:                        r = compnum(CO,n1->c[i],n2->c[i]);
                    729:                        if ( r )
                    730:                                return r;
                    731:                }
                    732:                return 0;
                    733:        }
                    734: }
                    735:
                    736: void kmulp(vl,n1,n2,nr)
                    737: VL vl;
                    738: P n1,n2;
                    739: P *nr;
                    740: {
                    741:        UP b1,b2,br;
                    742:
                    743:        if ( !n1 || !n2 )
                    744:                *nr = 0;
                    745:        else if ( OID(n1) == O_N || OID(n2) == O_N )
                    746:                mulp(vl,n1,n2,nr);
                    747:        else {
                    748:                ptoup(n1,&b1); ptoup(n2,&b2);
                    749:                kmulup(b1,b2,&br);
                    750:                uptop(br,nr);
                    751:        }
                    752: }
                    753:
                    754: void ksquarep(vl,n1,nr)
                    755: VL vl;
                    756: P n1;
                    757: P *nr;
                    758: {
                    759:        UP b1,br;
                    760:
                    761:        if ( !n1 )
                    762:                *nr = 0;
                    763:        else if ( OID(n1) == O_N )
                    764:                mulp(vl,n1,n1,nr);
                    765:        else {
                    766:                ptoup(n1,&b1);
                    767:                ksquareup(b1,&br);
                    768:                uptop(br,nr);
                    769:        }
                    770: }
                    771:
                    772: void kmulup(n1,n2,nr)
                    773: UP n1,n2,*nr;
                    774: {
                    775:        UP n,t,s,m,carry;
                    776:        int d,d1,d2,len,i,l;
                    777:        pointer *r,*r0;
                    778:
                    779:        if ( !n1 || !n2 ) {
                    780:                *nr = 0; return;
                    781:        }
                    782:        d1 = DEG(n1)+1; d2 = DEG(n2)+1;
                    783:        if ( (d1 < up_kara_mag) && (d2 < up_kara_mag) )
                    784:                mulup(n1,n2,nr);
                    785:        else
                    786:                kmulupmain(n1,n2,nr);
                    787: }
                    788:
                    789: void ksquareup(n1,nr)
                    790: UP n1,*nr;
                    791: {
                    792:        int d1;
                    793:        extern Q TWO;
                    794:
                    795:        if ( !n1 ) {
                    796:                *nr = 0; return;
                    797:        }
                    798:        d1 = DEG(n1)+1;
                    799:        if ( (d1 < up_kara_mag) )
                    800:                squareup(n1,nr);
                    801:        else
                    802:                ksquareupmain(n1,nr);
                    803: }
                    804:
                    805: void copyup(n1,n2)
                    806: UP n1,n2;
                    807: {
                    808:        n2->d = n1->d;
                    809:        bcopy((char *)n1->c,(char *)n2->c,(n1->d+1)*sizeof(Q));
                    810: }
                    811:
                    812: void c_copyup(n,len,p)
                    813: UP n;
                    814: int len;
                    815: pointer *p;
                    816: {
                    817:        if ( n )
                    818:                bcopy((char *)COEF(n),(char *)p,MIN((DEG(n)+1),len)*sizeof(pointer));
                    819: }
                    820:
                    821: void kmulupmain(n1,n2,nr)
                    822: UP n1,n2,*nr;
                    823: {
                    824:        int d1,d2,h,len;
                    825:        UP n1lo,n1hi,n2lo,n2hi,hi,lo,mid1,mid2,mid,s1,s2,t1,t2;
                    826:
                    827:        d1 = DEG(n1)+1; d2 = DEG(n2)+1; h = (MAX(d1,d2)+1)/2;
                    828:        decompup(n1,h,&n1lo,&n1hi);
                    829:        decompup(n2,h,&n2lo,&n2hi);
                    830:        kmulup(n1lo,n2lo,&lo);
                    831:        kmulup(n1hi,n2hi,&hi);
                    832:        shiftup(hi,2*h,&t2);
                    833:        addup(lo,t2,&t1);
                    834:        addup(hi,lo,&mid1);
                    835:        subup(n1hi,n1lo,&s1); subup(n2lo,n2hi,&s2); kmulup(s1,s2,&mid2);
                    836:        addup(mid1,mid2,&mid);
                    837:        shiftup(mid,h,&t2);
                    838:        addup(t1,t2,nr);
                    839: }
                    840:
                    841: void ksquareupmain(n1,nr)
                    842: UP n1,*nr;
                    843: {
                    844:        int d1,h,len;
                    845:        UP n1lo,n1hi,hi,lo,mid1,mid2,mid,s1,t1,t2;
                    846:
                    847:        d1 = DEG(n1)+1; h = (d1+1)/2;
                    848:        decompup(n1,h,&n1lo,&n1hi);
                    849:        ksquareup(n1hi,&hi); ksquareup(n1lo,&lo);
                    850:        shiftup(hi,2*h,&t2);
                    851:        addup(lo,t2,&t1);
                    852:        addup(hi,lo,&mid1);
                    853:        subup(n1hi,n1lo,&s1); ksquareup(s1,&mid2);
                    854:        subup(mid1,mid2,&mid);
                    855:        shiftup(mid,h,&t2);
                    856:        addup(t1,t2,nr);
                    857: }
                    858:
                    859: void rembymulup(n1,n2,nr)
                    860: UP n1,n2;
                    861: UP *nr;
                    862: {
                    863:        int d1,d2,d;
                    864:        UP r1,r2,inv2,t,s,q;
                    865:
                    866:        if ( !n2 )
                    867:                error("rembymulup : division by 0");
                    868:        else if ( !n1 || !n2->d )
                    869:                *nr = 0;
                    870:        else if ( (d1 = n1->d) < (d2 = n2->d) )
                    871:                *nr = n1;
                    872:        else {
                    873:                d = d1-d2;
                    874:                reverseup(n1,d1,&t); truncup(t,d+1,&r1);
                    875:                reverseup(n2,d2,&r2);
                    876:                invmodup(r2,d,&inv2);
                    877:                kmulup(r1,inv2,&t);
                    878:                truncup(t,d+1,&s);
                    879:                reverseup(s,d,&q);
                    880:                kmulup(q,n2,&t); subup(n1,t,nr);
                    881:        }
                    882: }
                    883:
                    884: /*
                    885:        deg n2 = d
                    886:        deg n1 <= 2*d-1
                    887:        inv2 = inverse of reversep(n2) mod x^d
                    888: */
                    889:
                    890: void hybrid_rembymulup_special(ff,n1,n2,inv2,nr)
                    891: int ff;
                    892: UP n1,n2,inv2;
                    893: UP *nr;
                    894: {
                    895:        int d1,d2,d;
                    896:        UP r1,t,s,q,u;
                    897:
                    898:        if ( !n2 )
                    899:                error("hybrid_rembymulup : division by 0");
                    900:        else if ( !n1 || !n2->d )
                    901:                *nr = 0;
                    902:        else if ( (d1 = n1->d) < (d2 = n2->d) )
                    903:                *nr = n1;
                    904:        else {
                    905:                d = d1-d2;
                    906:                reverseup(n1,d1,&t); truncup(t,d+1,&r1);
                    907:                hybrid_tmulup(ff,r1,inv2,d+1,&t);
                    908:                truncup(t,d+1,&s);
                    909:                reverseup(s,d,&q);
                    910:
                    911:                hybrid_tmulup(ff,q,n2,d2,&t);
                    912:                truncup(n1,d2,&s);
                    913:                subup(s,t,nr);
                    914:        }
                    915: }
                    916:
                    917: void rembymulup_special(n1,n2,inv2,nr)
                    918: UP n1,n2,inv2;
                    919: UP *nr;
                    920: {
                    921:        int d1,d2,d;
                    922:        UP r1,t,s,q,u;
                    923:
                    924:        if ( !n2 )
                    925:                error("rembymulup : division by 0");
                    926:        else if ( !n1 || !n2->d )
                    927:                *nr = 0;
                    928:        else if ( (d1 = n1->d) < (d2 = n2->d) )
                    929:                *nr = n1;
                    930:        else {
                    931:                d = d1-d2;
                    932:                reverseup(n1,d1,&t); truncup(t,d+1,&r1);
                    933:                tkmulup(r1,inv2,d+1,&t);
                    934:                truncup(t,d+1,&s);
                    935:                reverseup(s,d,&q);
                    936:
                    937:                tkmulup(q,n2,d2,&t);
                    938:                truncup(n1,d2,&s);
                    939:                subup(s,t,nr);
                    940:        }
                    941: }
                    942:
                    943: /* *nr = n1*n2 mod x^d */
                    944:
                    945: void tkmulup(n1,n2,d,nr)
                    946: UP n1,n2;
                    947: int d;
                    948: UP *nr;
                    949: {
                    950:        int m;
                    951:        UP n1l,n1h,n2l,n2h,l,h,t,s,u,afo;
                    952:
                    953:        if ( d < 0 )
                    954:                error("tkmulup : invalid argument");
                    955:        else if ( d == 0 )
                    956:                *nr = 0;
                    957:        else {
                    958:                truncup(n1,d,&t); n1 = t;
                    959:                truncup(n2,d,&t); n2 = t;
                    960:                if ( !n1 || !n2 )
                    961:                        *nr = 0;
                    962:                else if ( n1->d < up_tkara_mag || n2->d < up_tkara_mag )
                    963:                        tmulup(n1,n2,d,nr);
                    964:                else {
                    965:                        m = (d+1)/2;
                    966:                        decompup(n1,m,&n1l,&n1h);
                    967:                        decompup(n2,m,&n2l,&n2h);
                    968:                        kmulup(n1l,n2l,&l);
                    969:                        tkmulup(n1l,n2h,d-m,&t);
                    970:                        tkmulup(n2l,n1h,d-m,&s);
                    971:                        addup(t,s,&u);
                    972:                        shiftup(u,m,&h);
                    973:                        addup(l,h,&t);
                    974:                        truncup(t,d,nr);
                    975:                }
                    976:        }
                    977: }
                    978:
                    979: /* n->n*x^d */
                    980:
                    981: void shiftup(n,d,nr)
                    982: UP n;
                    983: int d;
                    984: UP *nr;
                    985: {
                    986:        int dr;
                    987:        UP r;
                    988:
                    989:        if ( !n )
                    990:                *nr = 0;
                    991:        else {
                    992:                dr = n->d+d;
                    993:                *nr = r = UPALLOC(dr); r->d = dr;
                    994:                bzero(r->c,(dr+1)*sizeof(Num));
                    995:                bcopy(n->c,r->c+d,(n->d+1)*sizeof(Num));
                    996:        }
                    997: }
                    998:
                    999: void fft_rembymulup_special(n1,n2,inv2,nr)
                   1000: UP n1,n2,inv2;
                   1001: UP *nr;
                   1002: {
                   1003:        int d1,d2,d;
                   1004:        UP r1,t,s,q,u;
                   1005:
                   1006:        if ( !n2 )
                   1007:                error("rembymulup : division by 0");
                   1008:        else if ( !n1 || !n2->d )
                   1009:                *nr = 0;
                   1010:        else if ( (d1 = n1->d) < (d2 = n2->d) )
                   1011:                *nr = n1;
                   1012:        else {
                   1013:                d = d1-d2;
                   1014:                reverseup(n1,d1,&t); truncup(t,d+1,&r1);
                   1015:                trunc_fft_mulup(r1,inv2,d+1,&t);
                   1016:                truncup(t,d+1,&s);
                   1017:                reverseup(s,d,&q);
                   1018:                trunc_fft_mulup(q,n2,d2,&t); truncup(t,d2,&u);
                   1019:                truncup(n1,d2,&s);
                   1020:                subup(s,u,nr);
                   1021:        }
                   1022: }
                   1023:
                   1024: void set_degreeup(n,d)
                   1025: UP n;
                   1026: int d;
                   1027: {
                   1028:        int i;
                   1029:
                   1030:        for ( i = d; i >= 0 && !n->c[i]; i-- );
                   1031:        n->d = i;
                   1032: }
                   1033:
                   1034: /* n -> n0 + x^d n1 */
                   1035:
                   1036: void decompup(n,d,n0,n1)
                   1037: UP n;
                   1038: int d;
                   1039: UP *n0,*n1;
                   1040: {
                   1041:        int dn;
                   1042:        UP r0,r1;
                   1043:
                   1044:        if ( !n || d > n->d ) {
                   1045:                *n0 = n; *n1 = 0;
                   1046:        } else if ( d < 0 )
                   1047:                error("decompup : invalid argument");
                   1048:        else if ( d == 0 ) {
                   1049:                *n0 = 0; *n1 = n;
                   1050:        } else {
                   1051:                dn = n->d;
                   1052:                *n0 = r0 = UPALLOC(d-1);
                   1053:                *n1 = r1 = UPALLOC(dn-d);
                   1054:                bcopy(n->c,r0->c,d*sizeof(Num));
                   1055:                bcopy(n->c+d,r1->c,(dn-d+1)*sizeof(Num));
                   1056:                set_degreeup(r0,d-1);
                   1057:                if ( r0->d < 0 )
                   1058:                        *n0 = 0;
                   1059:                set_degreeup(r1,dn-d);
                   1060:                if ( r1->d < 0 )
                   1061:                        *n1 = 0;
                   1062:        }
                   1063: }
                   1064:
                   1065: /* n -> n mod x^d */
                   1066:
                   1067: void truncup(n1,d,nr)
                   1068: UP n1;
                   1069: int d;
                   1070: UP *nr;
                   1071: {
                   1072:        int i;
                   1073:        UP r;
                   1074:
                   1075:        if ( !n1 || d > n1->d )
                   1076:                *nr = n1;
                   1077:        else if ( d < 0 )
                   1078:                error("truncup : invalid argument");
                   1079:        else if ( d == 0 )
                   1080:                *nr = 0;
                   1081:        else {
                   1082:                *nr = r = UPALLOC(d-1);
                   1083:                bcopy(n1->c,r->c,d*sizeof(Num));
                   1084:                for ( i = d-1; i >= 0 && !r->c[i]; i-- );
                   1085:                if ( i < 0 )
                   1086:                        *nr = 0;
                   1087:                else
                   1088:                        r->d = i;
                   1089:        }
                   1090: }
                   1091:
                   1092: int int_bits(t)
                   1093: int t;
                   1094: {
                   1095:        int k;
                   1096:
                   1097:        for ( k = 0; t; t>>=1, k++);
                   1098:        return k;
                   1099: }
                   1100:
                   1101: /* n is assumed to be LM or integer coefficient */
                   1102:
                   1103: int maxblenup(n)
                   1104: UP n;
                   1105: {
                   1106:        int m,r,i,d;
                   1107:        Num *c;
                   1108:
                   1109:        if ( !n )
                   1110:                return 0;
                   1111:        d = n->d; c = (Num *)n->c;
                   1112:        for ( r = 0, i = 0; i <= d; i++ )
                   1113:                if ( c[i] ) {
                   1114:                        switch ( NID(c[i]) ) {
                   1115:                                case N_LM:
                   1116:                                        m = n_bits(((LM)c[i])->body);
                   1117:                                        break;
                   1118:                                case N_Q:
                   1119:                                        m = n_bits(((Q)c[i])->nm);
                   1120:                                        break;
                   1121:                                default:
                   1122:                                        error("maxblenup : invalid coefficient");
                   1123:                        }
                   1124:                        r = MAX(m,r);
                   1125:                }
                   1126:        return r;
                   1127: }
                   1128:
                   1129: void uptofmarray(mod,n,f)
                   1130: int mod;
                   1131: UP n;
                   1132: ModNum *f;
                   1133: {
                   1134:        int d,i;
                   1135:        unsigned int r;
                   1136:        Num *c;
                   1137:
                   1138:        if ( !n )
                   1139:                return;
                   1140:        else {
                   1141:                d = n->d; c = (Num *)n->c;
                   1142:                for ( i = 0; i <= d; i++ ) {
                   1143:                        if ( c[i] ) {
                   1144:                                switch ( NID(c[i]) ) {
                   1145:                                        case N_LM:
                   1146:                                                f[i] = (ModNum)rem(((LM)c[i])->body,mod);
                   1147:                                                break;
                   1148:                                        case N_Q:
                   1149:                                                r = rem(NM((Q)c[i]),mod);
                   1150:                                                if ( r && (SGN((Q)c[i])<0) )
                   1151:                                                        r = mod-r;
                   1152:                                                f[i] = (ModNum)r;
                   1153:                                                break;
                   1154:                                        default:
                   1155:                                                error("uptofmarray : invalid coefficient");
                   1156:                                }
                   1157:                        } else
                   1158:                                f[i] = 0;
                   1159:                }
                   1160:        }
                   1161: }
                   1162:
                   1163: void fmarraytoup(f,d,nr)
                   1164: ModNum *f;
                   1165: int d;
                   1166: UP *nr;
                   1167: {
                   1168:        int i;
                   1169:        Q *c;
                   1170:        UP r;
                   1171:
                   1172:        if ( d < 0 ) {
                   1173:                *nr = 0;
                   1174:        } else {
                   1175:                *nr = r = UPALLOC(d); c = (Q *)r->c;
                   1176:                for ( i = 0; i <= d; i++ ) {
                   1177:                        UTOQ((unsigned int)f[i],c[i]);
                   1178:                }
                   1179:                for ( i = d; i >= 0 && !c[i]; i-- );
                   1180:                if ( i < 0 )
                   1181:                        *nr = 0;
                   1182:                else
                   1183:                        r->d = i;
                   1184:        }
                   1185: }
                   1186:
                   1187: /* f[i]: an array of length n */
                   1188:
                   1189: void uiarraytoup(f,n,d,nr)
                   1190: unsigned int **f;
                   1191: int n,d;
                   1192: UP *nr;
                   1193: {
                   1194:        int i,j;
                   1195:        unsigned int *fi;
                   1196:        N ci;
                   1197:        Q *c;
                   1198:        UP r;
                   1199:
                   1200:        if ( d < 0 ) {
                   1201:                *nr = 0;
                   1202:        } else {
                   1203:                *nr = r = UPALLOC(d); c = (Q *)r->c;
                   1204:                for ( i = 0; i <= d; i++ ) {
                   1205:                        fi = f[i];
                   1206:                        for ( j = n-1; j >= 0 && !fi[j]; j-- );
                   1207:                        j++;
                   1208:                        if ( j ) {
                   1209:                                ci = NALLOC(j);
                   1210:                                PL(ci) = j;
                   1211:                                bcopy(fi,BD(ci),j*sizeof(unsigned int));
                   1212:                                NTOQ(ci,1,c[i]);
                   1213:                        } else
                   1214:                                c[i] = 0;
                   1215:                }
                   1216:                for ( i = d; i >= 0 && !c[i]; i-- );
                   1217:                if ( i < 0 )
                   1218:                        *nr = 0;
                   1219:                else
                   1220:                        r->d = i;
                   1221:        }
                   1222: }
                   1223:
                   1224: void adj_coefup(n,m,m2,nr)
                   1225: UP n;
                   1226: N m,m2;
                   1227: UP *nr;
                   1228: {
                   1229:        int d;
                   1230:        Q *c,*cr;
                   1231:        Q mq;
                   1232:        int i;
                   1233:        UP r;
                   1234:
                   1235:        if ( !n )
                   1236:                *nr = 0;
                   1237:        else {
                   1238:                d = n->d; c = (Q *)n->c;
                   1239:                *nr = r = UPALLOC(d); cr = (Q *)r->c;
                   1240:                NTOQ(m,1,mq);
                   1241:                for ( i = 0; i <= d; i++ ) {
                   1242:                        if ( !c[i] )
                   1243:                                continue;
                   1244:                        if ( cmpn(NM(c[i]),m2) > 0 )
                   1245:                                subq(c[i],mq,&cr[i]);
                   1246:                        else
                   1247:                                cr[i] = c[i];
                   1248:                }
                   1249:                for ( i = d; i >= 0 && !cr[i]; i-- );
                   1250:                if ( i < 0 )
                   1251:                        *nr = 0;
                   1252:                else
                   1253:                        r->d = i;
                   1254:        }
                   1255: }
                   1256:
                   1257: /* n is assumed to have positive integer coefficients. */
                   1258:
                   1259: void remcup(n,mod,nr)
                   1260: UP n;
                   1261: N mod;
                   1262: UP *nr;
                   1263: {
                   1264:        int i,d;
                   1265:        Q *c,*cr;
                   1266:        UP r;
                   1267:        N t;
                   1268:
                   1269:        if ( !n )
                   1270:                *nr = 0;
                   1271:        else {
                   1272:                d = n->d; c = (Q *)n->c;
                   1273:                *nr = r = UPALLOC(d); cr = (Q *)r->c;
                   1274:                for ( i = 0; i <= d; i++ )
                   1275:                        if ( c[i] ) {
                   1276:                                remn(NM(c[i]),mod,&t);
                   1277:                                if ( t )
                   1278:                                        NTOQ(t,1,cr[i]);
                   1279:                                else
                   1280:                                        cr[i] = 0;
                   1281:                        } else
                   1282:                                cr[i] = 0;
                   1283:                for ( i = d; i >= 0 && !cr[i]; i-- );
                   1284:                if ( i < 0 )
                   1285:                        *nr = 0;
                   1286:                else
                   1287:                        r->d = i;
                   1288:        }
                   1289: }
                   1290:
                   1291: void fft_mulup_main(UP,UP,int,UP *);
                   1292:
                   1293: void fft_mulup(n1,n2,nr)
                   1294: UP n1,n2;
                   1295: UP *nr;
                   1296: {
                   1297:        int d1,d2,d,b1,b2,h;
                   1298:        UP n1lo,n1hi,n2lo,n2hi,lo,hi,t1,t2,mid1,mid2,mid,s1,s2;
                   1299:
                   1300:        if ( !n1 || !n2 )
                   1301:                *nr = 0;
                   1302:        else {
                   1303:                d1 = n1->d; d2 = n2->d;
                   1304:                if ( MAX(d1,d2) < up_fft_mag )
                   1305:                        kmulup(n1,n2,nr);
                   1306:                else {
                   1307:                        b1 = maxblenup(n1); b2 = maxblenup(n2);
                   1308:                        if ( fft_available(d1,b1,d2,b2) )
                   1309:                                fft_mulup_main(n1,n2,0,nr);
                   1310:                        else {
                   1311:                                d = MAX(d1,d2)+1; h = (d+1)/2;
                   1312:                                decompup(n1,h,&n1lo,&n1hi);
                   1313:                                decompup(n2,h,&n2lo,&n2hi);
                   1314:                                fft_mulup(n1lo,n2lo,&lo);
                   1315:                                fft_mulup(n1hi,n2hi,&hi);
                   1316:                                shiftup(hi,2*h,&t2);
                   1317:                                addup(lo,t2,&t1);
                   1318:                                addup(hi,lo,&mid1);
                   1319:                                subup(n1hi,n1lo,&s1); subup(n2lo,n2hi,&s2);
                   1320:                                fft_mulup(s1,s2,&mid2);
                   1321:                                addup(mid1,mid2,&mid);
                   1322:                                shiftup(mid,h,&t2);
                   1323:                                addup(t1,t2,nr);
                   1324:                        }
                   1325:                }
                   1326:        }
                   1327: }
                   1328:
                   1329: void trunc_fft_mulup(n1,n2,dbd,nr)
                   1330: UP n1,n2;
                   1331: int dbd;
                   1332: UP *nr;
                   1333: {
                   1334:        int d1,d2,b1,b2,m;
                   1335:        UP n1l,n1h,n2l,n2h,l,h,t,s,u;
                   1336:
                   1337:        if ( !n1 || !n2 )
                   1338:                *nr = 0;
                   1339:        else if ( dbd < 0 )
                   1340:                error("trunc_fft_mulup : invalid argument");
                   1341:        else if ( dbd == 0 )
                   1342:                *nr = 0;
                   1343:        else {
                   1344:                truncup(n1,dbd,&t); n1 = t;
                   1345:                truncup(n2,dbd,&t); n2 = t;
                   1346:                d1 = n1->d; d2 = n2->d;
                   1347:                if ( MAX(d1,d2) < up_fft_mag )
                   1348:                        tkmulup(n1,n2,dbd,nr);
                   1349:                else {
                   1350:                        b1 = maxblenup(n1); b2 = maxblenup(n2);
                   1351:                        if ( fft_available(d1,b1,d2,b2) )
                   1352:                                fft_mulup_main(n1,n2,dbd,nr);
                   1353:                        else {
                   1354:                                m = (dbd+1)/2;
                   1355:                                decompup(n1,m,&n1l,&n1h);
                   1356:                                decompup(n2,m,&n2l,&n2h);
                   1357:                                fft_mulup(n1l,n2l,&l);
                   1358:                                trunc_fft_mulup(n1l,n2h,dbd-m,&t);
                   1359:                                trunc_fft_mulup(n2l,n1h,dbd-m,&s);
                   1360:                                addup(t,s,&u);
                   1361:                                shiftup(u,m,&h);
                   1362:                                addup(l,h,&t);
                   1363:                                truncup(t,dbd,nr);
                   1364:                        }
                   1365:                }
                   1366:        }
                   1367: }
                   1368:
                   1369: void fft_squareup(n1,nr)
                   1370: UP n1;
                   1371: UP *nr;
                   1372: {
                   1373:        int d1,d,h,len,b1;
                   1374:        UP n1lo,n1hi,hi,lo,mid1,mid2,mid,s1,t1,t2;
                   1375:
                   1376:        if ( !n1 )
                   1377:                *nr = 0;
                   1378:        else {
                   1379:                d1 = n1->d;
                   1380:                if ( d1 < up_fft_mag )
                   1381:                        ksquareup(n1,nr);
                   1382:                else {
                   1383:                        b1 = maxblenup(n1);
                   1384:                        if ( fft_available(d1,b1,d1,b1) )
                   1385:                                fft_mulup_main(n1,n1,0,nr);
                   1386:                        else {
                   1387:                                d = d1+1; h = (d1+1)/2;
                   1388:                                decompup(n1,h,&n1lo,&n1hi);
                   1389:                                fft_squareup(n1hi,&hi);
                   1390:                                fft_squareup(n1lo,&lo);
                   1391:                                shiftup(hi,2*h,&t2);
                   1392:                                addup(lo,t2,&t1);
                   1393:                                addup(hi,lo,&mid1);
                   1394:                                subup(n1hi,n1lo,&s1);
                   1395:                                fft_squareup(s1,&mid2);
                   1396:                                subup(mid1,mid2,&mid);
                   1397:                                shiftup(mid,h,&t2);
                   1398:                                addup(t1,t2,nr);
                   1399:                        }
                   1400:                }
                   1401:        }
                   1402: }
                   1403:
                   1404: /*
                   1405:  * dbd == 0 => n1 * n2
                   1406:  * dbd > 0  => n1 * n2 mod x^dbd
                   1407:  * n1 == n2 => squaring
                   1408:  */
                   1409:
                   1410: void fft_mulup_main(n1,n2,dbd,nr)
                   1411: UP n1,n2;
                   1412: UP *nr;
                   1413: {
                   1414:        ModNum *f1,*f2,*w,*fr;
                   1415:        ModNum **frarray,**fa;
                   1416:        unsigned int *modarray,*ma;
                   1417:        int modarray_len;
                   1418:        int frarray_index = 0;
                   1419:        N m,m1,m2;
                   1420:        int d1,d2,dmin,i,mod,root,d,cond,bound;
                   1421:        UP r;
                   1422:
                   1423:        if ( !n1 || !n2 ) {
                   1424:                *nr = 0; return;
                   1425:        }
                   1426:        d1 = n1->d; d2 = n2->d; dmin = MIN(d1,d2);
                   1427:        if ( !d1 || !d2 ) {
                   1428:                mulup(n1,n2,nr); return;
                   1429:        }
                   1430:        m = ONEN;
                   1431:        bound = maxblenup(n1)+maxblenup(n2)+int_bits(dmin)+1;
                   1432:        f1 = (ModNum *)MALLOC_ATOMIC((d1+d2+1)*sizeof(ModNum));
                   1433:        if ( n1 == n2 )
                   1434:                f2 = 0;
                   1435:        else
                   1436:                f2 = (ModNum *)MALLOC_ATOMIC((d1+d2+1)*sizeof(ModNum));
                   1437:        w = (ModNum *)MALLOC_ATOMIC(6*(1<<int_bits(d1+d2+1))*sizeof(ModNum));
                   1438:        modarray_len = 1024;
                   1439:        modarray = (unsigned int *)MALLOC_ATOMIC(modarray_len*sizeof(unsigned int));
                   1440:        frarray = (ModNum **)MALLOC(modarray_len*sizeof(ModNum *));
                   1441:        for ( i = 0; i < NPrimes; i++ ) {
                   1442:                FFT_primes(i,&mod,&root,&d);
                   1443:                if ( (1<<d) < d1+d2+1 )
                   1444:                        continue;
                   1445:                if ( frarray_index == modarray_len ) {
                   1446:                        ma = (unsigned int *)MALLOC_ATOMIC(2*modarray_len*sizeof(unsigned int));
                   1447:                        bcopy(modarray,ma,modarray_len*sizeof(unsigned int));
                   1448:                        modarray = ma;
                   1449:                        fa = (ModNum **)MALLOC(2*modarray_len*sizeof(ModNum *));
                   1450:                        bcopy(frarray,fa,modarray_len*sizeof(ModNum *));
                   1451:                        frarray = fa;
                   1452:                        modarray_len *= 2;
                   1453:                }
                   1454:                modarray[frarray_index] = mod;
                   1455:                frarray[frarray_index++] = fr
                   1456:                        = (ModNum *)MALLOC_ATOMIC((d1+d2+1)*sizeof(ModNum));
                   1457:                uptofmarray(mod,n1,f1);
                   1458:                if ( !f2 )
                   1459:                        cond = FFT_pol_square(d1,f1,fr,i,w);
                   1460:                else {
                   1461:                        uptofmarray(mod,n2,f2);
                   1462:                        cond = FFT_pol_product(d1,f1,d2,f2,fr,i,w);
                   1463:                }
                   1464:                if ( cond )
                   1465:                        error("fft_mulup : error in FFT_pol_product");
                   1466:                STON(mod,m1); muln(m,m1,&m2); m = m2;
                   1467:                if ( n_bits(m) > bound ) {
                   1468:                        if ( !dbd )
                   1469:                                dbd = d1+d2+1;
                   1470:                        crup(frarray,MIN(d1+d2,dbd-1),modarray,frarray_index,m,&r);
                   1471:                        divin(m,2,&m2);
                   1472:                        adj_coefup(r,m,m2,nr);
                   1473:                        return;
                   1474:                }
                   1475:        }
                   1476:        error("fft_mulup : FFT_primes exhausted");
                   1477: }
                   1478: #if 0
                   1479: /* inefficient version */
                   1480:
                   1481: void crup(f,d,mod,index,m,r)
                   1482: ModNum **f;
                   1483: int d;
                   1484: int *mod;
                   1485: int index;
                   1486: N m;
                   1487: UP *r;
                   1488: {
                   1489:        N *cof,*c;
                   1490:        int *inv;
                   1491:        struct oUP w;
                   1492:        int i;
                   1493:        UP s,s1,s2;
                   1494:        N t;
                   1495:        UP *g;
                   1496:        Q q;
                   1497:        struct oEGT eg0,eg1;
                   1498:
                   1499:        get_eg(&eg0);
                   1500:        w.d = 0;
                   1501:        inv = (int *)ALLOCA(index*sizeof(int));
                   1502:        cof = (N *)ALLOCA(index*sizeof(N));
                   1503:        c = (N *)ALLOCA(index*sizeof(N));
                   1504:        g = (UP *)ALLOCA(index*sizeof(UP));
                   1505:        up_lazy = 1;
                   1506:        for ( i = 0, s = 0; i < index; i++ ) {
                   1507:                divin(m,mod[i],&cof[i]);
                   1508:                inv[i] = invm(rem(cof[i],mod[i]),mod[i]);
                   1509:                STON(inv[i],t);
                   1510:                muln(cof[i],t,&c[i]);
                   1511:                NTOQ(c[i],1,q); w.c[0] = (Num)q;
                   1512:                fmarraytoup(f[i],d,&g[i]);
                   1513:                mulup(g[i],&w,&s1);
                   1514:                addup(s,s1,&s2);
                   1515:                s = s2;
                   1516:        }
                   1517:        up_lazy = 0;
                   1518:        remcup(s,m,r);
                   1519:        get_eg(&eg1);
                   1520:        add_eg(&eg_chrem,&eg0,&eg1);
                   1521: }
                   1522:
                   1523: #else
                   1524: /* improved version */
                   1525:
                   1526: void crup(f,d,mod,index,m,r)
                   1527: ModNum **f;
                   1528: int d;
                   1529: int *mod;
                   1530: int index;
                   1531: N m;
                   1532: UP *r;
                   1533: {
                   1534:        N cof,c,t,w,w1;
                   1535:        struct oN fc;
                   1536:        N *s;
                   1537:        UP u;
                   1538:        Q q;
                   1539:        int inv,i,j,rlen;
                   1540:
                   1541:        rlen = PL(m)+10; /* XXX */
                   1542:        PL(&fc) = 1;
                   1543:        c = NALLOC(rlen);
                   1544:        w = NALLOC(rlen);
                   1545:        w1 = NALLOC(rlen);
                   1546:        s = (N *)MALLOC((d+1)*sizeof(N));
                   1547:        for ( i = 0; i <= d; i++ ) {
                   1548:                s[i] = NALLOC(rlen);
                   1549:                PL(s[i]) = 0;
                   1550:                bzero(BD(s[i]),rlen*sizeof(unsigned int));
                   1551:        }
                   1552:        for ( i = 0; i < index; i++ ) {
                   1553:                divin(m,mod[i],&cof);
                   1554:                inv = invm(rem(cof,mod[i]),mod[i]); STON(inv,t);
                   1555:                _muln(cof,t,c);
                   1556:                /* s += c*f[i] */
                   1557:                for ( j = 0; j <= d; j++ )
                   1558:                        if ( f[i][j] ) {
                   1559:                                BD(&fc)[0] = f[i][j];
                   1560:                                _muln(c,&fc,w);
                   1561:                                _addn(s[j],w,w1);
                   1562:                                dupn(w1,s[j]);
                   1563:                        }
                   1564:        }
                   1565:        for ( i = d; i >= 0; i-- )
                   1566:                if ( s[i] )
                   1567:                        break;
                   1568:        if ( i < 0 )
                   1569:                *r = 0;
                   1570:        else {
                   1571:                u = UPALLOC(i);
                   1572:                DEG(u) = i;
                   1573:                for ( j = 0; j <= i; j++ ) {
                   1574:                        if ( PL(s[j]) )
                   1575:                                NTOQ(s[j],1,q);
                   1576:                        else
                   1577:                                q = 0;
                   1578:                        COEF(u)[j] = (Num)q;
                   1579:                }
                   1580:                remcup(u,m,r);
                   1581:        }
                   1582: }
                   1583: #endif
                   1584:

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