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

Annotation of OpenXM_contrib2/asir2000/builtin/gf.c, Revision 1.1.1.1

1.1       noro        1: /* $OpenXM: OpenXM/src/asir99/builtin/gf.c,v 1.1.1.1 1999/11/10 08:12:25 noro Exp $ */
                      2: #include "ca.h"
                      3: #include "parse.h"
                      4:
                      5: struct resf_dlist {
                      6:        int ib,id;
                      7: };
                      8:
                      9: int resf_degtest(int,int *,int,struct resf_dlist *);
                     10: void uhensel(P,NODE,int,int,NODE *);
                     11: void resf_hensel(int,P,int,P *,ML *);
                     12: void resf_dtest(P,ML,int,int *,int *,DCP *);
                     13: void resf_dtest_special(P,ML,int,int *,int *,DCP *);
                     14: void dtest_special(P,ML,P *);
                     15: void hensel_special(int,int,P,P *,ML *);
                     16:
                     17: void nullspace(UM **,UM,int,int,int *);
                     18: void nullspace_lm(LM **,int,int *);
                     19: void nullspace_gf2n(GF2N **,int,int *);
                     20: void nullspace_gfpn(GFPN **,int,int *);
                     21: void null_to_sol(int **,int *,int,int,UM *);
                     22:
                     23: void showgfmat(UM **,int);
                     24: void pwr_mod(P,P,V,P,int,N,P *);
                     25: void rem_mod(P,P,V,P,int,P *);
                     26:
                     27: void Pnullspace(),Pgcda_mod(),Pftest(),Presfmain(),Ppwr_mod(),Puhensel();
                     28:
                     29: void Pnullspace_ff();
                     30:
                     31: void Psolve_linear_equation_gf2n();
                     32: void Plinear_form_to_vect(),Pvect_to_linear_form();
                     33:
                     34: void solve_linear_equation_gf2n(GF2N **,int,int,int *);
                     35: void linear_form_to_array(P,VL,int,Num *);
                     36: void array_to_linear_form(Num *,VL,int,P *);
                     37:
                     38: extern int current_ff;
                     39:
                     40: struct ftab gf_tab[] = {
                     41:        {"solve_linear_equation_gf2n",Psolve_linear_equation_gf2n,1},
                     42:        {"nullspace",Pnullspace,3},
                     43:        {"nullspace_ff",Pnullspace_ff,1},
                     44: /*     {"gcda_mod",Pgcda_mod,5}, */
                     45:        {"ftest",Pftest,2},
                     46:        {"resfmain",Presfmain,4},
                     47:        {"pwr_mod",Ppwr_mod,6},
                     48:        {"uhensel",Puhensel,4},
                     49:        {0,0,0},
                     50: };
                     51:
                     52: int resf_degtest(k,in,nb,dlist)
                     53: int k;
                     54: int *in;
                     55: int nb;
                     56: struct resf_dlist *dlist;
                     57: {
                     58:        int i,d0,d;
                     59:        int dl_i;
                     60:        struct resf_dlist *t;
                     61:
                     62:        if ( k < nb )
                     63:                return 0;
                     64:        if ( nb == 1 )
                     65:                return 1;
                     66:        d0 = 0; d = 0; dl_i = 0;
                     67:        for ( i = 0; i < k; i++ ) {
                     68:                t = &dlist[in[i]];
                     69:                if ( t->ib > dl_i + 1 )
                     70:                        return 0;
                     71:                else if ( t->ib == dl_i )
                     72:                        d += t->id;
                     73:                else if ( !d || (dl_i && d0 != d) )
                     74:                        return 0;
                     75:                else {
                     76:                        d0 = d; dl_i++; d = t->id;
                     77:                }
                     78:        }
                     79:        if ( dl_i != nb - 1 || d0 != d )
                     80:                return 0;
                     81:        else
                     82:                return 1;
                     83: }
                     84:
                     85: void Puhensel(arg,rp)
                     86: NODE arg;
                     87: LIST *rp;
                     88: {
                     89:        P f;
                     90:        NODE mfl,r;
                     91:        int mod,bound;
                     92:
                     93:        f = (P)ARG0(arg);
                     94:        mfl = BDY((LIST)ARG1(arg));
                     95:        mod = QTOS((Q)ARG2(arg));
                     96:        bound = QTOS((Q)ARG3(arg));
                     97:        uhensel(f,mfl,mod,bound,&r);
                     98:        MKLIST(*rp,r);
                     99: }
                    100:
                    101: void uhensel(f,mfl,mod,bound,rp)
                    102: P f;
                    103: NODE mfl;
                    104: int mod,bound;
                    105: NODE *rp;
                    106: {
                    107:        ML blist,clist,rlist;
                    108:        LUM fl;
                    109:        int nf,i;
                    110:        P s;
                    111:        V v;
                    112:        NODE t,top;
                    113:
                    114:        nf = length(mfl);
                    115:        blist = MLALLOC(nf); blist->n = nf; blist->mod = mod;
                    116:        for ( i = 0, t = mfl; i < nf; i++, t = NEXT(t) ) {
                    117:                blist->c[i] = (pointer)UMALLOC(UDEG((P)BDY(t)));
                    118:                ptoum(mod,(P)BDY(t),blist->c[i]);
                    119:        }
                    120:        gcdgen(f,blist,&clist);
                    121:        blist->bound = clist->bound = bound;
                    122:        W_LUMALLOC((int)UDEG(f),bound,fl);
                    123:        ptolum(mod,bound,f,fl);
                    124:        henmain(fl,blist,clist,&rlist);
                    125:        v = VR(f);
                    126:        for ( i = nf-1, top = 0; i >= 0; i-- ) {
                    127:                lumtop(v,mod,bound,rlist->c[i],&s);
                    128:                MKNODE(t,s,top); top = t;
                    129:        }
                    130:        *rp = top;
                    131: }
                    132:
                    133: void Presfmain(arg,rp)
                    134: NODE arg;
                    135: LIST *rp;
                    136: {
                    137:        P f;
                    138:        int mod,n,nb,i,j,k;
                    139:        int *nf,*md;
                    140:        P *mf;
                    141:        NODE mfl,mdl,t,s,u;
                    142:        ML list;
                    143:        DCP dc;
                    144:        int sflag;
                    145:
                    146:        f = (P)ARG0(arg);
                    147:        mod = QTOS((Q)ARG1(arg));
                    148:        mfl = BDY((LIST)ARG2(arg));
                    149:        mdl = BDY((LIST)ARG3(arg));
                    150:        for ( n = nb = 0, t = mfl; t; nb++, t = NEXT(t) )
                    151:                for ( s = BDY((LIST)BDY(t)); s; n++, s = NEXT(s) );
                    152:        if ( n == nb ) {
                    153:                /* f must be irreducible! */
                    154:                NEWDC(dc);
                    155:                dc->c = f; dc->d = ONE;
                    156:        } else {
                    157:                nf = W_ALLOC(nb); md = W_ALLOC(nb); mf = (P *)ALLOCA(n*sizeof(P));
                    158:                for ( k = i = 0, t = mfl, u = mdl, sflag = 1; t;
                    159:                        i++, t = NEXT(t), u = NEXT(u) ) {
                    160:                        if ( sflag && length(BDY((LIST)BDY(t))) != 2 )
                    161:                                sflag = 0;
                    162:                        for ( j = 0, s = BDY((LIST)BDY(t)); s; j++, s = NEXT(s) )
                    163:                                mf[k++] = (P)BDY(s);
                    164:                        nf[i] = j; md[i] = QTOS((Q)BDY(u));
                    165:                }
                    166:                resf_hensel(mod,f,n,mf,&list);
                    167:                if ( sflag )
                    168:                        resf_dtest_special(f,list,nb,nf,md,&dc);
                    169:                else
                    170:                        resf_dtest(f,list,nb,nf,md,&dc);
                    171:        }
                    172:        dcptolist(dc,rp);
                    173: }
                    174:
                    175: void resf_hensel(mod,f,nf,mfl,listp)
                    176: int mod;
                    177: P f;
                    178: int nf;
                    179: P *mfl;
                    180: ML *listp;
                    181: {
                    182:        register int i,j;
                    183:        int q,n,bound;
                    184:        int *p;
                    185:        int **pp;
                    186:        ML blist,clist,bqlist,cqlist,rlist;
                    187:        UM *b;
                    188:        LUM fl,tl;
                    189:        LUM *l;
                    190:
                    191:        blist = MLALLOC(nf); blist->n = nf; blist->mod = mod;
                    192:        for ( i = 0; i < nf; i++ ) {
                    193:                blist->c[i] = (pointer)UMALLOC(UDEG(mfl[i]));
                    194:                ptoum(mod,mfl[i],blist->c[i]);
                    195:        }
                    196:        gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    197:        n = bqlist->n; q = bqlist->mod;
                    198:        bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    199:        if ( bound == 1 ) {
                    200:                *listp = rlist = MLALLOC(n);
                    201:                rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    202:                for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    203:                        tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    204:                        for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    205:                                        pp[j][0] = p[j];
                    206:                }
                    207:        } else {
                    208:                W_LUMALLOC((int)UDEG(f),bound,fl);
                    209:                ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    210:        }
                    211: }
                    212:
                    213: void resf_dtest(f,list,nb,nfl,mdl,dcp)
                    214: P f;
                    215: ML list;
                    216: int nb;
                    217: int *nfl,*mdl;
                    218: DCP *dcp;
                    219: {
                    220:        int n,np,bound,q;
                    221:        int i,j,k;
                    222:        int *win;
                    223:        P g,factor,cofactor;
                    224:        Q csum,csumt;
                    225:        DCP dcf,dcf0;
                    226:        LUM *c;
                    227:        ML wlist;
                    228:        struct resf_dlist *dlist;
                    229:        int z;
                    230:
                    231:        n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    232:        win = W_ALLOC(np+1);
                    233:        ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    234:        wlist = W_MLALLOC(np); wlist->n = list->n;
                    235:        wlist->mod = list->mod; wlist->bound = list->bound;
                    236:        c = (LUM *)COEF(wlist);
                    237:        bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    238:        dlist = (struct resf_dlist *)ALLOCA(np*sizeof(struct resf_dlist));
                    239:        for ( i = 0, j = 0; j < nb; j++ )
                    240:                for ( k = 0; k < nfl[j]; k++, i++ ) {
                    241:                        dlist[i].ib = j; dlist[i].id = DEG(c[i])/mdl[j];
                    242:                }
                    243:        k = nb;
                    244:        for ( i = 0; i < nb; i++ )
                    245:                win[i] = i+1;
                    246:        for ( g = f, dcf = dcf0 = 0, --np, z = 0; ; ) {
                    247: #if 0
                    248:                if ( !(z++ % 10000) )
                    249:                        fputc('.',stderr);
                    250: #endif
                    251:                if ( resf_degtest(k,win,nb,dlist) &&
                    252:                        dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
                    253:                        NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = factor;
                    254:                        g = cofactor;
                    255:                        ucsump(g,&csum); mulq(csum,(Q)COEF(DC(g)),&csumt); csum = csumt;
                    256:                        for ( i = 0; i < k - 1; i++ )
                    257:                                for ( j = win[i] + 1; j < win[i + 1]; j++ ) {
                    258:                                        c[j-i-1] = c[j];
                    259:                                        dlist[j-i-1] = dlist[j];
                    260:                                }
                    261:                        for ( j = win[k-1] + 1; j <= np; j++ ) {
                    262:                                c[j-k] = c[j];
                    263:                                dlist[j-k] = dlist[j];
                    264:                        }
                    265:                        if ( ( np -= k ) < k )
                    266:                                break;
                    267:                        if ( np - win[0] + 1 < k )
                    268:                                if ( ++k > np )
                    269:                                        break;
                    270:                                else
                    271:                                        for ( i = 0; i < k; i++ )
                    272:                                                win[i] = i + 1;
                    273:                        else
                    274:                                for ( i = 1; i < k; i++ )
                    275:                                        win[i] = win[0] + i;
                    276:                } else if ( !ncombi(1,np,k,win) )
                    277:                        if ( k == np )
                    278:                                break;
                    279:                        else
                    280:                                for ( i = 0, ++k; i < k; i++ )
                    281:                                        win[i] = i + 1;
                    282:        }
                    283:        NEXTDC(dcf0,dcf); COEF(dcf) = g;
                    284:        DEG(dcf) = ONE; NEXT(dcf) = 0;*dcp = dcf0;
                    285: }
                    286:
                    287: void resf_dtest_special(f,list,nb,nfl,mdl,dcp)
                    288: P f;
                    289: ML list;
                    290: int nb;
                    291: int *nfl,*mdl;
                    292: DCP *dcp;
                    293: {
                    294:        int n,np,bound,q;
                    295:        int i,j;
                    296:        int *win;
                    297:        P g,factor,cofactor;
                    298:        Q csum,csumt;
                    299:        DCP dcf,dcf0;
                    300:        LUM *c;
                    301:        ML wlist;
                    302:        int max;
                    303:
                    304:        n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    305:        win = W_ALLOC(np+1);
                    306:        ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    307:        wlist = W_MLALLOC(np); wlist->n = list->n;
                    308:        wlist->mod = list->mod; wlist->bound = list->bound;
                    309:        c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    310:        max = 1<<nb;
                    311:        for ( g = f, dcf = dcf0 = 0, i = 0; i < max; i++ ) {
                    312: #if 0
                    313:                if ( !(i % 1000) )
                    314:                        fprintf(stderr,"i=%d\n",i);
                    315: #endif
                    316:                for ( j = 0; j < nb; j++ )
                    317:                        win[j] = (i&(1<<j)) ? 2*j+1 : 2*j;
                    318:                if ( dtestmain(g,csum,wlist,nb,win,&factor,&cofactor) ) {
                    319: #if 0
                    320:                        fprintf(stderr,"success : i=%d\n",i);
                    321: #endif
                    322:                        NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = factor;
                    323:                        NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = cofactor;
                    324:                        NEXT(dcf) = 0;*dcp = dcf0;
                    325:                        return;
                    326:                }
                    327:        }
                    328:        NEXTDC(dcf0,dcf); COEF(dcf) = g;
                    329:        DEG(dcf) = ONE; NEXT(dcf) = 0;*dcp = dcf0;
                    330: }
                    331:
                    332: #if 0
                    333: void Pftest(arg,rp)
                    334: NODE arg;
                    335: P *rp;
                    336: {
                    337:        ML list;
                    338:        DCP dc;
                    339:        P p;
                    340:        P *mfl;
                    341:
                    342:        p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
                    343:        hensel_special(4,1,p,mfl,&list);
                    344:        dtest_special(p,list,rp);
                    345: }
                    346:
                    347: void dtest_special(f,list,pr)
                    348: P f;
                    349: ML list;
                    350: P *pr;
                    351: {
                    352:        int n,np,bound,q;
                    353:        int i,j,k;
                    354:        int *win;
                    355:        P g,factor,cofactor;
                    356:        Q csum,csumt;
                    357:        DCP dc,dcf,dcf0;
                    358:        LUM *c;
                    359:        ML wlist;
                    360:
                    361:        n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    362:        win = W_ALLOC(np+1);
                    363:        ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    364:        wlist = W_MLALLOC(np); wlist->n = list->n;
                    365:        wlist->mod = list->mod; wlist->bound = list->bound;
                    366:        c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    367:        for ( g = f, i = 130000; i < (1<<20); i++ ) {
                    368: #if 0
                    369:                if ( !(i % 1000) )
                    370:                        fprintf(stderr,"i=%d\n",i);
                    371: #endif
                    372:                for ( j = 0; j < 20; j++ )
                    373:                        win[j] = (i&(1<<j)) ? 2*j+1 : 2*j;
                    374:                if ( dtestmain(g,csum,wlist,20,win,&factor,&cofactor) ) {
                    375: #if 0
                    376:                        fprintf(stderr,"success : i=%d\n",i);
                    377: #endif
                    378:                        *pr = factor; return;
                    379:                }
                    380:        }
                    381: }
                    382:
                    383: void hensel_special(index,count,f,mfl,listp)
                    384: int index,count;
                    385: P f;
                    386: P *mfl;
                    387: ML *listp;
                    388: {
                    389:        register int i,j;
                    390:        int q,n,t,d,r,u,br,tmp,bound;
                    391:        int *c,*p,*m,*w;
                    392:        int **pp;
                    393:        DCP dc;
                    394:        ML blist,clist,bqlist,cqlist,rlist;
                    395:        UM *b;
                    396:        LUM fl,tl;
                    397:        LUM *l;
                    398:
                    399:        blist = MLALLOC(40); blist->n = 40; blist->mod = 11;
                    400:        for ( i = 0; i < 40; i++ ) {
                    401:                blist->c[i] = (pointer)UMALLOC(6);
                    402:                ptoum(11,mfl[i],blist->c[i]);
                    403:        }
                    404:        gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    405:        n = bqlist->n; q = bqlist->mod;
                    406:        bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    407:        if ( bound == 1 ) {
                    408:                *listp = rlist = MLALLOC(n);
                    409:                rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    410:                for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    411:                        tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    412:                        for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    413:                                        pp[j][0] = p[j];
                    414:                }
                    415:        } else {
                    416:                W_LUMALLOC(UDEG(f),bound,fl);
                    417:                ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    418:        }
                    419: }
                    420: #endif
                    421:
                    422: #if 0
                    423: void Pftest(arg,rp)
                    424: NODE arg;
                    425: P *rp;
                    426: {
                    427:        ML list;
                    428:        DCP dc;
                    429:        P p;
                    430:        P *mfl;
                    431:
                    432:        p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
                    433:        hensel_special(2,1,p,mfl,&list);
                    434:        dtest_special(p,list,rp);
                    435: }
                    436:
                    437: void dtest_special(f,list,pr)
                    438: P f;
                    439: ML list;
                    440: P *pr;
                    441: {
                    442:        int n,np,bound,q;
                    443:        int i,j,k,t,b0;
                    444:        int *win;
                    445:        P g,factor,cofactor;
                    446:        Q csum,csumt;
                    447:        DCP dc,dcf,dcf0;
                    448:        LUM *c;
                    449:        ML wlist;
                    450:        static int nbits[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
                    451:
                    452:        n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    453:        win = W_ALLOC(np+1);
                    454:        ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    455:        wlist = W_MLALLOC(np); wlist->n = list->n;
                    456:        wlist->mod = list->mod; wlist->bound = list->bound;
                    457:        c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    458:        for ( g = f, i = 0; i < (1<<23); i++ ) {
                    459: #if 0
                    460:                if ( !(i % 1000) )
                    461:                fprintf(stderr,"i=%d\n",i);
                    462: #endif
                    463:                t = i>>20; b0 = nbits[t];
                    464:                if ( !b0 )
                    465:                        continue;
                    466:                for ( j = 1; j < 6; j++ ) {
                    467:                        t = (i>>(20-4*j))&0xf;
                    468:                        if ( nbits[t] != b0 )
                    469:                                break;
                    470:                }
                    471:                if ( j != 6 )
                    472:                        continue;
                    473:                for ( j = k = 0; j < 24; j++ )
                    474:                        if ( i & (1<<(23-j)) )
                    475:                                win[k++] = j;
                    476:                if ( dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
                    477: #if 0
                    478:                        fprintf(stderr,"success : i=%d\n",i);
                    479: #endif
                    480:                        *pr = factor; return;
                    481:                }
                    482:        }
                    483:        *pr = f;
                    484: }
                    485:
                    486: void hensel_special(index,count,f,mfl,listp)
                    487: int index,count;
                    488: P f;
                    489: P *mfl;
                    490: ML *listp;
                    491: {
                    492:        register int i,j;
                    493:        int q,n,t,d,r,u,br,tmp,bound;
                    494:        int *c,*p,*m,*w;
                    495:        int **pp;
                    496:        DCP dc;
                    497:        ML blist,clist,bqlist,cqlist,rlist;
                    498:        UM *b;
                    499:        LUM fl,tl;
                    500:        LUM *l;
                    501:
                    502:        blist = MLALLOC(24); blist->n = 24; blist->mod = 5;
                    503:        for ( i = 0; i < 24; i++ ) {
                    504:                blist->c[i] = (pointer)UMALLOC(7);
                    505:                ptoum(5,mfl[i],blist->c[i]);
                    506:        }
                    507:        gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    508:        n = bqlist->n; q = bqlist->mod;
                    509:        bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    510:        if ( bound == 1 ) {
                    511:                *listp = rlist = MLALLOC(n);
                    512:                rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    513:                for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    514:                        tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    515:                        for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    516:                                        pp[j][0] = p[j];
                    517:                }
                    518:        } else {
                    519:                W_LUMALLOC(UDEG(f),bound,fl);
                    520:                ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    521:        }
                    522: }
                    523: #endif
                    524:
                    525: void Pftest(arg,rp)
                    526: NODE arg;
                    527: P *rp;
                    528: {
                    529:        ML list;
                    530:        P p;
                    531:        P *mfl;
                    532:
                    533:        p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
                    534:        hensel_special(5,1,p,mfl,&list);
                    535:        dtest_special(p,list,rp);
                    536: }
                    537:
                    538: int nbits(a)
                    539: int a;
                    540: {
                    541:        int i,s;
                    542:
                    543:        for ( i = 0, s = 0; a && (i < 20); i++, a >>= 1 )
                    544:                if ( a & 1 ) s++;
                    545:        return s;
                    546: }
                    547:
                    548: void dtest_special(f,list,pr)
                    549: P f;
                    550: ML list;
                    551: P *pr;
                    552: {
                    553:        int n,np,bound,q;
                    554:        int i,j,k,b0;
                    555:        int *win;
                    556:        P g,factor,cofactor;
                    557:        Q csum,csumt;
                    558:        LUM *c;
                    559:        ML wlist;
                    560:
                    561:        n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    562:        win = W_ALLOC(np+1);
                    563:        ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    564:        wlist = W_MLALLOC(np); wlist->n = list->n;
                    565:        wlist->mod = list->mod; wlist->bound = list->bound;
                    566:        c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    567:        for ( g = f, i = 0; i < (1<<19); i++ ) {
                    568: #if 0
                    569:                if ( !(i % 10000) )
                    570:                fprintf(stderr,"i=%d\n",i);
                    571: #endif
                    572:                b0 = nbits(i>>10);
                    573:                if ( !b0 || (nbits(i&0x3ff) != b0) )
                    574:                        continue;
                    575:                for ( j = k = 0; j < 20; j++ )
                    576:                        if ( i & (1<<(19-j)) )
                    577:                                win[k++] = j;
                    578:                if ( dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
                    579: #if 0
                    580:                        fprintf(stderr,"success : i=%d\n",i);
                    581: #endif
                    582:                        *pr = factor; return;
                    583:                }
                    584:        }
                    585:        *pr = f;
                    586: }
                    587:
                    588: void hensel_special(index,count,f,mfl,listp)
                    589: int index,count;
                    590: P f;
                    591: P *mfl;
                    592: ML *listp;
                    593: {
                    594:        register int i,j;
                    595:        int q,n,bound;
                    596:        int *p;
                    597:        int **pp;
                    598:        ML blist,clist,bqlist,cqlist,rlist;
                    599:        UM *b;
                    600:        LUM fl,tl;
                    601:        LUM *l;
                    602:
                    603:        blist = MLALLOC(20); blist->n = 20; blist->mod = 11;
                    604:        for ( i = 0; i < 20; i++ ) {
                    605:                blist->c[i] = (pointer)UMALLOC(10);
                    606:                ptoum(11,mfl[i],blist->c[i]);
                    607:        }
                    608:        gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    609:        n = bqlist->n; q = bqlist->mod;
                    610:        bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    611:        if ( bound == 1 ) {
                    612:                *listp = rlist = MLALLOC(n);
                    613:                rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    614:                for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    615:                        tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    616:                        for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    617:                                        pp[j][0] = p[j];
                    618:                }
                    619:        } else {
                    620:                W_LUMALLOC((int)UDEG(f),bound,fl);
                    621:                ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    622:        }
                    623: }
                    624:
                    625: void Pnullspace(arg,rp)
                    626: NODE arg;
                    627: LIST *rp;
                    628: {
                    629:        int i,j,n,mod;
                    630:        MAT mat,r;
                    631:        VECT u;
                    632:        V v;
                    633:        P p,z;
                    634:        Q q;
                    635:        UM **w;
                    636:        UM mp;
                    637:        P *t;
                    638:        UM *s;
                    639:        int *ind;
                    640:        NODE n0,n1;
                    641:
                    642:        mat = (MAT)ARG0(arg);
                    643:        p = (P)ARG1(arg);
                    644:        v = VR(p);
                    645:        mod = QTOS((Q)ARG2(arg));
                    646:        n = mat->row;
                    647:        w = (UM **)almat_pointer(n,n);
                    648:        for ( i = 0; i < n; i++ )
                    649:                for ( j = 0, t = (P *)mat->body[i], s = w[i]; j < n; j++ ) {
                    650:                        ptomp(mod,t[j],&z);
                    651:                        s[j] = W_UMALLOC((z&&!NUM(z))?UDEG(z):0);
                    652:                        mptoum(z,s[j]);
                    653:                }
                    654:        mp = W_UMALLOC(UDEG(p)); ptoum(mod,p,mp);
                    655:        ind = (int *)ALLOCA(n*sizeof(int));
                    656:        nullspace(w,mp,mod,n,ind);
                    657:        MKMAT(r,n,n);
                    658:        for ( i = 0; i < n; i++ )
                    659:                for ( j = 0, t = (P *)r->body[i], s = w[i]; j < n; j++ )
                    660:                        umtop(v,s[j],&t[j]);
                    661:        MKVECT(u,n);
                    662:        for ( i = 0; i < n; i++ ) {
                    663:                STOQ(ind[i],q); u->body[i] = (pointer)q;
                    664:        }
                    665:        MKNODE(n1,u,0); MKNODE(n0,r,n1); MKLIST(*rp,n0);
                    666: }
                    667:
                    668: void nullspace(mat,p,mod,n,ind)
                    669: UM **mat;
                    670: UM p;
                    671: int mod,n;
                    672: int *ind;
                    673: {
                    674:        int i,j,l,s,d;
                    675:        UM q,w,w1,h,inv;
                    676:        UM *t,*u;
                    677:
                    678:        d = DEG(p); inv = W_UMALLOC(d); q = W_UMALLOC(2*d);
                    679:        w = W_UMALLOC(2*d); w1 = W_UMALLOC(2*d); h = W_UMALLOC(d);
                    680:        bzero(ind,n*sizeof(int));
                    681:        ind[0] = 0;
                    682:        for ( i = j = 0; j < n; i++, j++ ) {
                    683:                for ( ; j < n; j++ ) {
                    684:                        for ( l = i; l < n; l++ )
                    685:                                if ( DEG(mat[l][j])>=0 )
                    686:                                        break;
                    687:                        if ( l < n ) {
                    688:                                t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    689:                        } else
                    690:                                ind[j] = 1;
                    691:                }
                    692:                if ( j == n )
                    693:                        break;
                    694:                invum(mod,p,mat[i][j],inv);
                    695:                for ( s = j, t = mat[i]; s < n; s++ ) {
                    696:                        mulum(mod,t[s],inv,w);
                    697:                        DEG(w) = divum(mod,w,p,q);
                    698:                        cpyum(w,t[s]);
                    699:                }
                    700:                for ( l = 0; l < n; l++ ) {
                    701:                        if ( l == i )
                    702:                                continue;
                    703:                        u = mat[l]; DEG(w) = -1; subum(mod,w,u[j],h);
                    704:                        for ( s = j; s < n; s++ ) {
                    705:                                mulum(mod,h,t[s],w); addum(mod,w,u[s],w1);
                    706:                                DEG(w1) = divum(mod,w1,p,q); cpyum(w1,u[s]);
                    707:                        }
                    708:                }
                    709:        }
                    710: }
                    711:
                    712: void Pnullspace_ff(arg,rp)
                    713: NODE arg;
                    714: LIST *rp;
                    715: {
                    716:        int i,j,n;
                    717:        Q mod;
                    718:        MAT mat,r;
                    719:        VECT u;
                    720:        Q q;
                    721:        Obj **w;
                    722:        Obj *t;
                    723:        Obj *s;
                    724:        int *ind;
                    725:        NODE n0,n1;
                    726:
                    727:        mat = (MAT)ARG0(arg);
                    728:        n = mat->row;
                    729:        w = (Obj **)almat_pointer(n,n);
                    730:        for ( i = 0; i < n; i++ )
                    731:                for ( j = 0, t = (Obj *)mat->body[i], s = w[i]; j < n; j++ )
                    732:                        s[j] = t[j];
                    733:        ind = (int *)ALLOCA(n*sizeof(int));
                    734:        switch ( current_ff ) {
                    735:                case FF_GFP:
                    736:                        nullspace_lm((LM **)w,n,ind); break;
                    737:                case FF_GF2N:
                    738:                        nullspace_gf2n((GF2N **)w,n,ind); break;
                    739:                case FF_GFPN:
                    740:                        nullspace_gfpn((GFPN **)w,n,ind); break;
                    741:                default:
                    742:                        error("nullspace_ff : current_ff is not set");
                    743:        }
                    744:        MKMAT(r,n,n);
                    745:        for ( i = 0; i < n; i++ )
                    746:                for ( j = 0, t = (Obj *)r->body[i], s = w[i]; j < n; j++ )
                    747:                        t[j] = s[j];
                    748:        MKVECT(u,n);
                    749:        for ( i = 0; i < n; i++ ) {
                    750:                STOQ(ind[i],q); u->body[i] = (pointer)q;
                    751:        }
                    752:        MKNODE(n1,u,0); MKNODE(n0,r,n1); MKLIST(*rp,n0);
                    753: }
                    754:
                    755: void nullspace_lm(mat,n,ind)
                    756: LM **mat;
                    757: int n;
                    758: int *ind;
                    759: {
                    760:        int i,j,l,s;
                    761:        Q q,mod;
                    762:        N lm;
                    763:        LM w,w1,h,inv;
                    764:        LM *t,*u;
                    765:
                    766:        getmod_lm(&lm); NTOQ(lm,1,mod);
                    767:
                    768:        bzero(ind,n*sizeof(int));
                    769:        ind[0] = 0;
                    770:        for ( i = j = 0; j < n; i++, j++ ) {
                    771:                for ( ; j < n; j++ ) {
                    772:                        for ( l = i; l < n; l++ ) {
                    773:                                simplm(mat[l][j],&w); mat[l][j] = w;
                    774:                                if ( mat[l][j] )
                    775:                                        break;
                    776:                        }
                    777:                        if ( l < n ) {
                    778:                                t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    779:                        } else
                    780:                                ind[j] = 1;
                    781:                }
                    782:                if ( j == n )
                    783:                        break;
                    784:                NTOQ(mat[i][j]->body,1,q); invl(q,mod,(Q *)&inv);
                    785:                for ( s = j, t = mat[i]; s < n; s++ ) {
                    786:                        mullm(t[s],inv,&w); t[s] = w;
                    787:                }
                    788:                for ( l = 0; l < n; l++ ) {
                    789:                        if ( l == i )
                    790:                                continue;
                    791:                        u = mat[l]; chsgnlm(u[j],&h);
                    792:                        for ( s = j; s < n; s++ ) {
                    793:                                mullm(h,t[s],&w); addlm(w,u[s],&w1); u[s] = w1;
                    794:                        }
                    795:                }
                    796:        }
                    797: }
                    798:
                    799: void nullspace_gf2n(mat,n,ind)
                    800: GF2N **mat;
                    801: int n;
                    802: int *ind;
                    803: {
                    804:        int i,j,l,s;
                    805:        GF2N w,w1,h,inv;
                    806:        GF2N *t,*u;
                    807:        extern gf2n_lazy;
                    808:
                    809:        bzero(ind,n*sizeof(int));
                    810:        ind[0] = 0;
                    811:        for ( i = j = 0; j < n; i++, j++ ) {
                    812:                for ( ; j < n; j++ ) {
                    813:                        for ( l = i; l < n; l++ ) {
                    814:                                simpgf2n(mat[l][j],&w); mat[l][j] = w;
                    815:                                if ( mat[l][j] )
                    816:                                        break;
                    817:                        }
                    818:                        if ( l < n ) {
                    819:                                t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    820:                        } else
                    821:                                ind[j] = 1;
                    822:                }
                    823:                if ( j == n )
                    824:                        break;
                    825:                invgf2n(mat[i][j],&inv);
                    826:                for ( s = j, t = mat[i]; s < n; s++ ) {
                    827:                        mulgf2n(t[s],inv,&w); t[s] = w;
                    828:                }
                    829:                for ( l = 0; l < n; l++ ) {
                    830:                        if ( l == i )
                    831:                                continue;
                    832:                        u = mat[l]; h = u[j];
                    833:                        for ( s = j; s < n; s++ ) {
                    834:                                mulgf2n(h,t[s],&w); addgf2n(w,u[s],&w1); u[s] = w1;
                    835:                        }
                    836:                }
                    837:        }
                    838: }
                    839:
                    840: void nullspace_gfpn(mat,n,ind)
                    841: GFPN **mat;
                    842: int n;
                    843: int *ind;
                    844: {
                    845:        int i,j,l,s;
                    846:        GFPN w,w1,h,inv;
                    847:        GFPN *t,*u;
                    848:
                    849:        bzero(ind,n*sizeof(int));
                    850:        ind[0] = 0;
                    851:        for ( i = j = 0; j < n; i++, j++ ) {
                    852:                for ( ; j < n; j++ ) {
                    853:                        for ( l = i; l < n; l++ ) {
                    854:                                simpgfpn(mat[l][j],&w); mat[l][j] = w;
                    855:                                if ( mat[l][j] )
                    856:                                        break;
                    857:                        }
                    858:                        if ( l < n ) {
                    859:                                t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    860:                        } else
                    861:                                ind[j] = 1;
                    862:                }
                    863:                if ( j == n )
                    864:                        break;
                    865:                divgfpn((GFPN)ONE,(GFPN)mat[i][j],&inv);
                    866:                for ( s = j, t = mat[i]; s < n; s++ ) {
                    867:                        mulgfpn(t[s],inv,&w); t[s] = w;
                    868:                }
                    869:                for ( l = 0; l < n; l++ ) {
                    870:                        if ( l == i )
                    871:                                continue;
                    872:                        u = mat[l]; chsgngfpn(u[j],&h);
                    873:                        for ( s = j; s < n; s++ ) {
                    874:                                mulgfpn(h,t[s],&w); addgfpn(w,u[s],&w1); u[s] = w1;
                    875:                        }
                    876:                }
                    877:        }
                    878: }
                    879: /* p = a(0)vl[0]+a(1)vl[1]+...+a(m-1)vl[m-1]+a(m) -> array = [a(0) a(1) ... a(m)] */
                    880:
                    881: void linear_form_to_array(p,vl,m,array)
                    882: P p;
                    883: VL vl;
                    884: int m;
                    885: Num *array;
                    886: {
                    887:        int i;
                    888:        DCP dc;
                    889:
                    890:        bzero((char *)array,(m+1)*sizeof(Num *));
                    891:        for ( i = 0; p && vl; vl = NEXT(vl), i++ ) {
                    892:                if ( ID(p) == O_N )
                    893:                        break;
                    894:                else if ( VR(p) == vl->v ) {
                    895:                        dc = DC(p);
                    896:                        array[i] = (Num)COEF(dc);
                    897:                        dc = NEXT(dc);
                    898:                        p = dc ? COEF(dc) : 0;
                    899:                }
                    900:        }
                    901:        array[m] = (Num)p;
                    902: }
                    903:
                    904: void array_to_linear_form(array,vl,m,r)
                    905: Num *array;
                    906: VL vl;
                    907: int m;
                    908: P *r;
                    909: {
                    910:        P t;
                    911:        DCP dc0,dc1;
                    912:
                    913:        if ( !m )
                    914:                *r = (P)array[0];
                    915:        else {
                    916:                array_to_linear_form(array+1,NEXT(vl),m-1,&t);
                    917:                if ( !array[0] )
                    918:                        *r = t;
                    919:                else {
                    920:                        NEWDC(dc0); DEG(dc0) = ONE; COEF(dc0) = (P)array[0];
                    921:                        if ( !t )
                    922:                                NEXT(dc0) = 0;
                    923:                        else {
                    924:                                NEWDC(dc1); DEG(dc1) = 0; COEF(dc1) = t;
                    925:                                NEXT(dc1) = 0;
                    926:                                NEXT(dc0) = dc1;
                    927:                        }
                    928:                        MKP(vl->v,dc0,*r);
                    929:                }
                    930:        }
                    931: }
                    932:
                    933: void Psolve_linear_equation_gf2n(arg,rp)
                    934: NODE arg;
                    935: LIST *rp;
                    936: {
                    937:        NODE eqs,tn;
                    938:        VL vars,tvl;
                    939:        int i,j,n,m,dim,codim;
                    940:        GF2N **w;
                    941:        int *ind;
                    942:        NODE n0,n1;
                    943:
                    944:        get_vars(ARG0(arg),&vars);
                    945:        eqs = BDY((LIST)ARG0(arg));
                    946:        for ( n = 0, tn = eqs; tn; tn = NEXT(tn), n++);
                    947:        for ( m = 0, tvl = vars; tvl; tvl = NEXT(tvl), m++);
                    948:        w = (GF2N **)almat_pointer(n,m+1);
                    949:        for ( i = 0, tn = eqs; i < n; i++, tn = NEXT(tn) )
                    950:                linear_form_to_array(BDY(tn),vars,m,(Num *)w[i]);
                    951:        ind = (int *)ALLOCA(m*sizeof(int));
                    952:        solve_linear_equation_gf2n(w,n,m,ind);
                    953:        for ( j = 0, dim = 0; j < m; j++ )
                    954:                if ( ind[j] )
                    955:                        dim++;
                    956:        codim = m-dim;
                    957:        for ( i = codim; i < n; i++ )
                    958:                if ( w[i][m] ) {
                    959:                        MKLIST(*rp,0); return;
                    960:                }
                    961:        for ( i = 0, n0 = 0; i < codim; i++ ) {
                    962:                NEXTNODE(n0,n1);
                    963:                array_to_linear_form((Num *)w[i],vars,m,(P *)&BDY(n1));
                    964:        }
                    965:        if ( n0 )
                    966:                NEXT(n1) = 0;
                    967:        MKLIST(*rp,n0);
                    968: }
                    969:
                    970: void solve_linear_equation_gf2n(mat,n,m,ind)
                    971: GF2N **mat;
                    972: int n;
                    973: int *ind;
                    974: {
                    975:        int i,j,l,s;
                    976:        GF2N w,w1,h,inv;
                    977:        GF2N *t,*u;
                    978:        extern gf2n_lazy;
                    979:
                    980:        bzero(ind,m*sizeof(int));
                    981:        ind[0] = 0;
                    982:        for ( i = j = 0; j < m; i++, j++ ) {
                    983:                for ( ; j < m; j++ ) {
                    984:                        for ( l = i; l < n; l++ ) {
                    985:                                simpgf2n(mat[l][j],&w); mat[l][j] = w;
                    986:                                if ( mat[l][j] )
                    987:                                        break;
                    988:                        }
                    989:                        if ( l < n ) {
                    990:                                t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    991:                        } else
                    992:                                ind[j] = 1;
                    993:                }
                    994:                if ( j == m )
                    995:                        break;
                    996:                invgf2n(mat[i][j],&inv);
                    997:                for ( s = j, t = mat[i]; s <= m; s++ ) {
                    998:                        mulgf2n(t[s],inv,&w); t[s] = w;
                    999:                }
                   1000:                for ( l = 0; l < n; l++ ) {
                   1001:                        if ( l == i )
                   1002:                                continue;
                   1003:                        u = mat[l]; h = u[j];
                   1004:                        for ( s = j; s <= m; s++ ) {
                   1005:                                mulgf2n(h,t[s],&w); addgf2n(w,u[s],&w1); u[s] = w1;
                   1006:                        }
                   1007:                }
                   1008:        }
                   1009: }
                   1010:
                   1011: /*
                   1012: void null_to_sol(mat,ind,mod,n,r)
                   1013: int **mat;
                   1014: int *ind;
                   1015: int mod,n;
                   1016: UM *r;
                   1017: {
                   1018:        int i,j,k,l;
                   1019:        int *c;
                   1020:        UM w;
                   1021:
                   1022:        for ( i = 0, l = 0; i < n; i++ ) {
                   1023:                if ( !ind[i] )
                   1024:                        continue;
                   1025:                w = UMALLOC(n);
                   1026:                for ( j = k = 0, c = COEF(w); j < n; j++ )
                   1027:                        if ( ind[j] )
                   1028:                                c[j] = 0;
                   1029:                        else
                   1030:                                c[j] = mat[k++][i];
                   1031:                c[i] = mod-1;
                   1032:                for ( j = n; j >= 0; j-- )
                   1033:                        if ( c[j] )
                   1034:                                break;
                   1035:                DEG(w) = j;
                   1036:                r[l++] = w;
                   1037:        }
                   1038: }
                   1039: */
                   1040:
                   1041: void showgfmat(mat,n)
                   1042: UM **mat;
                   1043: int n;
                   1044: {
                   1045:        int i,j,k;
                   1046:        int *c;
                   1047:        UM p;
                   1048:
                   1049:        for ( i = 0; i < n; i++ ) {
                   1050:                for ( j = 0; j < n; j++ ) {
                   1051:                        p = mat[i][j];
                   1052:                        if ( DEG(p) < 0 )
                   1053:                                fprintf(asir_out,"0");
                   1054:                        else
                   1055:                                for ( p = mat[i][j], k = DEG(p), c = COEF(p); k >= 0; k-- ) {
                   1056:                                        if ( c[k] )
                   1057:                                                fprintf(asir_out,"+%d",c[k]);
                   1058:                                        if ( k > 1 )
                   1059:                                                fprintf(asir_out,"a^%d",k);
                   1060:                                        else if ( k == 1 )
                   1061:                                                fprintf(asir_out,"a",k);
                   1062:                                }
                   1063:                        fprintf(asir_out," ");
                   1064:                }
                   1065:                fprintf(asir_out,"\n");
                   1066:        }
                   1067: }
                   1068:
                   1069: #if 0
                   1070: void Pgcda_mod(arg,rp)
                   1071: NODE arg;
                   1072: P *rp;
                   1073: {
                   1074:        p1 = (P)ARG0(arg);
                   1075:        p2 = (P)ARG1(arg);
                   1076:        v = VR((P)ARG2(arg));
                   1077:        d = (P)ARG3(arg);
                   1078:        m = QTOS((Q)ARG4(arg));
                   1079:        reordvar(CO,v,&vl);
                   1080:        reorderp(vl,CO,p1,&t); ptomp(m,t,&m1);
                   1081:        reorderp(vl,CO,p2,&t); ptomp(m,t,&m2);
                   1082:        if ( NUM(m1) || NUM(m2) || VR(m1) != v || VR(m2) != v ) {
                   1083:                *rp = ONE; return;
                   1084:        }
                   1085:        if ( deg(v,m1) >= deg(v,m2) ) {
                   1086:                t = m1; m1 = m2; m2 = t;
                   1087:        }
                   1088:        while ( 1 ) {
                   1089:                inva_mod(COEF(DC(m2)),d,m,&inv);
                   1090:                NEWDC(dc); NEXT(dc) = 0; MKP(v,dc,h);
                   1091:                d0 = deg(v,m1)-deg(v,m2); STOQ(d0,DEG(dc));
                   1092:                mulgq(m,d,inv,COEF(DC(m1)),&COEF(dc));
                   1093:                mulgp(vl,m,d,m2,h,&t); subgp(vl,m,d,m1,t,&s);
                   1094:        }
                   1095: }
                   1096: #endif
                   1097:
                   1098: void Ppwr_mod(arg,rp)
                   1099: NODE arg;
                   1100: P *rp;
                   1101: {
                   1102:        P p,a,d,r;
                   1103:        int m;
                   1104:        Q q;
                   1105:        N n;
                   1106:
                   1107:        m = QTOS((Q)ARG4(arg)); q = (Q)ARG5(arg); n = q ? NM(q) : 0;
                   1108:        ptomp(m,(P)ARG0(arg),&p); ptomp(m,(P)ARG1(arg),&a);
                   1109:        ptomp(m,(P)ARG3(arg),&d);
                   1110:        pwr_mod(p,a,VR((P)ARG2(arg)),d,m,n,&r);
                   1111:        mptop(r,rp);
                   1112: }
                   1113:
                   1114: void pwr_mod(p,a,v,d,m,n,rp)
                   1115: P p,a,d;
                   1116: V v;
                   1117: int m;
                   1118: N n;
                   1119: P *rp;
                   1120: {
                   1121:        int b;
                   1122:        P t,s,r;
                   1123:        N n1;
                   1124:
                   1125:        if ( !n )
                   1126:                *rp = (P)ONEM;
                   1127:        else if ( UNIN(n) )
                   1128:                *rp = p;
                   1129:        else {
                   1130:                b = divin(n,2,&n1);
                   1131:                pwr_mod(p,a,v,d,m,n1,&t);
                   1132:                mulmp(CO,m,t,t,&s); rem_mod(s,a,v,d,m,&r);
                   1133:                if ( b ) {
                   1134:                        mulmp(CO,m,r,p,&t); rem_mod(t,a,v,d,m,rp);
                   1135:                } else
                   1136:                        *rp = r;
                   1137:        }
                   1138: }
                   1139:
                   1140: void rem_mod(p,a,v,d,m,rp)
                   1141: P p,a,d;
                   1142: V v;
                   1143: int m;
                   1144: P *rp;
                   1145: {
                   1146:        P tmp,r1,r2;
                   1147:
                   1148:        divsrmp(CO,m,p,d,&tmp,&r1);
                   1149:        divsrmp(CO,m,r1,a,&tmp,&r2);
                   1150:        divsrmp(CO,m,r2,d,&tmp,rp);
                   1151: }

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