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

Annotation of OpenXM_contrib2/asir2018/engine/dalg.c, Revision 1.2

1.1       noro        1: /*
1.2     ! noro        2:  * $OpenXM: OpenXM_contrib2/asir2018/engine/dalg.c,v 1.1 2018/09/19 05:45:07 noro Exp $
1.1       noro        3: */
                      4:
                      5: #include "ca.h"
                      6: #include "base.h"
                      7:
                      8: static NumberField current_numberfield;
                      9: extern struct order_spec *dp_current_spec;
                     10: void simpdalg(DAlg da,DAlg *r);
                     11: int invdalg(DAlg a,DAlg *c);
                     12: void rmcontdalg(DAlg a, DAlg *c);
                     13: void algtodalg(Alg a,DAlg *r);
                     14: void dalgtoalg(DAlg da,Alg *r);
                     15:
                     16: NumberField get_numberfield()
                     17: {
                     18:   return current_numberfield;
                     19: }
                     20:
                     21: void setfield_dalg(NODE alist)
                     22: {
                     23:   NumberField nf;
                     24:   VL vl,vl1,vl2;
                     25:   int n,i,dim;
                     26:   Alg *gen;
                     27:   P *defpoly;
                     28:   P p;
                     29:   Z iq,two;
                     30:   Q c;
                     31:   DP *ps,*mb;
                     32:   DP one;
                     33:   NODE t,b,b1,b2,hlist,mblist;
                     34:   struct order_spec *current_spec;
                     35:
                     36:   nf = (NumberField)MALLOC(sizeof(struct oNumberField));
                     37:   current_numberfield = nf;
                     38:   vl = 0;
                     39:   for ( t = alist; t; t = NEXT(t) ) {
                     40:     clctalg((P)BDY((Alg)BDY(t)),&vl1);
                     41:     mergev(ALG,vl,vl1,&vl2); vl = vl2;
                     42:   }
                     43:   for ( n = 0, vl1 = vl; vl1; vl1 = NEXT(vl1), n++ );
                     44:   nf->n = n;
                     45:   nf->vl = vl;
                     46:   nf->defpoly = defpoly = (P *)MALLOC(n*sizeof(P));
                     47:   nf->ps = ps = (DP *)MALLOC(n*sizeof(DP));
                     48:   current_spec = dp_current_spec;
1.2     ! noro       49:   STOZ(2,two);
1.1       noro       50:   create_order_spec(0,(Obj)two,&nf->spec);
                     51:   initd(nf->spec);
                     52:   for ( b = hlist = 0, i = 0, vl1 = vl; i < n; vl1 = NEXT(vl1), i++ ) {
                     53:     ptozp(vl1->v->attr,1,&c,&defpoly[i]);
                     54:     ptod(ALG,vl,defpoly[i],&ps[i]);
1.2     ! noro       55:     STOZ(i,iq); MKNODE(b1,(pointer)iq,b); b = b1;
1.1       noro       56:     MKNODE(b2,(pointer)ps[i],hlist); hlist = b2;
                     57:   }
                     58:   ptod(ALG,vl,(P)ONE,&one);
                     59:   MKDAlg(one,ONE,nf->one);
                     60:   nf->ind = b;
                     61:   dp_mbase(hlist,&mblist);
                     62:   initd(current_spec);
                     63:   nf->dim = dim = length(mblist);
                     64:   nf->mb = mb = (DP *)MALLOC(dim*sizeof(DP));
                     65:   for ( i = 0, t = mblist; t; t = NEXT(t), i++ )
                     66:     mb[dim-i-1] = (DP)BDY(t);
                     67: }
                     68:
                     69: void setfield_gb(NODE gb,VL vl,struct order_spec *spec)
                     70: {
                     71:   NumberField nf;
                     72:   VL vl1,vl2;
                     73:   int n,i,dim;
                     74:   Alg *gen;
                     75:   P *defpoly;
                     76:   P p;
                     77:   Q c;
                     78:   Z iq,two;
                     79:   DP *ps,*mb;
                     80:   DP one;
                     81:   NODE t,b,b1,b2,hlist,mblist;
                     82:   struct order_spec *current_spec;
                     83:
                     84:   nf = (NumberField)MALLOC(sizeof(struct oNumberField));
                     85:   current_numberfield = nf;
                     86:   for ( vl1 = vl, n = 0; vl1; vl1 = NEXT(vl1), n++ );
                     87:   nf->n = n;
                     88:   nf->psn = length(gb);
                     89:   nf->vl = vl;
                     90:   nf->defpoly = defpoly = (P *)MALLOC(nf->psn*sizeof(P));
                     91:   nf->ps = ps = (DP *)MALLOC(nf->psn*sizeof(DP));
                     92:   current_spec = dp_current_spec;
                     93:   nf->spec = spec;
                     94:   initd(nf->spec);
                     95:   for ( b = hlist = 0, i = 0, t = gb; i < nf->psn; t = NEXT(t), i++ ) {
                     96:     ptozp((P)BDY(t),1,&c,&defpoly[i]);
                     97:     ptod(CO,vl,defpoly[i],&ps[i]);
1.2     ! noro       98:     STOZ(i,iq); MKNODE(b1,(pointer)iq,b); b = b1;
1.1       noro       99:     MKNODE(b2,(pointer)ps[i],hlist); hlist = b2;
                    100:   }
                    101:   ptod(ALG,vl,(P)ONE,&one);
                    102:   MKDAlg(one,ONE,nf->one);
                    103:   nf->ind = b;
                    104:   dp_mbase(hlist,&mblist);
                    105:   initd(current_spec);
                    106:   nf->dim = dim = length(mblist);
                    107:   nf->mb = mb = (DP *)MALLOC(dim*sizeof(DP));
                    108:   for ( i = 0, t = mblist; t; t = NEXT(t), i++ )
                    109:     mb[dim-i-1] = (DP)BDY(t);
                    110: }
                    111:
                    112: void qtodalg(Q q,DAlg *r)
                    113: {
                    114:   NumberField nf;
                    115:   Z t;
                    116:   DP nm;
                    117:
                    118:   if ( !(nf=current_numberfield) )
                    119:     error("qtodalg : current_numberfield is not set");
                    120:   if ( !q )
                    121:     *r = 0;
                    122:   else if ( NID(q) == N_DA )
                    123:     *r = (DAlg)q;
                    124:   else if ( NID(q) == N_Q ) {
                    125:     if ( INT(q) ) {
                    126:       muldc(CO,nf->one->nm,(Obj)q,&nm);
                    127:       MKDAlg(nm,ONE,*r);
                    128:     } else {
                    129:       MPZTOZ(mpq_numref(BDY((Q)q)),t);
                    130:       muldc(CO,nf->one->nm,(Obj)t,&nm);
                    131:       MPZTOZ(mpq_denref(BDY((Q)q)),t);
                    132:       MKDAlg(nm,t,*r);
                    133:     }
                    134:   } else
                    135:     error("qtodalg : invalid argument");
                    136: }
                    137:
                    138: void obj_algtodalg(Obj obj,Obj *r)
                    139: {
                    140:   DAlg d;
                    141:   DCP dc,dcr0,dcr;
                    142:   P c,p;
                    143:   Obj t;
                    144:   Obj nm,dn;
                    145:   NODE b,s,s0;
                    146:   R rat;
                    147:   VECT v;
                    148:   MAT mat;
                    149:   LIST list;
                    150:   pointer *a;
                    151:   pointer **m;
                    152:   int len,row,col,i,j,l;
                    153:
                    154:   if ( !obj ) {
                    155:     *r = 0;
                    156:     return;
                    157:   }
                    158:   switch ( OID(obj) ) {
                    159:     case O_N:
                    160:       algtodalg((Alg)obj,&d); *r = (Obj)d;
                    161:       break;
                    162:     case O_P:
                    163:       for ( dcr0 = 0, dc = DC((P)obj); dc; dc = NEXT(dc) ) {
                    164:         obj_algtodalg((Obj)COEF(dc),&t);
                    165:         if ( t ) {
                    166:           NEXTDC(dcr0,dcr);
                    167:           COEF(dcr) = (P)t;
                    168:           DEG(dcr) = DEG(dc);
                    169:         }
                    170:       }
                    171:       if ( dcr0 ) {
                    172:         MKP(VR((P)obj),dcr0,p);
                    173:         *r = (Obj)p;
                    174:       } else
                    175:         *r = 0;
                    176:       break;
                    177:     case O_R:
                    178:       obj_algtodalg((Obj)NM((R)obj),&nm);
                    179:       obj_algtodalg((Obj)DN((R)obj),&dn);
                    180:       if ( !dn )
                    181:         error("obj_algtodalg : division by 0");
                    182:       if ( !nm )
                    183:         *r = 0;
                    184:       else {
                    185:         MKRAT((P)nm,(P)dn,0,rat); *r = (Obj)rat;
                    186:       }
                    187:       break;
                    188:     case O_LIST:
                    189:       s0 = 0;
                    190:       for ( b = BDY((LIST)obj); b; b = NEXT(b) ) {
                    191:         NEXTNODE(s0,s);
                    192:         obj_algtodalg((Obj)BDY(b),&t);
                    193:         BDY(s) = (pointer)t;
                    194:       }
                    195:       NEXT(s) = 0;
                    196:       MKLIST(list,s0);
                    197:       *r = (Obj)list;
                    198:       break;
                    199:     case O_VECT:
                    200:       l = ((VECT)obj)->len;
                    201:       a = BDY((VECT)obj);
                    202:       MKVECT(v,l);
                    203:       for ( i = 0; i < l; i++ ) {
                    204:         obj_algtodalg((Obj)a[i],&t);
                    205:         BDY(v)[i] = (pointer)t;
                    206:       }
                    207:       *r = (Obj)v;
                    208:       break;
                    209:     case O_MAT:
                    210:       row = ((MAT)obj)->row; col = ((MAT)obj)->col;
                    211:       m = BDY((MAT)obj);
                    212:       MKMAT(mat,row,col);
                    213:       for ( i = 0; i < row; i++ )
                    214:         for ( j = 0; j < col; j++ ) {
                    215:           obj_algtodalg((Obj)m[i][j],&t);
                    216:           BDY(mat)[i][j] = (pointer)t;
                    217:         }
                    218:       *r = (Obj)mat;
                    219:       break;
                    220:     default:
                    221:       *r = obj;
                    222:       break;
                    223:   }
                    224: }
                    225:
                    226: void obj_dalgtoalg(Obj obj,Obj *r)
                    227: {
                    228:   Alg d;
                    229:   DCP dc,dcr0,dcr;
                    230:   P c,p;
                    231:   Obj t;
                    232:   Obj nm,dn;
                    233:   NODE b,s,s0;
                    234:   R rat;
                    235:   VECT v;
                    236:   MAT mat;
                    237:   LIST list;
                    238:   pointer *a;
                    239:   pointer **m;
                    240:   int len,row,col,i,j,l;
                    241:
                    242:   if ( !obj ) {
                    243:     *r = 0;
                    244:     return;
                    245:   }
                    246:   switch ( OID(obj) ) {
                    247:     case O_N:
                    248:       dalgtoalg((DAlg)obj,&d); *r = (Obj)d;
                    249:       break;
                    250:     case O_P:
                    251:       for ( dcr0 = 0, dc = DC((P)obj); dc; dc = NEXT(dc) ) {
                    252:         obj_dalgtoalg((Obj)COEF(dc),&t);
                    253:         if ( t ) {
                    254:           NEXTDC(dcr0,dcr);
                    255:           COEF(dcr) = (P)t;
                    256:           DEG(dcr) = DEG(dc);
                    257:         }
                    258:       }
                    259:       if ( dcr0 ) {
                    260:         MKP(VR((P)obj),dcr0,p);
                    261:         *r = (Obj)p;
                    262:       } else
                    263:         *r = 0;
                    264:       break;
                    265:     case O_R:
                    266:       obj_dalgtoalg((Obj)NM((R)obj),&nm);
                    267:       obj_dalgtoalg((Obj)DN((R)obj),&dn);
                    268:       if ( !dn )
                    269:         error("obj_dalgtoalg : division by 0");
                    270:       if ( !nm )
                    271:         *r = 0;
                    272:       else {
                    273:         MKRAT((P)nm,(P)dn,0,rat); *r = (Obj)rat;
                    274:       }
                    275:       break;
                    276:     case O_LIST:
                    277:       s0 = 0;
                    278:       for ( b = BDY((LIST)obj); b; b = NEXT(b) ) {
                    279:         NEXTNODE(s0,s);
                    280:         obj_dalgtoalg((Obj)BDY(b),&t);
                    281:         BDY(s) = (pointer)t;
                    282:       }
                    283:       NEXT(s) = 0;
                    284:       MKLIST(list,s0);
                    285:       *r = (Obj)list;
                    286:       break;
                    287:     case O_VECT:
                    288:       l = ((VECT)obj)->len;
                    289:       a = BDY((VECT)obj);
                    290:       MKVECT(v,l);
                    291:       for ( i = 0; i < l; i++ ) {
                    292:         obj_dalgtoalg((Obj)a[i],&t);
                    293:         BDY(v)[i] = (pointer)t;
                    294:       }
                    295:       *r = (Obj)v;
                    296:       break;
                    297:     case O_MAT:
                    298:       row = ((MAT)obj)->row; col = ((MAT)obj)->col;
                    299:       m = BDY((MAT)obj);
                    300:       MKMAT(mat,row,col);
                    301:       for ( i = 0; i < row; i++ )
                    302:         for ( j = 0; j < col; j++ ) {
                    303:           obj_dalgtoalg((Obj)m[i][j],&t);
                    304:           BDY(mat)[i][j] = (pointer)t;
                    305:         }
                    306:       *r = (Obj)mat;
                    307:       break;
                    308:     default:
                    309:       *r = obj;
                    310:       break;
                    311:   }
                    312: }
                    313:
                    314: void algtodalg(Alg a,DAlg *r)
                    315: {
                    316:   P ap,p,p1;
                    317:   Q c;
                    318:   Z c1,d1,nm,dn;
                    319:   DP dp;
                    320:   DAlg da;
                    321:   NumberField nf;
                    322:   struct order_spec *current_spec;
                    323:   VL vl,tvl,svl;
                    324:   V v;
                    325:
                    326:   if ( !(nf=current_numberfield) )
                    327:     error("algtodalg : current_numberfield is not set");
                    328:   if ( !a ) {
                    329:     *r = 0;
                    330:     return;
                    331:   }
                    332:   switch (NID((Num)a) ) {
                    333:     case N_Q:
                    334:       c = (Q)a;
                    335:       if ( INT(c) ) {
                    336:         muldc(CO,nf->one->nm,(Obj)c,&dp);
                    337:         MKDAlg(dp,ONE,*r);
                    338:       } else {
                    339:         MPZTOZ(mpq_numref(BDY((Q)c)),c1);
                    340:         MPZTOZ(mpq_denref(BDY((Q)c)),d1);
                    341:         muldc(CO,nf->one->nm,(Obj)c1,&dp);
                    342:         MKDAlg(dp,d1,*r);
                    343:       }
                    344:       break;
                    345:     case N_A:
                    346:       ap = (P)BDY(a);
                    347:       ptozp(ap,1,&c,&p);
                    348:       if ( INT(c) ) {
                    349:         p = ap;
                    350:         dn = ONE;
                    351:       } else {
                    352:         MPZTOZ(mpq_numref(BDY((Q)c)),nm);
                    353:         MPZTOZ(mpq_denref(BDY((Q)c)),dn);
                    354:         mulpq(p,(P)nm,&p1); p = p1;
                    355:       }
                    356:       current_spec = dp_current_spec; initd(nf->spec);
                    357:       get_vars((Obj)p,&vl);
                    358:       for ( tvl = vl; tvl; tvl = NEXT(tvl) ) {
                    359:         v = tvl->v;
                    360:         for ( svl = nf->vl; svl; svl = NEXT(svl) )
                    361:           if ( v == svl->v )
                    362:             break;
                    363:         if ( !svl )
                    364:           error("algtodalg : incompatible numberfield");
                    365:       }
                    366:       ptod(ALG,nf->vl,p,&dp);
                    367:       MKDAlg(dp,dn,da);
                    368:       simpdalg(da,r);
                    369:       break;
                    370:     default:
                    371:       error("algtodalg : invalid argument");
                    372:       break;
                    373:   }
                    374: }
                    375:
                    376: void dalgtoalg(DAlg da,Alg *r)
                    377: {
                    378:   NumberField nf;
                    379:   P p,p1;
                    380:   Q inv;
                    381:
                    382:   if ( !(nf=current_numberfield) )
                    383:     error("dalgtoalg : current_numberfield is not set");
                    384:   if ( !da ) *r = 0;
                    385:   else {
                    386:     dtop(ALG,nf->vl,da->nm,(Obj *)&p);
                    387:     invq((Q)da->dn,&inv);
                    388:     mulpq(p,(P)inv,&p1);
                    389:     MKAlg(p1,*r);
                    390:   }
                    391: }
                    392:
                    393: void simpdalg(DAlg da,DAlg *r)
                    394: {
                    395:   NumberField nf;
                    396:   DP nm;
                    397:   DAlg d;
                    398:   Z dn,dn1;
                    399:   struct order_spec *current_spec;
                    400:
                    401:   if ( !(nf=current_numberfield) )
                    402:     error("simpdalg : current_numberfield is not set");
                    403:   if ( !da ) {
                    404:     *r = 0;
                    405:     return;
                    406:   }
                    407:   current_spec = dp_current_spec; initd(nf->spec);
                    408:   dp_true_nf(nf->ind,da->nm,nf->ps,1,&nm,(P *)&dn);
                    409:   if ( !nm ) *r = 0;
                    410:   else {
                    411:     initd(current_spec);
                    412:     mulz(da->dn,dn,&dn1);
                    413:     MKDAlg(nm,dn1,d);
                    414:     rmcontdalg(d,r);
                    415:   }
                    416: }
                    417:
                    418: void adddalg(DAlg a,DAlg b,DAlg *c)
                    419: {
                    420:   NumberField nf;
                    421:   Z dna,dnb,a1,b1,dn,g,an,bn,gn;
                    422:   DAlg t;
                    423:   DP ta,tb,nm;
                    424:   struct order_spec *current_spec;
                    425:
                    426:   if ( !(nf=current_numberfield) )
                    427:     error("adddalg : current_numberfield is not set");
                    428:   if ( !a )
                    429:     *c = b;
                    430:   else if ( !b )
                    431:     *c = a;
                    432:   else {
                    433:     qtodalg((Q)a,&t); a = t; qtodalg((Q)b,&t); b = t;
                    434:     dna = a->dn;
                    435:     dnb = b->dn;
                    436:     gcdz(dna,dnb,&gn);
1.2     ! noro      437:     divsz(dna,gn,&a1); divsz(dnb,gn,&b1);
1.1       noro      438:     /* nma/dna+nmb/dnb = (nma*b1+nmb*a1)/(dna*b1) */
                    439:     muldc(CO,a->nm,(Obj)b1,&ta); muldc(CO,b->nm,(Obj)a1,&tb);
                    440:     current_spec = dp_current_spec; initd(nf->spec);
                    441:     addd(CO,ta,tb,&nm);
                    442:     initd(current_spec);
                    443:     if ( !nm )
                    444:       *c = 0;
                    445:     else {
                    446:       mulz(dna,b1,&dn);
                    447:       MKDAlg(nm,dn,*c);
                    448:     }
                    449:   }
                    450: }
                    451:
                    452: void subdalg(DAlg a,DAlg b,DAlg *c)
                    453: {
                    454:   NumberField nf;
                    455:   Z dna,dnb,a1,b1,dn,gn;
                    456:   DP ta,tb,nm;
                    457:   DAlg t;
                    458:   struct order_spec *current_spec;
                    459:
                    460:   if ( !(nf=current_numberfield) )
                    461:     error("subdalg : current_numberfield is not set");
                    462:   if ( !a )
                    463:     *c = b;
                    464:   else if ( !b )
                    465:     *c = a;
                    466:   else {
                    467:     qtodalg((Q)a,&t); a = t; qtodalg((Q)b,&t); b = t;
                    468:     dna = a->dn;
                    469:     dnb = b->dn;
                    470:     gcdz(dna,dnb,&gn);
1.2     ! noro      471:     divsz(dna,gn,&a1); divsz(dnb,gn,&b1);
1.1       noro      472:     /* nma/dna-nmb/dnb = (nma*b1-nmb*a1)/(dna*b1) */
                    473:     muldc(CO,a->nm,(Obj)b1,&ta); muldc(CO,b->nm,(Obj)a1,&tb);
                    474:     current_spec = dp_current_spec; initd(nf->spec);
                    475:     subd(CO,ta,tb,&nm);
                    476:     initd(current_spec);
                    477:     if ( !nm )
                    478:       *c = 0;
                    479:     else {
                    480:       mulz(dna,b1,&dn);
                    481:       MKDAlg(nm,dn,*c);
                    482:     }
                    483:   }
                    484: }
                    485:
                    486: void muldalg(DAlg a,DAlg b,DAlg *c)
                    487: {
                    488:   NumberField nf;
                    489:   DP nm;
                    490:   Z dn;
                    491:   DAlg t;
                    492:   struct order_spec *current_spec;
                    493:
                    494:   if ( !(nf=current_numberfield) )
                    495:     error("muldalg : current_numberfield is not set");
                    496:   if ( !a || !b )
                    497:     *c = 0;
                    498:   else {
                    499:     qtodalg((Q)a,&t); a = t; qtodalg((Q)b,&t); b = t;
                    500:     current_spec = dp_current_spec; initd(nf->spec);
                    501:     muld(CO,a->nm,b->nm,&nm);
                    502:     initd(current_spec);
                    503:     mulz(a->dn,b->dn,&dn);
                    504:     MKDAlg(nm,dn,t);
                    505:     simpdalg(t,c);
                    506:   }
                    507: }
                    508:
                    509:
                    510: void divdalg(DAlg a,DAlg b,DAlg *c)
                    511: {
                    512:   DAlg inv,t;
                    513:   int ret;
                    514:
                    515:   if ( !current_numberfield )
                    516:     error("divdalg : current_numberfield is not set");
                    517:   if ( !b )
                    518:     error("divdalg : division by 0");
                    519:   if ( !a )
                    520:     c = 0;
                    521:   else {
                    522:     qtodalg((Q)a,&t); a = t; qtodalg((Q)b,&t); b = t;
                    523:     ret = invdalg(b,&inv);
                    524:     if ( !ret ) {
                    525:       error("divdalg : the denominator is not invertible");
                    526:     }
                    527:     muldalg(a,inv,c);
                    528:   }
                    529: }
                    530:
                    531: void rmcontdalg(DAlg a, DAlg *r)
                    532: {
                    533:   DP u,u1;
                    534:   Z cont,c,d,gn;
                    535:
                    536:   if ( !a )
                    537:     *r = a;
                    538:   else {
                    539:     dp_ptozp(a->nm,&u);
1.2     ! noro      540:     divsz((Z)BDY(a->nm)->c,(Z)BDY(u)->c,&cont);
1.1       noro      541:     gcdz(cont,a->dn,&gn);
                    542:     divsz(cont,gn,&c);
                    543:     divsz(a->dn,gn,&d);
                    544:     muldc(CO,u,(Obj)c,&u1);
                    545:     MKDAlg(u1,d,*r);
                    546:   }
                    547: }
                    548:
                    549: int invdalg(DAlg a,DAlg *c)
                    550: {
                    551:   NumberField nf;
                    552:   int dim,n,i,j,k,l;
                    553:   DP *mb;
                    554:   DP m,d,u;
                    555:   Z ln,gn,qn,dnsol;
                    556:   Q dn,mul,nmc,dn1;
                    557:   DAlg *simp;
                    558:   DAlg t,a0,r;
                    559:   MAT mobj,sol;
                    560:   Z **mat,**solmat;
                    561:   MP mp0,mp;
                    562:   int *rinfo,*cinfo;
                    563:   int rank,nparam;
                    564:   NODE nd0,nd,ndt;
                    565:   struct order_spec *current_spec;
                    566:   struct oEGT eg0,eg1;
                    567:   extern struct oEGT eg_le;
                    568:
                    569:   if ( !(nf=current_numberfield) )
                    570:     error("invdalg : current_numberfield is not set");
                    571:   if ( !a )
                    572:     error("invdalg : division by 0");
                    573:   else if ( NID(a) == N_Q ) {
                    574:     invq((Q)a,&dn); *c = (DAlg)dn;
                    575:     return 1;
                    576:   }
                    577:   dim = nf->dim;
                    578:   mb = nf->mb;
                    579:   n = nf->n;
                    580:   ln = ONE;
                    581:   dp_ptozp(a->nm,&u); divq((Q)BDY(a->nm)->c,(Q)BDY(u)->c,&nmc);
                    582:   MKDAlg(u,ONE,a0);
                    583:   simp = (DAlg *)ALLOCA(dim*sizeof(DAlg));
                    584:   current_spec = dp_current_spec; initd(nf->spec);
                    585:   for ( i = 0; i < dim; i++ ) {
                    586:     m = mb[i];
                    587:     for ( j = i-1; j >= 0; j-- )
                    588:       if ( dp_redble(m,mb[j]) )
                    589:         break;
                    590:     if ( j >= 0 ) {
                    591:       dp_subd(m,mb[j],&d);
                    592:       muld(CO,d,simp[j]->nm,&u);
                    593:       MKDAlg(u,simp[j]->dn,t);
                    594:       simpdalg(t,&simp[i]);
                    595:     } else {
                    596:       MKDAlg(m,ONE,t);
                    597:       muldalg(t,a0,&simp[i]);
                    598:     }
1.2     ! noro      599:     gcdz(simp[i]->dn,ln,&gn); divsz(ln,gn,&qn);
1.1       noro      600:     mulz(simp[i]->dn,qn,&ln);
                    601:   }
                    602:   initd(current_spec);
                    603:   absq((Q)ln,&dn);
                    604:   MKMAT(mobj,dim,dim+1);
                    605:   mat = (Z **)BDY(mobj);
                    606:   mulq((Q)dn,(Q)a->dn,(Q *)&mat[0][dim]);
                    607:   for ( j = 0; j < dim; j++ ) {
                    608:     divq((Q)dn,(Q)simp[j]->dn,&mul);
                    609:     for ( i = dim-1, mp = BDY(simp[j]->nm); mp && i >= 0; i-- )
                    610:       if ( dl_equal(n,BDY(mb[i])->dl,mp->dl) ) {
                    611:         mulq(mul,(Q)mp->c,(Q *)&mat[i][j]);
                    612:         mp = NEXT(mp);
                    613:       }
                    614:   }
                    615:   get_eg(&eg0);
                    616:   rank = generic_gauss_elim_hensel(mobj,&sol,&dnsol,&rinfo,&cinfo);
                    617:   get_eg(&eg1); add_eg(&eg_le,&eg0,&eg1);
                    618:   if ( cinfo[0] == dim ) {
                    619:     /* the input is invertible */
                    620:     solmat = (Z **)BDY(sol);
                    621:     for ( i = dim-1, mp0 = 0; i >= 0; i-- )
                    622:       if ( solmat[i][0] ) {
                    623:         NEXTMP(mp0,mp);
                    624:         mp->c = (Obj)solmat[i][0];
                    625:         mp->dl = BDY(mb[i])->dl;
                    626:       }
                    627:     NEXT(mp) = 0; MKDP(n,mp0,u);
                    628:     mulq((Q)dnsol,nmc,(Q *)&dn1);
                    629:     MKDAlg(u,(Z)dn1,r);
                    630:     rmcontdalg(r,c);
                    631:     return 1;
                    632:   } else
                    633:     return 0;
                    634: }
                    635:
                    636: NODE inv_or_split_dalg(DAlg a,DAlg *c)
                    637: {
                    638:   NumberField nf;
                    639:   int dim,n,i,j,k,l;
                    640:   DP *mb;
                    641:   DP m,d,u;
                    642:   Z ln,gn,qn;
                    643:   DAlg *simp;
                    644:   DAlg t,a0,r;
                    645:   Q dn,mul;
                    646:   Z dnsol,dn1,nmc;
                    647:   MAT mobj,sol;
                    648:   Z **mat,**solmat;
                    649:   MP mp0,mp;
                    650:   int *rinfo,*cinfo;
                    651:   int rank,nparam;
                    652:   NODE nd0,nd,ndt;
                    653:   struct order_spec *current_spec;
                    654:   struct oEGT eg0,eg1;
                    655:   extern struct oEGT eg_le;
                    656:   extern int DP_Print;
                    657:
                    658:   if ( !(nf=current_numberfield) )
                    659:     error("invdalg : current_numberfield is not set");
                    660:   if ( !a )
                    661:     error("invdalg : division by 0");
                    662:   else if ( NID(a) == N_Q ) {
                    663:     invq((Q)a,&dn); *c = (DAlg)dn;
                    664:     return 0;
                    665:   }
                    666:   dim = nf->dim;
                    667:   mb = nf->mb;
                    668:   n = nf->n;
                    669:   ln = ONE;
1.2     ! noro      670:   dp_ptozp(a->nm,&u); divsz((Z)BDY(a->nm)->c,(Z)BDY(u)->c,&nmc);
1.1       noro      671:   MKDAlg(u,ONE,a0);
                    672:   simp = (DAlg *)MALLOC(dim*sizeof(DAlg));
                    673:   current_spec = dp_current_spec; initd(nf->spec);
                    674:   for ( i = 0; i < dim; i++ ) {
                    675:     if ( DP_Print ) { fprintf(asir_out,"."); fflush(asir_out); }
                    676:     m = mb[i];
                    677:     for ( j = i-1; j >= 0; j-- )
                    678:       if ( dp_redble(m,mb[j]) )
                    679:         break;
                    680:     if ( j >= 0 ) {
                    681:       dp_subd(m,mb[j],&d);
                    682:       if ( simp[j] ) {
                    683:         muld(CO,d,simp[j]->nm,&u);
                    684:         MKDAlg(u,simp[j]->dn,t);
                    685:         simpdalg(t,&simp[i]);
                    686:       } else
                    687:         simp[i] = 0;
                    688:     } else {
                    689:       MKDAlg(m,ONE,t);
                    690:       muldalg(t,a0,&simp[i]);
                    691:     }
                    692:     if ( simp[i] ) {
1.2     ! noro      693:       gcdz(simp[i]->dn,ln,&gn); divsz(ln,gn,&qn);
1.1       noro      694:       mulz(simp[i]->dn,qn,&ln);
                    695:     }
                    696:   }
                    697:   initd(current_spec);
                    698:   absq((Q)ln,&dn);
                    699:   MKMAT(mobj,dim,dim+1);
                    700:   mat = (Z **)BDY(mobj);
                    701:   mulq(dn,(Q)a->dn,(Q *)&mat[0][dim]);
                    702:   for ( j = 0; j < dim; j++ ) {
                    703:     if ( simp[j] ) {
                    704:       divq(dn,(Q)simp[j]->dn,&mul);
                    705:       for ( i = dim-1, mp = BDY(simp[j]->nm); mp && i >= 0; i-- )
                    706:         if ( dl_equal(n,BDY(mb[i])->dl,mp->dl) ) {
                    707:           mulq(mul,(Q)mp->c,(Q *)&mat[i][j]);
                    708:           mp = NEXT(mp);
                    709:         }
                    710:     }
                    711:   }
                    712:   get_eg(&eg0);
                    713:   rank = generic_gauss_elim_hensel_dalg(mobj,mb,&sol,&dnsol,&rinfo,&cinfo);
                    714:   get_eg(&eg1); add_eg(&eg_le,&eg0,&eg1);
                    715:   if ( cinfo[0] == dim ) {
                    716:     /* the input is invertible */
                    717:     solmat = (Z **)BDY(sol);
                    718:     for ( i = dim-1, mp0 = 0; i >= 0; i-- )
                    719:       if ( solmat[i][0] ) {
                    720:         NEXTMP(mp0,mp);
                    721:         mp->c = (Obj)solmat[i][0];
                    722:         mp->dl = BDY(mb[i])->dl;
                    723:       }
                    724:     NEXT(mp) = 0; MKDP(n,mp0,u);
                    725:     mulz(dnsol,nmc,&dn1);
                    726:     MKDAlg(u,dn1,r);
                    727:     rmcontdalg(r,c);
                    728:     return 0;
                    729:   } else {
                    730:     /* the input is not invertible */
                    731:     nparam = sol->col;
                    732:     solmat = (Z **)BDY(sol);
                    733:     nd0 = 0;
                    734:     for ( k = 0; k < nparam; k++ ) {
                    735:       /* construct a new basis element */
                    736:       m = mb[cinfo[k]];
                    737:       mp0 = 0;
                    738:       NEXTMP(mp0,mp);
                    739:       chsgnz(dnsol,&dn1); mp->c = (Obj)dn1;
                    740:       mp->dl = BDY(m)->dl;
                    741:       /* skip the last parameter */
                    742:       for ( l = rank-2; l >= 0; l-- ) {
                    743:         if ( solmat[l][k] ) {
                    744:           NEXTMP(mp0,mp);
                    745:           mp->c = (Obj)solmat[l][k];
                    746:           mp->dl = BDY(mb[rinfo[l]])->dl;
                    747:         }
                    748:       }
                    749:       NEXT(mp) = 0; MKDP(n,mp0,u);
                    750:       NEXTNODE(nd0,nd);
                    751:       BDY(nd) = (pointer)u;
                    752:       NEXT(nd) = 0;
                    753:     }
                    754:     NEXT(nd) = 0;
                    755:     return nd0;
                    756:   }
                    757: }
                    758:
                    759: NODE dp_inv_or_split(NODE gb,DP f,struct order_spec *spec, DP *inv)
                    760: {
                    761:   int dim,n,i,j,k,l,nv;
                    762:   DP *mb,*ps;
                    763:   DP m,d,u,nm;
                    764:   Z ln,gn,qn;
                    765:   DAlg *simp;
                    766:   DAlg a0,r;
                    767:   Q mul,nmc;
                    768:   Z iq,dn,dn1,dnsol;
                    769:   MAT mobj,sol;
                    770:   Z **mat,**solmat;
                    771:   MP mp0,mp;
                    772:   int *rinfo,*cinfo;
                    773:   int rank,nparam;
                    774:   NODE nd0,nd,ndt,ind,indt,t,mblist;
                    775:   struct oEGT eg0,eg1;
                    776:   extern struct oEGT eg_le;
                    777:   extern int DP_Print;
                    778:   initd(spec);
                    779:   dp_ptozp(f,&u); f = u;
                    780:
                    781:   n = length(gb);
                    782:   ps = (DP *)MALLOC(n*sizeof(DP));
                    783:   for ( ind = 0, i = 0, t = gb; i < n; i++, t = NEXT(t) ) {
                    784:     ps[i] = (DP)BDY(t);
                    785:     NEXTNODE(ind,indt);
1.2     ! noro      786:     STOZ(i,iq); BDY(indt) = iq;
1.1       noro      787:   }
                    788:   if ( ind ) NEXT(indt) = 0;
                    789:   dp_true_nf(ind,f,ps,1,&nm,(P *)&dn);
                    790:   if ( !nm ) error("dp_inv_or_split : input is 0");
                    791:   f = nm;
                    792:
                    793:   dp_mbase(gb,&mblist);
                    794:   dim = length(mblist);
                    795:   mb = (DP *)MALLOC(dim*sizeof(DP));
                    796:   for ( i = 0, t = mblist; i < dim; i++, t = NEXT(t) )
                    797:     mb[dim-i-1] = (DP)BDY(t);
                    798:   nv = mb[0]->nv;
                    799:   ln = ONE;
                    800:   simp = (DAlg *)MALLOC(dim*sizeof(DAlg));
                    801:   for ( i = 0; i < dim; i++ ) {
                    802:     if ( DP_Print ) { fprintf(asir_out,"."); fflush(asir_out); }
                    803:     m = mb[i];
                    804:     for ( j = i-1; j >= 0; j-- )
                    805:       if ( dp_redble(m,mb[j]) )
                    806:         break;
                    807:     if ( j >= 0 ) {
                    808:       dp_subd(m,mb[j],&d);
                    809:       if ( simp[j] ) {
                    810:         muld(CO,d,simp[j]->nm,&u);
                    811:         dp_true_nf(ind,u,ps,1,&nm,(P *)&dn);
                    812:         mulz(simp[j]->dn,dn,&dn1);
                    813:         MKDAlg(nm,dn1,simp[i]);
                    814:       } else
                    815:         simp[i] = 0;
                    816:     } else {
                    817:       dp_true_nf(ind,f,ps,1,&nm,(P *)&dn);
                    818:       MKDAlg(nm,dn,simp[i]);
                    819:     }
                    820:     if ( simp[i] ) {
1.2     ! noro      821:       gcdz(simp[i]->dn,ln,&gn); divsz(ln,gn,&qn);
1.1       noro      822:       mulz(simp[i]->dn,qn,&ln);
                    823:     }
                    824:   }
                    825:   absz(ln,&dn);
                    826:   MKMAT(mobj,dim,dim+1);
                    827:   mat = (Z **)BDY(mobj);
                    828:   mat[0][dim] = dn;
                    829:   for ( j = 0; j < dim; j++ ) {
                    830:     if ( simp[j] ) {
                    831:       divq((Q)dn,(Q)simp[j]->dn,&mul);
                    832:       for ( i = dim-1, mp = BDY(simp[j]->nm); mp && i >= 0; i-- )
                    833:         if ( dl_equal(nv,BDY(mb[i])->dl,mp->dl) ) {
                    834:           mulq(mul,(Q)mp->c,(Q *)&mat[i][j]);
                    835:           mp = NEXT(mp);
                    836:         }
                    837:     }
                    838:   }
                    839:   get_eg(&eg0);
                    840:   rank = generic_gauss_elim_hensel_dalg(mobj,mb,&sol,&dnsol,&rinfo,&cinfo);
                    841:   get_eg(&eg1); add_eg(&eg_le,&eg0,&eg1);
                    842:   if ( cinfo[0] == dim ) {
                    843:     /* the input is invertible */
                    844:     solmat = (Z **)BDY(sol);
                    845:     for ( i = dim-1, mp0 = 0; i >= 0; i-- )
                    846:       if ( solmat[i][0] ) {
                    847:         NEXTMP(mp0,mp);
                    848:         mp->c = (Obj)solmat[i][0];
                    849:         mp->dl = BDY(mb[i])->dl;
                    850:       }
                    851:     NEXT(mp) = 0; MKDP(nv,mp0,*inv);
                    852:     return 0;
                    853:   } else {
                    854:     /* the input is not invertible */
                    855:     nparam = sol->col;
                    856:     solmat = (Z **)BDY(sol);
                    857:     nd0 = 0;
                    858:     for ( k = 0; k < nparam; k++ ) {
                    859:       /* construct a new basis element */
                    860:       m = mb[cinfo[k]];
                    861:       mp0 = 0;
                    862:       NEXTMP(mp0,mp);
                    863:       chsgnz(dnsol,&dn1); mp->c = (Obj)dn1;
                    864:       mp->dl = BDY(m)->dl;
                    865:       /* skip the last parameter */
                    866:       for ( l = rank-2; l >= 0; l-- ) {
                    867:         if ( solmat[l][k] ) {
                    868:           NEXTMP(mp0,mp);
                    869:           mp->c = (Obj)solmat[l][k];
                    870:           mp->dl = BDY(mb[rinfo[l]])->dl;
                    871:         }
                    872:       }
                    873:       NEXT(mp) = 0; MKDP(nv,mp0,u);
                    874:       NEXTNODE(nd0,nd);
                    875:       BDY(nd) = (pointer)u;
                    876:       NEXT(nd) = 0;
                    877:     }
                    878:     NEXT(nd) = 0;
                    879:     return nd0;
                    880:   }
                    881: }
                    882:
                    883: void chsgndalg(DAlg a,DAlg *c)
                    884: {
                    885:   DP nm;
                    886:   Q t;
                    887:
                    888:   if ( !a ) *c = 0;
                    889:   else if ( NID(a) == N_Q ) {
                    890:     chsgnq((Q)a,&t); *c = (DAlg)t;
                    891:   } else {
                    892:     chsgnd(a->nm,&nm);
                    893:     MKDAlg(nm,a->dn,*c);
                    894:   }
                    895: }
                    896:
                    897: void pwrdalg(DAlg a,Z e,DAlg *c)
                    898: {
                    899:   NumberField nf;
                    900:   DAlg t,z,y;
                    901:   Q q;
                    902:   Z en,qn,rn,two;
                    903:   int ret;
                    904:
                    905:   if ( !(nf=current_numberfield) )
                    906:     error("pwrdalg : current_numberfield is not set");
                    907:   if ( !a )
                    908:     *c = !e ? (DAlg)ONE : 0;
                    909:   else if ( NID(a) == N_Q ) {
                    910:     pwrq((Q)a,(Q)e,&q); *c = (DAlg)q;
                    911:   } else if ( !e )
                    912:     *c = nf->one;
                    913:   else if ( UNIZ(e) )
                    914:     *c = a;
                    915:   else {
                    916:     if ( sgnz(e) < 0 ) {
                    917:       ret = invdalg(a,&t);
                    918:       if ( !ret )
                    919:         error("pwrdalg : the denominator is not invertible");
                    920:       a = t;
                    921:     }
                    922:     absz(e,&en);
                    923:     y = nf->one;
                    924:     z = a;
1.2     ! noro      925:     STOZ(2,two);
1.1       noro      926:     while ( 1 ) {
                    927:       divqrz(en,two,&qn,&rn); en = qn;
                    928:       if ( rn ) {
                    929:         muldalg(z,y,&t); y = t;
                    930:         if ( !en ) {
                    931:           *c = y;
                    932:           return;
                    933:         }
                    934:       }
                    935:       muldalg(z,z,&t); z = t;
                    936:     }
                    937:   }
                    938: }
                    939:
                    940: int cmpdalg(DAlg a,DAlg b)
                    941: {
                    942:   DAlg c;
                    943:
                    944:   subdalg(a,b,&c);
                    945:   if ( !c ) return 0;
                    946:   else
                    947:     return sgnq((Q)BDY(c->nm)->c);
                    948: }
                    949:
                    950: /* convert da to a univariate poly; return the position of variable */
                    951:
                    952: int dalgtoup(DAlg da,P *up,Z *dn)
                    953: {
                    954:   int nv,i,hi,current_d;
                    955:   DCP dc0,dc;
                    956:   MP h,mp0,mp,t;
                    957:   DL hd,d;
                    958:   DP c;
                    959:   DAlg cc;
                    960:   P v;
                    961:
                    962:   nv = da->nm->nv;
                    963:   h = BDY(da->nm);
                    964:   *dn = da->dn;
                    965:   hd = h->dl;
                    966:   for ( i = 0; i < nv; i++ )
                    967:     if ( hd->d[i] ) break;
                    968:   hi = i;
                    969:   current_d = hd->d[i];
                    970:   dc0 = 0;
                    971:   mp0 = 0;
                    972:   for ( t = h; t; t = NEXT(t) ) {
                    973:     NEWDL(d,nv);
                    974:     for ( i = 0; i <= hi; i++ ) d->d[i] = 0;
                    975:     for ( ; i < nv; i++ ) d->d[i] = t->dl->d[i];
                    976:     d->td = t->dl->td - t->dl->d[hi];
                    977:     if ( t->dl->d[hi] != current_d ) {
                    978:       NEXT(mp) = 0; MKDP(nv,mp0,c); MKDAlg(c,ONE,cc);
1.2     ! noro      979:       NEXTDC(dc0,dc); STOZ(current_d,DEG(dc)); COEF(dc) = (P)cc;
1.1       noro      980:       current_d = t->dl->d[hi];
                    981:       mp0 = 0;
                    982:     }
                    983:     NEXTMP(mp0,mp);
                    984:     mp->c = t->c; mp->dl = d;
                    985:   }
                    986:   NEXT(mp) = 0; MKDP(nv,mp0,c); MKDAlg(c,ONE,cc);
1.2     ! noro      987:   NEXTDC(dc0,dc); STOZ(current_d,DEG(dc)); COEF(dc) = (P)cc;
1.1       noro      988:   NEXT(dc) = 0;
                    989:   makevar("x",&v);
                    990:   MKP(VR(v),dc0,*up);
                    991:   return hi;
                    992: }
                    993:

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