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

Annotation of OpenXM_contrib2/asir2018/builtin/gf.c, Revision 1.3

1.1       noro        1: /*
                      2:  * Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
                      3:  * All rights reserved.
                      4:  *
                      5:  * FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
                      6:  * non-exclusive and royalty-free license to use, copy, modify and
                      7:  * redistribute, solely for non-commercial and non-profit purposes, the
                      8:  * computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
                      9:  * conditions of this Agreement. For the avoidance of doubt, you acquire
                     10:  * only a limited right to use the SOFTWARE hereunder, and FLL or any
                     11:  * third party developer retains all rights, including but not limited to
                     12:  * copyrights, in and to the SOFTWARE.
                     13:  *
                     14:  * (1) FLL does not grant you a license in any way for commercial
                     15:  * purposes. You may use the SOFTWARE only for non-commercial and
                     16:  * non-profit purposes only, such as academic, research and internal
                     17:  * business use.
                     18:  * (2) The SOFTWARE is protected by the Copyright Law of Japan and
                     19:  * international copyright treaties. If you make copies of the SOFTWARE,
                     20:  * with or without modification, as permitted hereunder, you shall affix
                     21:  * to all such copies of the SOFTWARE the above copyright notice.
                     22:  * (3) An explicit reference to this SOFTWARE and its copyright owner
                     23:  * shall be made on your publication or presentation in any form of the
                     24:  * results obtained by use of the SOFTWARE.
                     25:  * (4) In the event that you modify the SOFTWARE, you shall notify FLL by
                     26:  * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
                     27:  * for such modification or the source code of the modified part of the
                     28:  * SOFTWARE.
                     29:  *
                     30:  * THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
                     31:  * MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
                     32:  * EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
                     33:  * FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
                     34:  * RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
                     35:  * MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
                     36:  * UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
                     37:  * OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
                     38:  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
                     39:  * DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
                     40:  * ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
                     41:  * FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
                     42:  * DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
                     43:  * SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
                     44:  * OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
                     45:  * DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
                     46:  * PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
                     47:  *
1.3     ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2018/builtin/gf.c,v 1.2 2018/09/28 08:20:27 noro Exp $
1.1       noro       49: */
                     50: #include "ca.h"
                     51: #include "parse.h"
                     52:
                     53: struct resf_dlist {
                     54:   int ib,id;
                     55: };
                     56:
                     57: int resf_degtest(int,int *,int,struct resf_dlist *);
                     58: void uhensel(P,NODE,int,int,NODE *);
                     59: void uhensel_incremental(P,NODE,int,int,int,NODE *);
                     60: void resf_hensel(int,P,int,P *,ML *);
                     61: void resf_dtest(P,ML,int,int *,int *,DCP *);
                     62: void resf_dtest_special(P,ML,int,int *,int *,DCP *);
                     63: void dtest_special(P,ML,P *);
                     64: void hensel_special(int,int,P,P *,ML *);
                     65:
                     66: void nullspace(UM **,UM,int,int,int *);
                     67: void nullspace_lm(LM **,int,int *);
                     68: void nullspace_gf2n(GF2N **,int,int *);
                     69: void nullspace_gfpn(GFPN **,int,int *);
                     70: void nullspace_gfs(GFS **,int,int *);
                     71: void nullspace_gfsn(GFSN **,int,int *);
                     72: void null_to_sol(int **,int *,int,int,UM *);
                     73:
                     74: void showgfmat(UM **,int);
                     75: void pwr_mod(P,P,V,P,int,Z,P *);
                     76: void rem_mod(P,P,V,P,int,P *);
                     77:
                     78: void Pnullspace(),Pgcda_mod(),Pftest(),Presfmain(),Ppwr_mod(),Puhensel();
                     79: void Puhensel_incremental();
                     80: void Psfuhensel();
                     81:
                     82: void Pnullspace_ff();
                     83:
                     84: void Psolve_linear_equation_gf2n();
                     85: void Plinear_form_to_vect(),Pvect_to_linear_form();
                     86:
                     87: void solve_linear_equation_gf2n(GF2N **,int,int,int *);
                     88: void linear_form_to_array(P,VL,int,Num *);
                     89: void array_to_linear_form(Num *,VL,int,P *);
                     90: void sfuhensel(P,NODE,GFS,int,NODE *);
                     91:
                     92: extern int current_ff;
                     93:
                     94: struct ftab gf_tab[] = {
                     95:   {"solve_linear_equation_gf2n",Psolve_linear_equation_gf2n,1},
                     96:   {"nullspace",Pnullspace,3},
                     97:   {"nullspace_ff",Pnullspace_ff,1},
                     98: /*  {"gcda_mod",Pgcda_mod,5}, */
                     99:   {"ftest",Pftest,2},
                    100:   {"resfmain",Presfmain,4},
                    101:   {"pwr_mod",Ppwr_mod,6},
                    102:   {"uhensel",Puhensel,4},
                    103:   {"uhensel_incremental",Puhensel_incremental,5},
                    104:   {"sfuhensel",Psfuhensel,4},
                    105:   {0,0,0},
                    106: };
                    107:
                    108: int resf_degtest(int k,int *in,int nb,struct resf_dlist *dlist)
                    109: {
                    110:   int i,d0,d;
                    111:   int dl_i;
                    112:   struct resf_dlist *t;
                    113:
                    114:   if ( k < nb )
                    115:     return 0;
                    116:   if ( nb == 1 )
                    117:     return 1;
                    118:   d0 = 0; d = 0; dl_i = 0;
                    119:   for ( i = 0; i < k; i++ ) {
                    120:     t = &dlist[in[i]];
                    121:     if ( t->ib > dl_i + 1 )
                    122:       return 0;
                    123:     else if ( t->ib == dl_i )
                    124:       d += t->id;
                    125:     else if ( !d || (dl_i && d0 != d) )
                    126:       return 0;
                    127:     else {
                    128:       d0 = d; dl_i++; d = t->id;
                    129:     }
                    130:   }
                    131:   if ( dl_i != nb - 1 || d0 != d )
                    132:     return 0;
                    133:   else
                    134:     return 1;
                    135: }
                    136:
                    137: void Puhensel(NODE arg,LIST *rp)
                    138: {
                    139:   P f;
                    140:   NODE mfl,r;
                    141:   int mod,bound;
                    142:
                    143:   f = (P)ARG0(arg);
                    144:   mfl = BDY((LIST)ARG1(arg));
1.2       noro      145:   mod = ZTOS((Q)ARG2(arg));
                    146:   bound = ZTOS((Q)ARG3(arg));
1.1       noro      147:   uhensel(f,mfl,mod,bound,&r);
                    148:   MKLIST(*rp,r);
                    149: }
                    150:
                    151: void Puhensel_incremental(NODE arg,LIST *rp)
                    152: {
                    153:   P f;
                    154:   NODE mfl,r;
                    155:   int mod,bound,start;
                    156:
                    157:   f = (P)ARG0(arg);
                    158:   mfl = BDY((LIST)ARG1(arg));
1.2       noro      159:   mod = ZTOS((Q)ARG2(arg));
                    160:   start = ZTOS((Q)ARG3(arg));
                    161:   bound = ZTOS((Q)ARG4(arg));
1.1       noro      162:   uhensel_incremental(f,mfl,mod,start,bound,&r);
                    163:   MKLIST(*rp,r);
                    164: }
                    165:
                    166: void uhensel(P f,NODE mfl,int mod,int bound,NODE *rp)
                    167: {
                    168:   ML blist,clist,rlist;
                    169:   LUM fl;
                    170:   int nf,i;
                    171:   P s;
                    172:   V v;
                    173:   NODE t,top;
                    174:
                    175:   nf = length(mfl);
                    176:   blist = MLALLOC(nf); blist->n = nf; blist->mod = mod;
                    177:   for ( i = 0, t = mfl; i < nf; i++, t = NEXT(t) ) {
                    178:     blist->c[i] = (pointer)UMALLOC(UDEG((P)BDY(t)));
                    179:     ptoum(mod,(P)BDY(t),blist->c[i]);
                    180:   }
                    181:   gcdgen(f,blist,&clist);
                    182:   blist->bound = clist->bound = bound;
                    183:   W_LUMALLOC((int)UDEG(f),bound,fl);
                    184:   ptolum(mod,bound,f,fl);
                    185:   henmain(fl,blist,clist,&rlist);
                    186:   v = VR(f);
                    187:   for ( i = nf-1, top = 0; i >= 0; i-- ) {
                    188:     lumtop(v,mod,bound,rlist->c[i],&s);
                    189:     MKNODE(t,s,top); top = t;
                    190:   }
                    191:   *rp = top;
                    192: }
                    193:
                    194: void uhensel_incremental(P f,NODE mfl,int mod,int start,int bound,NODE *rp)
                    195: {
                    196:   ML blist,clist,rlist;
                    197:   LUM fl;
                    198:   LUM *lblist;
                    199:   int nf,i,j,k;
                    200:   int **p;
                    201:   P s;
                    202:   V v;
                    203:   NODE t,top;
                    204:
                    205:   nf = length(mfl);
                    206:   blist = MLALLOC(nf); blist->n = nf; blist->mod = mod;
                    207:   lblist = (LUM *)MALLOC(nf*sizeof(LUM));
                    208:   for ( i = 0, t = mfl; i < nf; i++, t = NEXT(t) ) {
                    209:     blist->c[i] = (pointer)UMALLOC(UDEG((P)BDY(t)));
                    210:     ptoum(mod,(P)BDY(t),blist->c[i]);
                    211:     W_LUMALLOC((int)UDEG((P)BDY(t)),bound,lblist[i]);
                    212:     ptolum(mod,start,(P)BDY(t),lblist[i]);
                    213:     p = lblist[i]->c;
                    214:     for ( j = DEG(lblist[i]); j >= 0; j-- )
                    215:       for ( k = start; k < bound; k++ )
                    216:         p[j][k] = 0;
                    217:   }
                    218:   gcdgen(f,blist,&clist);
                    219:   clist->bound = bound;
                    220:   W_LUMALLOC((int)UDEG(f),bound,fl);
                    221:   ptolum(mod,bound,f,fl);
                    222:   henmain_incremental(fl,lblist,clist,nf,mod,start,bound);
                    223:   v = VR(f);
                    224:   for ( i = nf-1, top = 0; i >= 0; i-- ) {
                    225:     lumtop_unsigned(v,mod,bound,lblist[i],&s);
                    226:     MKNODE(t,s,top); top = t;
                    227:   }
                    228:   *rp = top;
                    229: }
                    230:
                    231: void Psfuhensel(NODE arg,LIST *rp)
                    232: {
                    233:   P f;
                    234:   int bound;
                    235:   NODE r,mfl;
                    236:   GFS ev;
                    237:
                    238:   f = (P)ARG0(arg);
                    239:   mfl = BDY((LIST)ARG1(arg));
                    240:   ev = (GFS)ARG2(arg);
1.2       noro      241:   bound = ZTOS((Q)ARG3(arg));
1.1       noro      242:   sfuhensel(f,mfl,ev,bound,&r);
                    243:   MKLIST(*rp,r);
                    244: }
                    245:
                    246: void sfuhensel(P f,NODE mfl,GFS ev,int bound,NODE *rp)
                    247: {
                    248:   BM fl;
                    249:   BM *r;
                    250:   VL vl,nvl;
                    251:   int i,fn,dx,dy,d;
                    252:   NODE t,top;
                    253:   UM fm,hm,q;
                    254:   UM *gm;
                    255:   V x,y;
                    256:   P g,s,u;
                    257:
                    258:   clctv(CO,f,&vl);
                    259:   if ( !vl || !vl->next || vl->next->next )
                    260:     error("sfuhensel : f must be a bivariate poly");
                    261:
                    262:   for ( i = 0, t = mfl; t; i++, t = NEXT(t) );
                    263:   fn = i;
                    264:
                    265:   gm = (UM *)MALLOC(fn*sizeof(UM));
                    266:
                    267:   /* XXX : more severe check is necessary */
                    268:   x = VR((P)BDY(mfl));
                    269:   y = vl->v == x ? vl->next->v : vl->v;
                    270:
                    271:   for ( i = 0, t = mfl, d = 0; i < fn; i++, t = NEXT(t) ) {
                    272:     gm[i] = (pointer)UMALLOC(getdeg(x,(P)BDY(t)));
                    273:     ptosfum((P)BDY(t),gm[i]);
                    274:     d += DEG(gm[i]);
                    275:   }
                    276:
                    277:   /* reorder f if necessary */
                    278:   if ( vl->v != x ) {
                    279:     reordvar(vl,x,&nvl); reorderp(nvl,vl,f,&g);
                    280:     vl = nvl; f = g;
                    281:   }
                    282:   dx = getdeg(x,f);
                    283:   if ( dx != d )
                    284:     error("sfuhensel : product of factors has incompatible degree");
                    285:
                    286:   dy = getdeg(y,f);
                    287:   dy = MAX(dy,bound);
                    288:   fl = BMALLOC(dx,dy);
                    289:   ptosfbm(dy,f,fl);
                    290:   if ( ev ) shiftsfbm(fl,FTOIF(CONT(ev)));
                    291:
                    292:   /* fm = fl mod y */
                    293:   fm = W_UMALLOC(dx);
                    294:   cpyum(COEF(fl)[0],fm);
                    295:   hm = W_UMALLOC(dx);
                    296:
                    297:   q = W_UMALLOC(dx);
                    298:   r = (BM *)MLALLOC(fn*sizeof(BM));
                    299:   for ( i = 0; i < fn-1; i++ ) {
                    300:     /* fl = gm[i]*hm mod y */
                    301:     divsfum(fm,gm[i],hm);
                    302:     /* fl is replaced by the cofactor of gk mod y^bound */
                    303:     /* r[i] = gk */
                    304:     sfhenmain2(fl,gm[i],hm,bound,r+i);
                    305:     cpyum(hm,fm);
                    306:   }
                    307:   /* finally, fl must be the lift of gm[fn-1] */
                    308:   r[i] = fl;
                    309:
                    310:   for ( i = fn-1, top = 0; i >= 0; i-- ) {
                    311:     sfbmtop(r[i],x,y,&s);
                    312:     reorderp(CO,vl,s,&u);
                    313:     MKNODE(t,u,top); top = t;
                    314:   }
                    315:   *rp = top;
                    316: }
                    317:
                    318: void Presfmain(NODE arg,LIST *rp)
                    319: {
                    320:   P f;
                    321:   int mod,n,nb,i,j,k;
                    322:   int *nf,*md;
                    323:   P *mf;
                    324:   NODE mfl,mdl,t,s,u;
                    325:   ML list;
                    326:   DCP dc;
                    327:   int sflag;
                    328:
                    329:   f = (P)ARG0(arg);
1.2       noro      330:   mod = ZTOS((Q)ARG1(arg));
1.1       noro      331:   mfl = BDY((LIST)ARG2(arg));
                    332:   mdl = BDY((LIST)ARG3(arg));
                    333:   for ( n = nb = 0, t = mfl; t; nb++, t = NEXT(t) )
                    334:     for ( s = BDY((LIST)BDY(t)); s; n++, s = NEXT(s) );
                    335:   if ( n == nb ) {
                    336:     /* f must be irreducible! */
                    337:     NEWDC(dc);
                    338:     dc->c = f; dc->d = ONE;
                    339:   } else {
                    340:     nf = W_ALLOC(nb); md = W_ALLOC(nb); mf = (P *)ALLOCA(n*sizeof(P));
                    341:     for ( k = i = 0, t = mfl, u = mdl, sflag = 1; t;
                    342:       i++, t = NEXT(t), u = NEXT(u) ) {
                    343:       if ( sflag && length(BDY((LIST)BDY(t))) != 2 )
                    344:         sflag = 0;
                    345:       for ( j = 0, s = BDY((LIST)BDY(t)); s; j++, s = NEXT(s) )
                    346:         mf[k++] = (P)BDY(s);
1.2       noro      347:       nf[i] = j; md[i] = ZTOS((Q)BDY(u));
1.1       noro      348:     }
                    349:     resf_hensel(mod,f,n,mf,&list);
                    350:     if ( sflag )
                    351:       resf_dtest_special(f,list,nb,nf,md,&dc);
                    352:     else
                    353:       resf_dtest(f,list,nb,nf,md,&dc);
                    354:   }
                    355:   dcptolist(dc,rp);
                    356: }
                    357:
                    358: void resf_hensel(int mod,P f,int nf,P *mfl,ML *listp)
                    359: {
                    360:   register int i,j;
                    361:   int q,n,bound,inv,lc;
                    362:   int *p;
                    363:   int **pp;
                    364:   ML blist,clist,bqlist,cqlist,rlist;
                    365:   UM *b;
                    366:   LUM fl,tl;
                    367:   LUM *l;
                    368:   UM w;
                    369:
                    370:   w = W_UMALLOC(UDEG(f));
                    371:   blist = MLALLOC(nf); blist->n = nf; blist->mod = mod;
                    372:
                    373:   /* c[0] must have lc(f) */
                    374:   blist->c[0] = (pointer)UMALLOC(UDEG(mfl[0]));
                    375:   ptoum(mod,mfl[0],w);
                    376:   inv = invm(w->c[UDEG(mfl[0])],mod);
                    377:   lc = remqi((Q)LC(f),mod);
                    378:   lc = dmar(inv,lc,0,mod);
                    379:   if ( lc == 1 )
                    380:     copyum(w,blist->c[0]);
                    381:   else
                    382:     mulsum(mod,w,lc,blist->c[0]);
                    383:
                    384:   /* c[i] (i=1,...,nf-1) must be monic */
                    385:   for ( i = 1; i < nf; i++ ) {
                    386:     blist->c[i] = (pointer)UMALLOC(UDEG(mfl[i]));
                    387:     ptoum(mod,mfl[i],w);
                    388:     inv = invm(w->c[UDEG(mfl[i])],mod);
                    389:     if ( inv == 1 )
                    390:       copyum(w,blist->c[i]);
                    391:     else
                    392:       mulsum(mod,w,inv,blist->c[i]);
                    393:   }
                    394:
                    395:   gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    396:   n = bqlist->n; q = bqlist->mod;
                    397:   bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    398:   if ( bound == 1 ) {
                    399:     *listp = rlist = MLALLOC(n);
                    400:     rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    401:     for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    402:       tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    403:       for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    404:           pp[j][0] = p[j];
                    405:     }
                    406:   } else {
                    407:     W_LUMALLOC((int)UDEG(f),bound,fl);
                    408:     ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    409:   }
                    410: }
                    411:
                    412: void resf_dtest(P f,ML list,int nb,int *nfl,int *mdl,DCP *dcp)
                    413: {
                    414:   int n,np,bound,q;
                    415:   int i,j,k;
                    416:   int *win;
                    417:   P g,factor,cofactor;
                    418:   Q csum,csumt;
                    419:   DCP dcf,dcf0;
                    420:   LUM *c;
                    421:   ML wlist;
                    422:   struct resf_dlist *dlist;
                    423:   int z;
                    424:
                    425:   n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    426:   win = W_ALLOC(np+1);
                    427:   ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    428:   wlist = W_MLALLOC(np); wlist->n = list->n;
                    429:   wlist->mod = list->mod; wlist->bound = list->bound;
                    430:   c = (LUM *)COEF(wlist);
                    431:   bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    432:   dlist = (struct resf_dlist *)ALLOCA(np*sizeof(struct resf_dlist));
                    433:   for ( i = 0, j = 0; j < nb; j++ )
                    434:     for ( k = 0; k < nfl[j]; k++, i++ ) {
                    435:       dlist[i].ib = j; dlist[i].id = DEG(c[i])/mdl[j];
                    436:     }
                    437:   k = nb;
                    438:   for ( i = 0; i < nb; i++ )
                    439:     win[i] = i+1;
                    440:   for ( g = f, dcf = dcf0 = 0, --np, z = 0; ; ) {
                    441: #if 0
                    442:     if ( !(z++ % 10000) )
                    443:       fputc('.',stderr);
                    444: #endif
                    445:     if ( resf_degtest(k,win,nb,dlist) &&
                    446:       dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
                    447:       NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = factor;
                    448:       g = cofactor;
                    449:       ucsump(g,&csum); mulq(csum,(Q)COEF(DC(g)),&csumt); csum = csumt;
                    450:       for ( i = 0; i < k - 1; i++ )
                    451:         for ( j = win[i] + 1; j < win[i + 1]; j++ ) {
                    452:           c[j-i-1] = c[j];
                    453:           dlist[j-i-1] = dlist[j];
                    454:         }
                    455:       for ( j = win[k-1] + 1; j <= np; j++ ) {
                    456:         c[j-k] = c[j];
                    457:         dlist[j-k] = dlist[j];
                    458:       }
                    459:       if ( ( np -= k ) < k )
                    460:         break;
1.3     ! noro      461:       if ( np - win[0] + 1 < k ) {
1.1       noro      462:         if ( ++k > np )
                    463:           break;
                    464:         else
                    465:           for ( i = 0; i < k; i++ )
                    466:             win[i] = i + 1;
1.3     ! noro      467:       } else
1.1       noro      468:         for ( i = 1; i < k; i++ )
                    469:           win[i] = win[0] + i;
1.3     ! noro      470:     } else if ( !ncombi(1,np,k,win) ) {
1.1       noro      471:       if ( k == np )
                    472:         break;
                    473:       else
                    474:         for ( i = 0, ++k; i < k; i++ )
                    475:           win[i] = i + 1;
1.3     ! noro      476:     }
1.1       noro      477:   }
                    478:   NEXTDC(dcf0,dcf); COEF(dcf) = g;
                    479:   DEG(dcf) = ONE; NEXT(dcf) = 0;*dcp = dcf0;
                    480: }
                    481:
                    482: void resf_dtest_special(P f,ML list,int nb,int *nfl,int *mdl,DCP *dcp)
                    483: {
                    484:   int n,np,bound,q;
                    485:   int i,j;
                    486:   int *win;
                    487:   P g,factor,cofactor;
                    488:   Q csum,csumt;
                    489:   DCP dcf,dcf0;
                    490:   LUM *c;
                    491:   ML wlist;
                    492:   int max;
                    493:
                    494:   n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    495:   win = W_ALLOC(np+1);
                    496:   ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    497:   wlist = W_MLALLOC(np); wlist->n = list->n;
                    498:   wlist->mod = list->mod; wlist->bound = list->bound;
                    499:   c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    500:   max = 1<<nb;
                    501:   for ( g = f, dcf = dcf0 = 0, i = 0; i < max; i++ ) {
                    502: #if 0
                    503:     if ( !(i % 1000) )
                    504:       fprintf(stderr,"i=%d\n",i);
                    505: #endif
                    506:     for ( j = 0; j < nb; j++ )
                    507:       win[j] = (i&(1<<j)) ? 2*j+1 : 2*j;
                    508:     if ( dtestmain(g,csum,wlist,nb,win,&factor,&cofactor) ) {
                    509: #if 0
                    510:       fprintf(stderr,"success : i=%d\n",i);
                    511: #endif
                    512:       NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = factor;
                    513:       NEXTDC(dcf0,dcf); DEG(dcf) = ONE; COEF(dcf) = cofactor;
                    514:       NEXT(dcf) = 0;*dcp = dcf0;
                    515:       return;
                    516:     }
                    517:   }
                    518:   NEXTDC(dcf0,dcf); COEF(dcf) = g;
                    519:   DEG(dcf) = ONE; NEXT(dcf) = 0;*dcp = dcf0;
                    520: }
                    521:
                    522: #if 0
                    523: void Pftest(arg,rp)
                    524: NODE arg;
                    525: P *rp;
                    526: {
                    527:   ML list;
                    528:   DCP dc;
                    529:   P p;
                    530:   P *mfl;
                    531:
                    532:   p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
                    533:   hensel_special(4,1,p,mfl,&list);
                    534:   dtest_special(p,list,rp);
                    535: }
                    536:
                    537: void dtest_special(f,list,pr)
                    538: P f;
                    539: ML list;
                    540: P *pr;
                    541: {
                    542:   int n,np,bound,q;
                    543:   int i,j,k;
                    544:   int *win;
                    545:   P g,factor,cofactor;
                    546:   Q csum,csumt;
                    547:   DCP dc,dcf,dcf0;
                    548:   LUM *c;
                    549:   ML wlist;
                    550:
                    551:   n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    552:   win = W_ALLOC(np+1);
                    553:   ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    554:   wlist = W_MLALLOC(np); wlist->n = list->n;
                    555:   wlist->mod = list->mod; wlist->bound = list->bound;
                    556:   c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    557:   for ( g = f, i = 130000; i < (1<<20); i++ ) {
                    558: #if 0
                    559:     if ( !(i % 1000) )
                    560:       fprintf(stderr,"i=%d\n",i);
                    561: #endif
                    562:     for ( j = 0; j < 20; j++ )
                    563:       win[j] = (i&(1<<j)) ? 2*j+1 : 2*j;
                    564:     if ( dtestmain(g,csum,wlist,20,win,&factor,&cofactor) ) {
                    565: #if 0
                    566:       fprintf(stderr,"success : i=%d\n",i);
                    567: #endif
                    568:       *pr = factor; return;
                    569:     }
                    570:   }
                    571: }
                    572:
                    573: void hensel_special(index,count,f,mfl,listp)
                    574: int index,count;
                    575: P f;
                    576: P *mfl;
                    577: ML *listp;
                    578: {
                    579:   register int i,j;
                    580:   int q,n,t,d,r,u,br,tmp,bound;
                    581:   int *c,*p,*m,*w;
                    582:   int **pp;
                    583:   DCP dc;
                    584:   ML blist,clist,bqlist,cqlist,rlist;
                    585:   UM *b;
                    586:   LUM fl,tl;
                    587:   LUM *l;
                    588:
                    589:   blist = MLALLOC(40); blist->n = 40; blist->mod = 11;
                    590:   for ( i = 0; i < 40; i++ ) {
                    591:     blist->c[i] = (pointer)UMALLOC(6);
                    592:     ptoum(11,mfl[i],blist->c[i]);
                    593:   }
                    594:   gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    595:   n = bqlist->n; q = bqlist->mod;
                    596:   bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    597:   if ( bound == 1 ) {
                    598:     *listp = rlist = MLALLOC(n);
                    599:     rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    600:     for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    601:       tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    602:       for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    603:           pp[j][0] = p[j];
                    604:     }
                    605:   } else {
                    606:     W_LUMALLOC(UDEG(f),bound,fl);
                    607:     ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    608:   }
                    609: }
                    610: #endif
                    611:
                    612: #if 0
                    613: void Pftest(arg,rp)
                    614: NODE arg;
                    615: P *rp;
                    616: {
                    617:   ML list;
                    618:   DCP dc;
                    619:   P p;
                    620:   P *mfl;
                    621:
                    622:   p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
                    623:   hensel_special(2,1,p,mfl,&list);
                    624:   dtest_special(p,list,rp);
                    625: }
                    626:
                    627: void dtest_special(f,list,pr)
                    628: P f;
                    629: ML list;
                    630: P *pr;
                    631: {
                    632:   int n,np,bound,q;
                    633:   int i,j,k,t,b0;
                    634:   int *win;
                    635:   P g,factor,cofactor;
                    636:   Q csum,csumt;
                    637:   DCP dc,dcf,dcf0;
                    638:   LUM *c;
                    639:   ML wlist;
                    640:   static int nbits[16] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4};
                    641:
                    642:   n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    643:   win = W_ALLOC(np+1);
                    644:   ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    645:   wlist = W_MLALLOC(np); wlist->n = list->n;
                    646:   wlist->mod = list->mod; wlist->bound = list->bound;
                    647:   c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    648:   for ( g = f, i = 0; i < (1<<23); i++ ) {
                    649: #if 0
                    650:     if ( !(i % 1000) )
                    651:     fprintf(stderr,"i=%d\n",i);
                    652: #endif
                    653:     t = i>>20; b0 = nbits[t];
                    654:     if ( !b0 )
                    655:       continue;
                    656:     for ( j = 1; j < 6; j++ ) {
                    657:       t = (i>>(20-4*j))&0xf;
                    658:       if ( nbits[t] != b0 )
                    659:         break;
                    660:     }
                    661:     if ( j != 6 )
                    662:       continue;
                    663:     for ( j = k = 0; j < 24; j++ )
                    664:       if ( i & (1<<(23-j)) )
                    665:         win[k++] = j;
                    666:     if ( dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
                    667: #if 0
                    668:       fprintf(stderr,"success : i=%d\n",i);
                    669: #endif
                    670:       *pr = factor; return;
                    671:     }
                    672:   }
                    673:   *pr = f;
                    674: }
                    675:
                    676: void hensel_special(index,count,f,mfl,listp)
                    677: int index,count;
                    678: P f;
                    679: P *mfl;
                    680: ML *listp;
                    681: {
                    682:   register int i,j;
                    683:   int q,n,t,d,r,u,br,tmp,bound;
                    684:   int *c,*p,*m,*w;
                    685:   int **pp;
                    686:   DCP dc;
                    687:   ML blist,clist,bqlist,cqlist,rlist;
                    688:   UM *b;
                    689:   LUM fl,tl;
                    690:   LUM *l;
                    691:
                    692:   blist = MLALLOC(24); blist->n = 24; blist->mod = 5;
                    693:   for ( i = 0; i < 24; i++ ) {
                    694:     blist->c[i] = (pointer)UMALLOC(7);
                    695:     ptoum(5,mfl[i],blist->c[i]);
                    696:   }
                    697:   gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    698:   n = bqlist->n; q = bqlist->mod;
                    699:   bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    700:   if ( bound == 1 ) {
                    701:     *listp = rlist = MLALLOC(n);
                    702:     rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    703:     for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    704:       tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    705:       for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    706:           pp[j][0] = p[j];
                    707:     }
                    708:   } else {
                    709:     W_LUMALLOC(UDEG(f),bound,fl);
                    710:     ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    711:   }
                    712: }
                    713: #endif
                    714:
                    715: void Pftest(NODE arg,P *rp)
                    716: {
                    717:   ML list;
                    718:   P p;
                    719:   P *mfl;
                    720:
                    721:   p = (P)ARG0(arg); mfl = (P *)(((VECT)ARG1(arg))->body);
                    722:   hensel_special(5,1,p,mfl,&list);
                    723:   dtest_special(p,list,rp);
                    724: }
                    725:
                    726: int nbits(int a)
                    727: {
                    728:   int i,s;
                    729:
                    730:   for ( i = 0, s = 0; a && (i < 20); i++, a >>= 1 )
                    731:     if ( a & 1 ) s++;
                    732:   return s;
                    733: }
                    734:
                    735: void dtest_special(P f,ML list,P *pr)
                    736: {
                    737:   int n,np,bound,q;
                    738:   int i,j,k,b0;
                    739:   int *win;
                    740:   P g,factor,cofactor;
                    741:   Q csum,csumt;
                    742:   LUM *c;
                    743:   ML wlist;
                    744:
                    745:   n = UDEG(f); np = list->n; bound = list->bound; q = list->mod;
                    746:   win = W_ALLOC(np+1);
                    747:   ucsump(f,&csum); mulq(csum,(Q)COEF(DC(f)),&csumt); csum = csumt;
                    748:   wlist = W_MLALLOC(np); wlist->n = list->n;
                    749:   wlist->mod = list->mod; wlist->bound = list->bound;
                    750:   c = (LUM *)COEF(wlist); bcopy((char *)COEF(list),(char *)c,(int)(sizeof(LUM)*np));
                    751:   for ( g = f, i = 0; i < (1<<19); i++ ) {
                    752: #if 0
                    753:     if ( !(i % 10000) )
                    754:     fprintf(stderr,"i=%d\n",i);
                    755: #endif
                    756:     b0 = nbits(i>>10);
                    757:     if ( !b0 || (nbits(i&0x3ff) != b0) )
                    758:       continue;
                    759:     for ( j = k = 0; j < 20; j++ )
                    760:       if ( i & (1<<(19-j)) )
                    761:         win[k++] = j;
                    762:     if ( dtestmain(g,csum,wlist,k,win,&factor,&cofactor) ) {
                    763: #if 0
                    764:       fprintf(stderr,"success : i=%d\n",i);
                    765: #endif
                    766:       *pr = factor; return;
                    767:     }
                    768:   }
                    769:   *pr = f;
                    770: }
                    771:
                    772: void hensel_special(int index,int count,P f,P *mfl,ML *listp)
                    773: {
                    774:   register int i,j;
                    775:   int q,n,bound;
                    776:   int *p;
                    777:   int **pp;
                    778:   ML blist,clist,bqlist,cqlist,rlist;
                    779:   UM *b;
                    780:   LUM fl,tl;
                    781:   LUM *l;
                    782:
                    783:   blist = MLALLOC(20); blist->n = 20; blist->mod = 11;
                    784:   for ( i = 0; i < 20; i++ ) {
                    785:     blist->c[i] = (pointer)UMALLOC(10);
                    786:     ptoum(11,mfl[i],blist->c[i]);
                    787:   }
                    788:   gcdgen(f,blist,&clist); henprep(f,blist,clist,&bqlist,&cqlist);
                    789:   n = bqlist->n; q = bqlist->mod;
                    790:   bqlist->bound = cqlist->bound = bound = mignotte(q,f);
                    791:   if ( bound == 1 ) {
                    792:     *listp = rlist = MLALLOC(n);
                    793:     rlist->n = n; rlist->mod = q; rlist->bound = bound;
                    794:     for ( i = 0, b = (UM *)bqlist->c, l = (LUM *)rlist->c; i < n; i++ ) {
                    795:       tl = LUMALLOC(DEG(b[i]),1); l[i] = tl; p = COEF(b[i]);
                    796:       for ( j = 0, pp = COEF(tl); j <= DEG(tl); j++ )
                    797:           pp[j][0] = p[j];
                    798:     }
                    799:   } else {
                    800:     W_LUMALLOC((int)UDEG(f),bound,fl);
                    801:     ptolum(q,bound,f,fl); henmain(fl,bqlist,cqlist,listp);
                    802:   }
                    803: }
                    804:
                    805: void Pnullspace(NODE arg,LIST *rp)
                    806: {
                    807:   int i,j,n,mod;
                    808:   MAT mat,r;
                    809:   VECT u;
                    810:   V v;
                    811:   P p,z;
                    812:   Z q;
                    813:   UM **w;
                    814:   UM mp;
                    815:   P *t;
                    816:   UM *s;
                    817:   int *ind;
                    818:   NODE n0,n1;
                    819:
                    820:   mat = (MAT)ARG0(arg);
                    821:   p = (P)ARG1(arg);
                    822:   v = VR(p);
1.2       noro      823:   mod = ZTOS((Q)ARG2(arg));
1.1       noro      824:   n = mat->row;
                    825:   w = (UM **)almat_pointer(n,n);
                    826:   for ( i = 0; i < n; i++ )
                    827:     for ( j = 0, t = (P *)mat->body[i], s = w[i]; j < n; j++ ) {
                    828:       ptomp(mod,t[j],&z);
                    829:       s[j] = W_UMALLOC((z&&!NUM(z))?UDEG(z):0);
                    830:       mptoum(z,s[j]);
                    831:     }
                    832:   mp = W_UMALLOC(UDEG(p)); ptoum(mod,p,mp);
                    833:   ind = (int *)ALLOCA(n*sizeof(int));
                    834:   nullspace(w,mp,mod,n,ind);
                    835:   MKMAT(r,n,n);
                    836:   for ( i = 0; i < n; i++ )
                    837:     for ( j = 0, t = (P *)r->body[i], s = w[i]; j < n; j++ )
                    838:       umtop(v,s[j],&t[j]);
                    839:   MKVECT(u,n);
                    840:   for ( i = 0; i < n; i++ ) {
1.2       noro      841:     STOZ(ind[i],q); u->body[i] = (pointer)q;
1.1       noro      842:   }
                    843:   MKNODE(n1,u,0); MKNODE(n0,r,n1); MKLIST(*rp,n0);
                    844: }
                    845:
                    846: void nullspace(UM **mat,UM p,int mod,int n,int *ind)
                    847: {
                    848:   int i,j,l,s,d;
                    849:   UM q,w,w1,h,inv;
                    850:   UM *t,*u;
                    851:
                    852:   d = DEG(p); inv = W_UMALLOC(d); q = W_UMALLOC(2*d);
                    853:   w = W_UMALLOC(2*d); w1 = W_UMALLOC(2*d); h = W_UMALLOC(d);
                    854:   bzero(ind,n*sizeof(int));
                    855:   ind[0] = 0;
                    856:   for ( i = j = 0; j < n; i++, j++ ) {
                    857:     for ( ; j < n; j++ ) {
                    858:       for ( l = i; l < n; l++ )
                    859:         if ( DEG(mat[l][j])>=0 )
                    860:           break;
                    861:       if ( l < n ) {
                    862:         t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    863:       } else
                    864:         ind[j] = 1;
                    865:     }
                    866:     if ( j == n )
                    867:       break;
                    868:     invum(mod,p,mat[i][j],inv);
                    869:     for ( s = j, t = mat[i]; s < n; s++ ) {
                    870:       mulum(mod,t[s],inv,w);
                    871:       DEG(w) = divum(mod,w,p,q);
                    872:       cpyum(w,t[s]);
                    873:     }
                    874:     for ( l = 0; l < n; l++ ) {
                    875:       if ( l == i )
                    876:         continue;
                    877:       u = mat[l]; DEG(w) = -1; subum(mod,w,u[j],h);
                    878:       for ( s = j; s < n; s++ ) {
                    879:         mulum(mod,h,t[s],w); addum(mod,w,u[s],w1);
                    880:         DEG(w1) = divum(mod,w1,p,q); cpyum(w1,u[s]);
                    881:       }
                    882:     }
                    883:   }
                    884: }
                    885:
                    886: void Pnullspace_ff(NODE arg,LIST *rp)
                    887: {
                    888:   int i,j,n;
                    889:   MAT mat,r;
                    890:   VECT u;
                    891:   Z q;
                    892:   Obj **w;
                    893:   Obj *t;
                    894:   Obj *s;
                    895:   int *ind;
                    896:   NODE n0,n1;
                    897:
                    898:   mat = (MAT)ARG0(arg);
                    899:   n = mat->row;
                    900:   w = (Obj **)almat_pointer(n,n);
                    901:   for ( i = 0; i < n; i++ )
                    902:     for ( j = 0, t = (Obj *)mat->body[i], s = w[i]; j < n; j++ )
                    903:       s[j] = t[j];
                    904:   ind = (int *)ALLOCA(n*sizeof(int));
                    905:   switch ( current_ff ) {
                    906:     case FF_GFP:
                    907:       nullspace_lm((LM **)w,n,ind); break;
                    908:     case FF_GF2N:
                    909:       nullspace_gf2n((GF2N **)w,n,ind); break;
                    910:     case FF_GFPN:
                    911:       nullspace_gfpn((GFPN **)w,n,ind); break;
                    912:     case FF_GFS:
                    913:       nullspace_gfs((GFS **)w,n,ind); break;
                    914:     case FF_GFSN:
                    915:       nullspace_gfsn((GFSN **)w,n,ind); break;
                    916:     default:
                    917:       error("nullspace_ff : current_ff is not set");
                    918:   }
                    919:   MKMAT(r,n,n);
                    920:   for ( i = 0; i < n; i++ )
                    921:     for ( j = 0, t = (Obj *)r->body[i], s = w[i]; j < n; j++ )
                    922:       t[j] = s[j];
                    923:   MKVECT(u,n);
                    924:   for ( i = 0; i < n; i++ ) {
1.2       noro      925:     STOZ(ind[i],q); u->body[i] = (pointer)q;
1.1       noro      926:   }
                    927:   MKNODE(n1,u,0); MKNODE(n0,r,n1); MKLIST(*rp,n0);
                    928: }
                    929:
                    930: void nullspace_lm(LM **mat,int n,int *ind)
                    931: {
                    932:   int i,j,l,s;
                    933:   Z q,z,mod;
                    934:   LM w,w1,h,inv;
                    935:   LM *t,*u;
                    936:
                    937:   getmod_lm(&mod);
                    938:
                    939:   bzero(ind,n*sizeof(int));
                    940:   ind[0] = 0;
                    941:   for ( i = j = 0; j < n; i++, j++ ) {
                    942:     for ( ; j < n; j++ ) {
                    943:       for ( l = i; l < n; l++ ) {
                    944:         simplm(mat[l][j],&w); mat[l][j] = w;
                    945:         if ( mat[l][j] )
                    946:           break;
                    947:       }
                    948:       if ( l < n ) {
                    949:         t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    950:       } else
                    951:         ind[j] = 1;
                    952:     }
                    953:     if ( j == n )
                    954:       break;
                    955:     lmtolf(mat[i][j],&q); invz(q,mod,&z); MKLM(BDY(z),inv);
                    956:     for ( s = j, t = mat[i]; s < n; s++ ) {
                    957:       mullm(t[s],inv,&w); t[s] = w;
                    958:     }
                    959:     for ( l = 0; l < n; l++ ) {
                    960:       if ( l == i )
                    961:         continue;
                    962:       u = mat[l]; chsgnlm(u[j],&h);
                    963:       for ( s = j; s < n; s++ ) {
                    964:         mullm(h,t[s],&w); addlm(w,u[s],&w1); u[s] = w1;
                    965:       }
                    966:     }
                    967:   }
                    968: }
                    969:
                    970: void nullspace_gf2n(GF2N **mat,int n,int *ind)
                    971: {
                    972:   int i,j,l,s;
                    973:   GF2N w,w1,h,inv;
                    974:   GF2N *t,*u;
                    975:   extern int gf2n_lazy;
                    976:
                    977:   bzero(ind,n*sizeof(int));
                    978:   ind[0] = 0;
                    979:   for ( i = j = 0; j < n; i++, j++ ) {
                    980:     for ( ; j < n; j++ ) {
                    981:       for ( l = i; l < n; l++ ) {
                    982:         simpgf2n(mat[l][j],&w); mat[l][j] = w;
                    983:         if ( mat[l][j] )
                    984:           break;
                    985:       }
                    986:       if ( l < n ) {
                    987:         t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                    988:       } else
                    989:         ind[j] = 1;
                    990:     }
                    991:     if ( j == n )
                    992:       break;
                    993:     invgf2n(mat[i][j],&inv);
                    994:     for ( s = j, t = mat[i]; s < n; s++ ) {
                    995:       mulgf2n(t[s],inv,&w); t[s] = w;
                    996:     }
                    997:     for ( l = 0; l < n; l++ ) {
                    998:       if ( l == i )
                    999:         continue;
                   1000:       u = mat[l]; h = u[j];
                   1001:       for ( s = j; s < n; s++ ) {
                   1002:         mulgf2n(h,t[s],&w); addgf2n(w,u[s],&w1); u[s] = w1;
                   1003:       }
                   1004:     }
                   1005:   }
                   1006: }
                   1007:
                   1008: void nullspace_gfpn(GFPN **mat,int n,int *ind)
                   1009: {
                   1010:   int i,j,l,s;
                   1011:   GFPN w,w1,h,inv;
                   1012:   GFPN *t,*u;
                   1013:
                   1014:   bzero(ind,n*sizeof(int));
                   1015:   ind[0] = 0;
                   1016:   for ( i = j = 0; j < n; i++, j++ ) {
                   1017:     for ( ; j < n; j++ ) {
                   1018:       for ( l = i; l < n; l++ ) {
                   1019:         simpgfpn(mat[l][j],&w); mat[l][j] = w;
                   1020:         if ( mat[l][j] )
                   1021:           break;
                   1022:       }
                   1023:       if ( l < n ) {
                   1024:         t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                   1025:       } else
                   1026:         ind[j] = 1;
                   1027:     }
                   1028:     if ( j == n )
                   1029:       break;
                   1030:     divgfpn((GFPN)ONE,(GFPN)mat[i][j],&inv);
                   1031:     for ( s = j, t = mat[i]; s < n; s++ ) {
                   1032:       mulgfpn(t[s],inv,&w); t[s] = w;
                   1033:     }
                   1034:     for ( l = 0; l < n; l++ ) {
                   1035:       if ( l == i )
                   1036:         continue;
                   1037:       u = mat[l]; chsgngfpn(u[j],&h);
                   1038:       for ( s = j; s < n; s++ ) {
                   1039:         mulgfpn(h,t[s],&w); addgfpn(w,u[s],&w1); u[s] = w1;
                   1040:       }
                   1041:     }
                   1042:   }
                   1043: }
                   1044:
                   1045: void nullspace_gfs(GFS **mat,int n,int *ind)
                   1046: {
                   1047:   int i,j,l,s;
                   1048:   GFS w,w1,h,inv;
                   1049:   GFS *t,*u;
                   1050:   GFS one;
                   1051:
                   1052:   bzero(ind,n*sizeof(int));
                   1053:   ind[0] = 0;
                   1054:   mqtogfs(ONEM,&one);
                   1055:
                   1056:   for ( i = j = 0; j < n; i++, j++ ) {
                   1057:     for ( ; j < n; j++ ) {
                   1058:       for ( l = i; l < n; l++ )
                   1059:         if ( mat[l][j] )
                   1060:           break;
                   1061:       if ( l < n ) {
                   1062:         t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                   1063:       } else
                   1064:         ind[j] = 1;
                   1065:     }
                   1066:     if ( j == n )
                   1067:       break;
                   1068:     divgfs(one,mat[i][j],&inv);
                   1069:     for ( s = j, t = mat[i]; s < n; s++ ) {
                   1070:       mulgfs(t[s],inv,&w); t[s] = w;
                   1071:     }
                   1072:     for ( l = 0; l < n; l++ ) {
                   1073:       if ( l == i )
                   1074:         continue;
                   1075:       u = mat[l];
                   1076:       chsgngfs(u[j],&h);
                   1077:       for ( s = j; s < n; s++ ) {
                   1078:         mulgfs(h,t[s],&w); addgfs(w,u[s],&w1); u[s] = w1;
                   1079:       }
                   1080:     }
                   1081:   }
                   1082: }
                   1083:
                   1084: void nullspace_gfsn(GFSN **mat,int n,int *ind)
                   1085: {
                   1086:   int i,j,l,s;
                   1087:   GFSN w,w1,h,inv;
                   1088:   GFSN *t,*u;
                   1089:
                   1090:   bzero(ind,n*sizeof(int));
                   1091:   ind[0] = 0;
                   1092:
                   1093:   for ( i = j = 0; j < n; i++, j++ ) {
                   1094:     for ( ; j < n; j++ ) {
                   1095:       for ( l = i; l < n; l++ )
                   1096:         if ( mat[l][j] )
                   1097:           break;
                   1098:       if ( l < n ) {
                   1099:         t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                   1100:       } else
                   1101:         ind[j] = 1;
                   1102:     }
                   1103:     if ( j == n )
                   1104:       break;
                   1105:     invgfsn(mat[i][j],&inv);
                   1106:     for ( s = j, t = mat[i]; s < n; s++ ) {
                   1107:       mulgfsn(t[s],inv,&w); t[s] = w;
                   1108:     }
                   1109:     for ( l = 0; l < n; l++ ) {
                   1110:       if ( l == i )
                   1111:         continue;
                   1112:       u = mat[l];
                   1113:       chsgngfsn(u[j],&h);
                   1114:       for ( s = j; s < n; s++ ) {
                   1115:         mulgfsn(h,t[s],&w); addgfsn(w,u[s],&w1); u[s] = w1;
                   1116:       }
                   1117:     }
                   1118:   }
                   1119: }
                   1120:
                   1121: /* p = a(0)vl[0]+a(1)vl[1]+...+a(m-1)vl[m-1]+a(m) -> array = [a(0) a(1) ... a(m)] */
                   1122:
                   1123: void linear_form_to_array(P p,VL vl,int m,Num *array)
                   1124: {
                   1125:   int i;
                   1126:   DCP dc;
                   1127:
                   1128:   bzero((char *)array,(m+1)*sizeof(Num *));
                   1129:   for ( i = 0; p && vl; vl = NEXT(vl), i++ ) {
                   1130:     if ( ID(p) == O_N )
                   1131:       break;
                   1132:     else if ( VR(p) == vl->v ) {
                   1133:       dc = DC(p);
                   1134:       array[i] = (Num)COEF(dc);
                   1135:       dc = NEXT(dc);
                   1136:       p = dc ? COEF(dc) : 0;
                   1137:     }
                   1138:   }
                   1139:   array[m] = (Num)p;
                   1140: }
                   1141:
                   1142: void array_to_linear_form(Num *array,VL vl,int m,P *r)
                   1143: {
                   1144:   P t;
                   1145:   DCP dc0,dc1;
                   1146:
                   1147:   if ( !m )
                   1148:     *r = (P)array[0];
                   1149:   else {
                   1150:     array_to_linear_form(array+1,NEXT(vl),m-1,&t);
                   1151:     if ( !array[0] )
                   1152:       *r = t;
                   1153:     else {
                   1154:       NEWDC(dc0); DEG(dc0) = ONE; COEF(dc0) = (P)array[0];
                   1155:       if ( !t )
                   1156:         NEXT(dc0) = 0;
                   1157:       else {
                   1158:         NEWDC(dc1); DEG(dc1) = 0; COEF(dc1) = t;
                   1159:         NEXT(dc1) = 0;
                   1160:         NEXT(dc0) = dc1;
                   1161:       }
                   1162:       MKP(vl->v,dc0,*r);
                   1163:     }
                   1164:   }
                   1165: }
                   1166:
                   1167: void Psolve_linear_equation_gf2n(NODE arg,LIST *rp)
                   1168: {
                   1169:   NODE eqs,tn;
                   1170:   VL vars,tvl;
                   1171:   int i,j,n,m,dim,codim;
                   1172:   GF2N **w;
                   1173:   int *ind;
                   1174:   NODE n0,n1;
                   1175:
                   1176:   get_vars(ARG0(arg),&vars);
                   1177:   eqs = BDY((LIST)ARG0(arg));
                   1178:   for ( n = 0, tn = eqs; tn; tn = NEXT(tn), n++);
                   1179:   for ( m = 0, tvl = vars; tvl; tvl = NEXT(tvl), m++);
                   1180:   w = (GF2N **)almat_pointer(n,m+1);
                   1181:   for ( i = 0, tn = eqs; i < n; i++, tn = NEXT(tn) )
                   1182:     linear_form_to_array(BDY(tn),vars,m,(Num *)w[i]);
                   1183:   ind = (int *)ALLOCA(m*sizeof(int));
                   1184:   solve_linear_equation_gf2n(w,n,m,ind);
                   1185:   for ( j = 0, dim = 0; j < m; j++ )
                   1186:     if ( ind[j] )
                   1187:       dim++;
                   1188:   codim = m-dim;
                   1189:   for ( i = codim; i < n; i++ )
                   1190:     if ( w[i][m] ) {
                   1191:       MKLIST(*rp,0); return;
                   1192:     }
                   1193:   for ( i = 0, n0 = 0; i < codim; i++ ) {
                   1194:     NEXTNODE(n0,n1);
                   1195:     array_to_linear_form((Num *)w[i],vars,m,(P *)&BDY(n1));
                   1196:   }
                   1197:   if ( n0 )
                   1198:     NEXT(n1) = 0;
                   1199:   MKLIST(*rp,n0);
                   1200: }
                   1201:
                   1202: void solve_linear_equation_gf2n(GF2N **mat,int n,int m,int *ind)
                   1203: {
                   1204:   int i,j,l,s;
                   1205:   GF2N w,w1,h,inv;
                   1206:   GF2N *t,*u;
                   1207:   extern int gf2n_lazy;
                   1208:
                   1209:   bzero(ind,m*sizeof(int));
                   1210:   ind[0] = 0;
                   1211:   for ( i = j = 0; j < m; i++, j++ ) {
                   1212:     for ( ; j < m; j++ ) {
                   1213:       for ( l = i; l < n; l++ ) {
                   1214:         simpgf2n(mat[l][j],&w); mat[l][j] = w;
                   1215:         if ( mat[l][j] )
                   1216:           break;
                   1217:       }
                   1218:       if ( l < n ) {
                   1219:         t = mat[i]; mat[i] = mat[l]; mat[l] = t; break;
                   1220:       } else
                   1221:         ind[j] = 1;
                   1222:     }
                   1223:     if ( j == m )
                   1224:       break;
                   1225:     invgf2n(mat[i][j],&inv);
                   1226:     for ( s = j, t = mat[i]; s <= m; s++ ) {
                   1227:       mulgf2n(t[s],inv,&w); t[s] = w;
                   1228:     }
                   1229:     for ( l = 0; l < n; l++ ) {
                   1230:       if ( l == i )
                   1231:         continue;
                   1232:       u = mat[l]; h = u[j];
                   1233:       for ( s = j; s <= m; s++ ) {
                   1234:         mulgf2n(h,t[s],&w); addgf2n(w,u[s],&w1); u[s] = w1;
                   1235:       }
                   1236:     }
                   1237:   }
                   1238: }
                   1239:
                   1240: /*
                   1241: void null_to_sol(mat,ind,mod,n,r)
                   1242: int **mat;
                   1243: int *ind;
                   1244: int mod,n;
                   1245: UM *r;
                   1246: {
                   1247:   int i,j,k,l;
                   1248:   int *c;
                   1249:   UM w;
                   1250:
                   1251:   for ( i = 0, l = 0; i < n; i++ ) {
                   1252:     if ( !ind[i] )
                   1253:       continue;
                   1254:     w = UMALLOC(n);
                   1255:     for ( j = k = 0, c = COEF(w); j < n; j++ )
                   1256:       if ( ind[j] )
                   1257:         c[j] = 0;
                   1258:       else
                   1259:         c[j] = mat[k++][i];
                   1260:     c[i] = mod-1;
                   1261:     for ( j = n; j >= 0; j-- )
                   1262:       if ( c[j] )
                   1263:         break;
                   1264:     DEG(w) = j;
                   1265:     r[l++] = w;
                   1266:   }
                   1267: }
                   1268: */
                   1269:
                   1270: void showgfmat(UM **mat,int n)
                   1271: {
                   1272:   int i,j,k;
                   1273:   int *c;
                   1274:   UM p;
                   1275:
                   1276:   for ( i = 0; i < n; i++ ) {
                   1277:     for ( j = 0; j < n; j++ ) {
                   1278:       p = mat[i][j];
                   1279:       if ( DEG(p) < 0 )
                   1280:         fprintf(asir_out,"0");
                   1281:       else
                   1282:         for ( p = mat[i][j], k = DEG(p), c = COEF(p); k >= 0; k-- ) {
                   1283:           if ( c[k] )
                   1284:             fprintf(asir_out,"+%d",c[k]);
                   1285:           if ( k > 1 )
                   1286:             fprintf(asir_out,"a^%d",k);
                   1287:           else if ( k == 1 )
1.3     ! noro     1288:             fprintf(asir_out,"a");
1.1       noro     1289:         }
                   1290:       fprintf(asir_out," ");
                   1291:     }
                   1292:     fprintf(asir_out,"\n");
                   1293:   }
                   1294: }
                   1295:
                   1296: #if 0
                   1297: void Pgcda_mod(arg,rp)
                   1298: NODE arg;
                   1299: P *rp;
                   1300: {
                   1301:   p1 = (P)ARG0(arg);
                   1302:   p2 = (P)ARG1(arg);
                   1303:   v = VR((P)ARG2(arg));
                   1304:   d = (P)ARG3(arg);
1.2       noro     1305:   m = ZTOS((Q)ARG4(arg));
1.1       noro     1306:   reordvar(CO,v,&vl);
                   1307:   reorderp(vl,CO,p1,&t); ptomp(m,t,&m1);
                   1308:   reorderp(vl,CO,p2,&t); ptomp(m,t,&m2);
                   1309:   if ( NUM(m1) || NUM(m2) || VR(m1) != v || VR(m2) != v ) {
                   1310:     *rp = ONE; return;
                   1311:   }
                   1312:   if ( deg(v,m1) >= deg(v,m2) ) {
                   1313:     t = m1; m1 = m2; m2 = t;
                   1314:   }
                   1315:   while ( 1 ) {
                   1316:     inva_mod(COEF(DC(m2)),d,m,&inv);
                   1317:     NEWDC(dc); NEXT(dc) = 0; MKP(v,dc,h);
1.2       noro     1318:     d0 = deg(v,m1)-deg(v,m2); STOZ(d0,DEG(dc));
1.1       noro     1319:     mulgq(m,d,inv,COEF(DC(m1)),&COEF(dc));
                   1320:     mulgp(vl,m,d,m2,h,&t); subgp(vl,m,d,m1,t,&s);
                   1321:   }
                   1322: }
                   1323: #endif
                   1324:
                   1325: void Ppwr_mod(NODE arg,P *rp)
                   1326: {
                   1327:   P p,a,d,r;
                   1328:   int m;
                   1329:   Z n;
                   1330:
1.2       noro     1331:   m = ZTOS((Q)ARG4(arg)); n = (Z)ARG5(arg);
1.1       noro     1332:   ptomp(m,(P)ARG0(arg),&p); ptomp(m,(P)ARG1(arg),&a);
                   1333:   ptomp(m,(P)ARG3(arg),&d);
                   1334:   pwr_mod(p,a,VR((P)ARG2(arg)),d,m,n,&r);
                   1335:   mptop(r,rp);
                   1336: }
                   1337:
                   1338: void pwr_mod(P p,P a,V v,P d,int m,Z n,P *rp)
                   1339: {
                   1340:   P t,s,r;
                   1341:   Z n1,two,b;
                   1342:
                   1343:   if ( !n )
                   1344:     *rp = (P)ONEM;
                   1345:   else if ( UNIZ(n) )
                   1346:     *rp = p;
                   1347:   else {
1.2       noro     1348:     STOZ(2,two);
1.1       noro     1349:     divqrz(n,two,&n1,&b);
                   1350:     pwr_mod(p,a,v,d,m,n1,&t);
                   1351:     mulmp(CO,m,t,t,&s); rem_mod(s,a,v,d,m,&r);
                   1352:     if ( b ) {
                   1353:       mulmp(CO,m,r,p,&t); rem_mod(t,a,v,d,m,rp);
                   1354:     } else
                   1355:       *rp = r;
                   1356:   }
                   1357: }
                   1358:
                   1359: void rem_mod(P p,P a,V v,P d,int m,P *rp)
                   1360: {
                   1361:   P tmp,r1,r2;
                   1362:
                   1363:   divsrmp(CO,m,p,d,&tmp,&r1);
                   1364:   divsrmp(CO,m,r1,a,&tmp,&r2);
                   1365:   divsrmp(CO,m,r2,d,&tmp,rp);
                   1366: }

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