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

Annotation of OpenXM_contrib2/asir2018/builtin/algnum.c, Revision 1.2

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.2     ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2018/builtin/algnum.c,v 1.1 2018/09/19 05:45:05 noro Exp $
1.1       noro       49: */
                     50: #include "ca.h"
                     51: #include "parse.h"
                     52:
                     53: void Pdefpoly(), Pnewalg(), Pmainalg(), Palgtorat(), Prattoalg(), Pgetalg();
                     54: void Palg(), Palgv(), Pgetalgtree();
                     55: void Pinvalg_le();
                     56: void Pset_field(),Palgtodalg(),Pdalgtoalg();
                     57: void Pinv_or_split_dalg();
                     58: void Pdalgtoup();
                     59: void Pget_field_defpoly();
                     60: void Pget_field_generator();
                     61:
                     62: void mkalg(P,Alg *);
                     63: int cmpalgp(P,P);
                     64: void algptop(P,P *);
                     65: void algtorat(Num,Obj *);
                     66: void rattoalg(Obj,Alg *);
                     67: void ptoalgp(P,P *);
                     68: void clctalg(P,VL *);
                     69: void get_algtree(Obj f,VL *r);
                     70: void Pinvalg_chrem();
                     71: void Pdalgtodp();
                     72: void Pdptodalg();
                     73:
                     74: struct ftab alg_tab[] = {
                     75:   {"set_field",Pset_field,-3},
                     76:   {"get_field_defpoly",Pget_field_defpoly,1},
                     77:   {"get_field_generator",Pget_field_generator,1},
                     78:   {"algtodalg",Palgtodalg,1},
                     79:   {"dalgtoalg",Pdalgtoalg,1},
                     80:   {"dalgtodp",Pdalgtodp,1},
                     81:   {"dalgtoup",Pdalgtoup,1},
                     82:   {"dptodalg",Pdptodalg,1},
                     83:   {"inv_or_split_dalg",Pinv_or_split_dalg,1},
                     84:   {"invalg_chrem",Pinvalg_chrem,2},
                     85:   {"invalg_le",Pinvalg_le,1},
                     86:   {"defpoly",Pdefpoly,1},
                     87:   {"newalg",Pnewalg,1},
                     88:   {"mainalg",Pmainalg,1},
                     89:   {"algtorat",Palgtorat,1},
                     90:   {"rattoalg",Prattoalg,1},
                     91:   {"getalg",Pgetalg,1},
                     92:   {"getalgtree",Pgetalgtree,1},
                     93:   {"alg",Palg,1},
                     94:   {"algv",Palgv,1},
                     95:   {0,0,0},
                     96: };
                     97:
                     98: static int UCN,ACNT;
                     99:
                    100: void Pset_field(NODE arg,Q *rp)
                    101: {
                    102:   int ac;
                    103:   NODE a0,a1;
                    104:   VL vl0,vl;
                    105:   struct order_spec *spec;
                    106:
                    107:   if ( (ac = argc(arg)) == 1 )
                    108:     setfield_dalg(BDY((LIST)ARG0(arg)));
                    109:   else if ( ac == 3 ) {
                    110:     a0 = BDY((LIST)ARG0(arg));
                    111:     a1 = BDY((LIST)ARG1(arg));
                    112:     for ( vl0 = 0; a1; a1 = NEXT(a1) ) {
                    113:       NEXTVL(vl0,vl);
                    114:       vl->v = VR((P)BDY(a1));
                    115:     }
                    116:     if ( vl0 ) NEXT(vl) = 0;
                    117:     create_order_spec(0,ARG2(arg),&spec);
                    118:     setfield_gb(a0,vl0,spec);
                    119:   }
                    120:   *rp = 0;
                    121: }
                    122:
                    123: void Palgtodalg(NODE arg,DAlg *rp)
                    124: {
                    125:   algtodalg((Alg)ARG0(arg),rp);
                    126: }
                    127:
                    128: void Pdalgtoalg(NODE arg,Alg *rp)
                    129: {
                    130:   dalgtoalg((DAlg)ARG0(arg),rp);
                    131: }
                    132:
                    133: void Pdalgtodp(NODE arg,LIST *r)
                    134: {
                    135:   NODE b;
                    136:   DP nm;
                    137:   Z dn;
                    138:   DAlg da;
                    139:
                    140:   da = (DAlg)ARG0(arg);
                    141:   nm = da->nm;
                    142:   dn = da->dn;
                    143:   b = mknode(2,nm,dn);
                    144:   MKLIST(*r,b);
                    145: }
                    146:
                    147: void Pdptodalg(NODE arg,DAlg *r)
                    148: {
                    149:   DP d,nm,nm1;
                    150:   MP m;
                    151:   Q c;
                    152:   Z a;
                    153:   DAlg t;
                    154:
                    155:   d = (DP)ARG0(arg);
                    156:   if ( !d ) *r = 0;
                    157:   else {
                    158:     for ( m = BDY(d); m; m = NEXT(m) )
                    159:       if ( !INT((Q)m->c) ) break;
                    160:     if ( !m ) {
                    161:       MKDAlg(d,ONE,t);
                    162:     } else {
                    163:       dp_ptozp(d,&nm);
                    164:       divq((Q)BDY(d)->c,(Q)BDY(nm)->c,&c);
                    165:       nmq(c,&a);
                    166:       muldc(CO,nm,(Obj)a,&nm1);
                    167:       dnq(c,&a);
                    168:       MKDAlg(nm1,a,t);
                    169:     }
                    170:     simpdalg(t,r);
                    171:   }
                    172: }
                    173:
                    174: void Pdalgtoup(NODE arg,LIST *r)
                    175: {
                    176:   NODE b;
                    177:   int pos;
                    178:   P up;
                    179:   DP nm;
                    180:   Z dn;
                    181:   Z q;
                    182:
                    183:   pos = dalgtoup((DAlg)ARG0(arg),&up,&dn);
1.2     ! noro      184:   STOZ(pos,q);
1.1       noro      185:   b = mknode(3,up,dn,q);
                    186:   MKLIST(*r,b);
                    187: }
                    188:
                    189: NODE inv_or_split_dalg(DAlg,DAlg *);
                    190: NumberField  get_numberfield();
                    191:
                    192: void Pget_field_defpoly(NODE arg,DAlg *r)
                    193: {
                    194:   NumberField nf;
                    195:   DP d;
                    196:
                    197:   nf = get_numberfield();
1.2     ! noro      198:   d = nf->ps[ZTOS((Q)ARG0(arg))];
1.1       noro      199:   MKDAlg(d,ONE,*r);
                    200: }
                    201:
                    202: void Pget_field_generator(NODE arg,DAlg *r)
                    203: {
                    204:   int index,n,i;
                    205:   DL dl;
                    206:   MP m;
                    207:   DP d;
                    208:
1.2     ! noro      209:   index = ZTOS((Q)ARG0(arg));
1.1       noro      210:   n = get_numberfield()->n;
                    211:   NEWDL(dl,n);
                    212:   for ( i = 0; i < n; i++ ) dl->d[i] = 0;
                    213:   dl->d[index] = 1; dl->td = 1;
                    214:   NEWMP(m); m->dl = dl; m->c = (Obj)ONE; NEXT(m) = 0;
                    215:   MKDP(n,m,d);
                    216:   MKDAlg(d,ONE,*r);
                    217: }
                    218:
                    219:
                    220: void Pinv_or_split_dalg(NODE arg,Obj *rp)
                    221: {
                    222:   NODE gen,t,nd0,nd;
                    223:   LIST list;
                    224:   int l,i,j,n;
                    225:   DP *ps,*ps1,*psw;
                    226:   NumberField nf;
                    227:   DAlg inv;
                    228:   extern struct order_spec *dp_current_spec;
                    229:   struct order_spec *current_spec;
                    230:
                    231:   gen = inv_or_split_dalg((DAlg)ARG0(arg),&inv);
                    232:   if ( !gen )
                    233:     *rp = (Obj)inv;
                    234:   else {
                    235:     nf = get_numberfield();
                    236:     current_spec = dp_current_spec; initd(nf->spec);
                    237:     l = length(gen);
                    238:     n = nf->n;
                    239:     ps = nf->ps;
                    240:     psw = (DP *)ALLOCA((n+l)*sizeof(DP));
                    241:     for ( i = j = 0; i < n; i++ ) {
                    242:       for ( t = gen; t; t = NEXT(t) )
                    243:         if ( dp_redble(ps[i],(DP)BDY(t)) ) break;
                    244:       if ( !t )
                    245:         psw[j++] = ps[i];
                    246:     }
                    247:     nd0  = 0;
                    248:     /* gen[0] < gen[1] < ... */
                    249:     /* psw[0] > psw[1] > ... */
                    250:     for ( i = j-1, t = gen; i >= 0 && t; ) {
                    251:       NEXTNODE(nd0,nd);
                    252:       if ( compd(CO,psw[i],(DP)BDY(t)) > 0 ) {
                    253:         BDY(nd) = BDY(t); t = NEXT(t);
                    254:       } else
                    255:         BDY(nd) = (pointer)psw[i--];
                    256:     }
                    257:     for ( ; i >= 0; i-- ) {
                    258:       NEXTNODE(nd0,nd); BDY(nd) = (pointer)psw[i];
                    259:     }
                    260:     for ( ; t; t = NEXT(t) ) {
                    261:       NEXTNODE(nd0,nd); BDY(nd) = BDY(t);
                    262:     }
                    263:     NEXT(nd) = 0;
                    264:     MKLIST(list,nd0);
                    265:     initd(current_spec);
                    266:     *rp = (Obj)list;
                    267:   }
                    268: }
                    269:
                    270: void Pnewalg(arg,rp)
                    271: NODE arg;
                    272: Alg *rp;
                    273: {
                    274:   P p;
                    275:   VL vl;
                    276:   P c;
                    277:
                    278:   p = (P)ARG0(arg);
                    279:   if ( !p || OID(p) != O_P )
                    280:     error("newalg : invalid argument");
                    281:   clctv(CO,p,&vl);
                    282:   if ( NEXT(vl) )
                    283:     error("newalg : invalid argument");
                    284:   c = COEF(DC(p));
                    285:   if ( !NUM(c) || !RATN(c) )
                    286:     error("newalg : invalid argument");
                    287:   mkalg(p,rp);
                    288: }
                    289:
                    290: void mkalg(p,r)
                    291: P p;
                    292: Alg *r;
                    293: {
                    294:   VL vl,mvl,nvl;
                    295:   V a,tv;
                    296:   char buf[BUFSIZ];
                    297:   char *name;
                    298:   P x,t,s;
                    299:   Num c;
                    300:   DCP dc,dcr,dcr0;
                    301:
                    302:   for ( vl = ALG; vl; vl = NEXT(vl) )
                    303:     if ( !cmpalgp(p,(P)vl->v->attr) ) {
                    304:       a = vl->v; break;
                    305:     }
                    306:   if ( !vl ) {
                    307:     NEWVL(vl); NEXT(vl) = ALG; ALG = vl;
                    308:     NEWV(a); vl->v = a;
                    309:     sprintf(buf,"#%d",ACNT++);
                    310:     name = (char *)MALLOC(strlen(buf)+1);
                    311:     strcpy(name,buf); NAME(a) = name;
                    312:
                    313:     for ( dc = DC(p), dcr0 = 0; dc; dc = NEXT(dc) ) {
                    314:       NEXTDC(dcr0,dcr); DEG(dcr) = DEG(dc); c = (Num)COEF(dc);
                    315:       if ( NID(c) != N_A )
                    316:         COEF(dcr) = (P)c;
                    317:       else
                    318:         COEF(dcr) = (P)BDY(((Alg)c));
                    319:     }
                    320:     NEXT(dcr) = 0; MKP(a,dcr0,t); a->attr = (pointer)t;
                    321:
                    322:     sprintf(buf,"t%s",name); makevar(buf,&s);
                    323:
                    324:     if ( NEXT(ALG) ) {
                    325:       tv = (V)NEXT(ALG)->v->priv;
                    326:       for ( vl = CO; NEXT(NEXT(vl)); vl = NEXT(vl) );
                    327:       nvl = NEXT(vl); NEXT(vl) = 0;
                    328:       for ( vl = CO; NEXT(vl) && (NEXT(vl)->v != tv); vl = NEXT(vl) );
                    329:       mvl = NEXT(vl); NEXT(vl) = nvl; NEXT(nvl) = mvl;
                    330:     }
                    331:
                    332:     a->priv = (pointer)VR(s); VR(s)->priv = (pointer)a;
                    333:   }
                    334:   MKV(a,x); MKAlg(x,*r);
                    335: }
                    336:
                    337: int cmpalgp(p,defp)
                    338: P p,defp;
                    339: {
                    340:   DCP dc,dcd;
                    341:   P t;
                    342:
                    343:   for ( dc = DC(p), dcd = DC(defp); dc && dcd;
                    344:     dc = NEXT(dc), dcd = NEXT(dcd) ) {
                    345:     if ( cmpz(DEG(dc),DEG(dcd)) )
                    346:       break;
                    347:     t = NID((Num)COEF(dc)) == N_A ? (P)BDY((Alg)COEF(dc)) : COEF(dc);
                    348:     if ( compp(ALG,t,COEF(dcd)) )
                    349:       break;
                    350:   }
                    351:   if ( dc || dcd )
                    352:     return 1;
                    353:   else
                    354:     return 0;
                    355: }
                    356:
                    357: void Pdefpoly(arg,rp)
                    358: NODE arg;
                    359: P *rp;
                    360: {
                    361:   asir_assert(ARG0(arg),O_N,"defpoly");
                    362:   algptop((P)VR((P)BDY((Alg)ARG0(arg)))->attr,rp);
                    363: }
                    364:
                    365: void Pmainalg(arg,r)
                    366: NODE arg;
                    367: Alg *r;
                    368: {
                    369:   Num c;
                    370:   V v;
                    371:   P b;
                    372:
                    373:   c = (Num)(ARG0(arg));
                    374:   if ( NID(c) <= N_R )
                    375:     *r = 0;
                    376:   else {
                    377:     v = VR((P)BDY((Alg)c)); MKV(v,b); MKAlg(b,*r);
                    378:   }
                    379: }
                    380:
                    381: void Palgtorat(arg,rp)
                    382: NODE arg;
                    383: Obj *rp;
                    384: {
                    385:   asir_assert(ARG0(arg),O_N,"algtorat");
                    386:   algtorat((Num)ARG0(arg),rp);
                    387: }
                    388:
                    389: void Prattoalg(arg,rp)
                    390: NODE arg;
                    391: Alg *rp;
                    392: {
                    393:   asir_assert(ARG0(arg),O_R,"rattoalg");
                    394:   rattoalg((Obj)ARG0(arg),rp);
                    395: }
                    396:
                    397: void Pgetalg(arg,rp)
                    398: NODE arg;
                    399: LIST *rp;
                    400: {
                    401:   Obj t;
                    402:   P p;
                    403:   VL vl;
                    404:   Num a;
                    405:   Alg b;
                    406:   NODE n0,n;
                    407:
                    408:   if ( !(a = (Num)ARG0(arg)) || NID(a) <= N_R )
                    409:     vl = 0;
                    410:   else {
                    411:     t = BDY((Alg)a);
                    412:     switch ( OID(t) ) {
                    413:       case O_P: case O_R:
                    414:         clctvr(ALG,t,&vl); break;
                    415:       default:
                    416:         vl = 0; break;
                    417:     }
                    418:   }
                    419:   for ( n0 = 0; vl; vl = NEXT(vl) ) {
                    420:     NEXTNODE(n0,n); MKV(vl->v,p); MKAlg(p,b); BDY(n) = (pointer)b;
                    421:   }
                    422:   if ( n0 )
                    423:     NEXT(n) = 0;
                    424:   MKLIST(*rp,n0);
                    425: }
                    426:
                    427: void Pgetalgtree(arg,rp)
                    428: NODE arg;
                    429: LIST *rp;
                    430: {
                    431:   Obj t;
                    432:   P p;
                    433:   VL vl,vl1,vl2;
                    434:   Num a;
                    435:   Alg b;
                    436:   NODE n0,n;
                    437:
                    438: #if 0
                    439:   if ( !(a = (Num)ARG0(arg)) || NID(a) <= N_R )
                    440:     vl = 0;
                    441:   else {
                    442:     t = BDY((Alg)a);
                    443:     switch ( OID(t) ) {
                    444:       case O_P:
                    445:         clctalg((P)t,&vl); break;
                    446:       case O_R:
                    447:         clctalg(NM((R)t),&vl1);
                    448:         clctalg(DN((R)t),&vl2);
                    449:         mergev(ALG,vl1,vl2,&vl); break;
                    450:       default:
                    451:         vl = 0; break;
                    452:     }
                    453:   }
                    454: #else
                    455:   get_algtree((Obj)ARG0(arg),&vl);
                    456: #endif
                    457:   for ( n0 = 0; vl; vl = NEXT(vl) ) {
                    458:     NEXTNODE(n0,n); MKV(vl->v,p); MKAlg(p,b); BDY(n) = (pointer)b;
                    459:   }
                    460:   if ( n0 )
                    461:     NEXT(n) = 0;
                    462:   MKLIST(*rp,n0);
                    463: }
                    464:
                    465: void clctalg(p,vl)
                    466: P p;
                    467: VL *vl;
                    468: {
                    469:   int n,i;
                    470:   VL tvl;
                    471:   VN vn,vn1;
                    472:   P d;
                    473:   DCP dc;
                    474:
                    475:   for ( n = 0, tvl = ALG; tvl; tvl = NEXT(tvl), n++ );
                    476:   vn = (VN) ALLOCA((n+1)*sizeof(struct oVN));
                    477:   for ( i = n-1, tvl = ALG; tvl; tvl = NEXT(tvl), i-- ) {
                    478:     vn[i].v = tvl->v;
                    479:     vn[i].n = 0;
                    480:   }
                    481:   markv(vn,n,p);
                    482:   for ( i = n-1; i >= 0; i-- ) {
                    483:     if ( !vn[i].n )
                    484:       continue;
                    485:     d = (P)vn[i].v->attr;
                    486:     for ( dc = DC(d); dc; dc = NEXT(dc) )
                    487:       markv(vn,i,COEF(dc));
                    488:   }
                    489:   vn1 = (VN) ALLOCA((n+1)*sizeof(struct oVN));
                    490:   for ( i = 0; i < n; i++ ) {
                    491:     vn1[i].v = vn[n-1-i].v; vn1[i].n = vn[n-1-i].n;
                    492:   }
                    493:   vntovl(vn1,n,vl);
                    494: }
                    495:
                    496: void Palg(arg,rp)
                    497: NODE arg;
                    498: Alg *rp;
                    499: {
                    500:   Q a;
                    501:   VL vl;
                    502:   P x;
                    503:   int n;
                    504:
                    505:   a = (Q)ARG0(arg);
                    506:   if ( a && (OID(a) != O_N || NID(a) != N_Q || !INT(a)) )
                    507:     *rp = 0;
                    508:   else {
1.2     ! noro      509:     n = ACNT-ZTOS(a)-1;
1.1       noro      510:     for ( vl = ALG; vl && n; vl = NEXT(vl), n-- );
                    511:     if ( vl ) {
                    512:       MKV(vl->v,x); MKAlg(x,*rp);
                    513:     } else
                    514:       *rp = 0;
                    515:   }
                    516: }
                    517:
                    518: void Palgv(arg,rp)
                    519: NODE arg;
                    520: Obj *rp;
                    521: {
                    522:   Q a;
                    523:   VL vl;
                    524:   P x;
                    525:   int n;
                    526:   Alg b;
                    527:
                    528:   a = (Q)ARG0(arg);
                    529:   if ( a && (OID(a) != O_N || NID(a) != N_Q || !INT(a)) )
                    530:     *rp = 0;
                    531:   else {
1.2     ! noro      532:     n = ACNT-ZTOS(a)-1;
1.1       noro      533:     for ( vl = ALG; vl && n; vl = NEXT(vl), n-- );
                    534:     if ( vl ) {
                    535:       MKV(vl->v,x); MKAlg(x,b); algtorat((Num)b,rp);
                    536:     } else
                    537:       *rp = 0;
                    538:   }
                    539: }
                    540:
                    541: void algptop(p,r)
                    542: P p,*r;
                    543: {
                    544:   DCP dc,dcr,dcr0;
                    545:
                    546:   if ( NUM(p) )
                    547:     *r = (P)p;
                    548:   else {
                    549:     for ( dc = DC(p), dcr0 = 0; dc; dc = NEXT(dc) ) {
                    550:       NEXTDC(dcr0,dcr); DEG(dcr) = DEG(dc);
                    551:       algptop(COEF(dc),&COEF(dcr));
                    552:     }
                    553:     NEXT(dcr) = 0; MKP((V)(VR(p)->priv),dcr0,*r);
                    554:   }
                    555: }
                    556:
                    557: void algtorat(n,r)
                    558: Num n;
                    559: Obj *r;
                    560: {
                    561:   Obj obj;
                    562:   P nm,dn;
                    563:
                    564:   if ( !n || NID(n) <= N_R )
                    565:     *r = (Obj)n;
                    566:   else {
                    567:     obj = BDY((Alg)n);
                    568:     if ( ID(obj) <= O_P )
                    569:       algptop((P)obj,(P *)r);
                    570:     else {
                    571:       algptop(NM((R)obj),&nm); algptop(DN((R)obj),&dn);
                    572:       divr(CO,(Obj)nm,(Obj)dn,r);
                    573:     }
                    574:   }
                    575: }
                    576:
                    577: void rattoalg(obj,n)
                    578: Obj obj;
                    579: Alg *n;
                    580: {
                    581:   P nm,dn;
                    582:   Obj t;
                    583:
                    584:   if ( !obj || ID(obj) == O_N )
                    585:     *n = (Alg)obj;
                    586:   else if ( ID(obj) == O_P ) {
                    587:     ptoalgp((P)obj,(P *)&t); MKAlg(t,*n);
                    588:   } else {
                    589:     ptoalgp(NM((R)obj),&nm); ptoalgp(DN((R)obj),&dn);
                    590:     divr(ALG,(Obj)nm,(Obj)dn,&t); MKAlg(t,*n);
                    591:   }
                    592: }
                    593:
                    594: void ptoalgp(p,r)
                    595: P p,*r;
                    596: {
                    597:   DCP dc,dcr,dcr0;
                    598:
                    599:   if ( NUM(p) )
                    600:     *r = (P)p;
                    601:   else {
                    602:     for ( dc = DC(p), dcr0 = 0; dc; dc = NEXT(dc) ) {
                    603:       NEXTDC(dcr0,dcr); DEG(dcr) = DEG(dc);
                    604:       ptoalgp(COEF(dc),&COEF(dcr));
                    605:     }
                    606:     NEXT(dcr) = 0; MKP((V)(VR(p)->priv),dcr0,*r);
                    607:   }
                    608: }
                    609:
                    610: void Pinvalg_chrem(NODE arg,LIST *r)
                    611: {
                    612:   NODE n;
                    613:
                    614:   inva_chrem((P)ARG0(arg),(P)ARG1(arg),&n);
                    615:   MKLIST(*r,n);
                    616: }
                    617:
                    618: void invalg_le(Alg a,LIST *r);
                    619:
                    620: void Pinvalg_le(NODE arg,LIST *r)
                    621: {
                    622:   invalg_le((Alg)ARG0(arg),r);
                    623: }
                    624:
                    625: typedef struct oMono_nf {
                    626:   DP mono;
                    627:   DP nf;
                    628:   Z dn;
                    629: } *Mono_nf;
                    630:
                    631: void invalg_le(Alg a,LIST *r)
                    632: {
                    633:   Alg inv;
                    634:   MAT mobj,sol;
                    635:   int *rinfo,*cinfo;
                    636:   P p,dn,ap;
                    637:   VL vl,tvl;
                    638:   Q c1,c2,c3,cont,c,mul;
                    639:   Z two,iq,dn0,dn1,dnsol;
                    640:   int i,j,n,len,k;
                    641:   MP mp,mp0;
                    642:   DP dp,nm,nm1,m,d,u,u1;
                    643:   NODE b,b1,hlist,mblist,t,s,rev0,rev,hist;
                    644:   DP *ps;
                    645:   struct order_spec *spec;
                    646:   Mono_nf h,h1;
                    647:   Z nq,nr,nl,ng;
                    648:   Q **mat,**solmat;
                    649:   Q *w;
                    650:   int *wi;
                    651:
                    652:   ap = (P)BDY(a);
                    653:   asir_assert(ap,O_P,"invalg_le");
                    654:
                    655:   /* collecting algebraic numbers */
                    656:   clctalg(ap,&vl);
                    657:
                    658:   /* setup */
                    659:   ptozp(ap,1,&c,&p);
1.2     ! noro      660:   STOZ(2,two); create_order_spec(0,(Obj)two,&spec); initd(spec);
1.1       noro      661:   for ( n = 0, tvl = vl; tvl; tvl = NEXT(tvl), n++ );
                    662:   ps = (DP *)ALLOCA(n*sizeof(DP));
                    663:
                    664:   /* conversion to DP */
                    665:   for ( i = 0, tvl = vl; i < n; i++, tvl = NEXT(tvl) ) {
                    666:     ptod(ALG,vl,tvl->v->attr,&ps[i]);
                    667:   }
                    668:   ptod(ALG,vl,p,&dp);
                    669:   /* index list */
                    670:   for ( b = 0, i = 0; i < n; i++ ) {
1.2     ! noro      671:     STOZ(i,iq); MKNODE(b1,(pointer)iq,b); b = b1;
1.1       noro      672:   }
                    673:   /* simplification */
                    674:   dp_true_nf(b,dp,ps,1,&nm,(P *)&dn);
                    675:
                    676:   /* construction of NF table */
                    677:
                    678:   /* stdmono: <<0,...,0>> < ... < max */
                    679:   for ( hlist = 0, i = 0; i < n; i++ ) {
                    680:     MKNODE(b1,(pointer)ps[i],hlist); hlist = b1;
                    681:   }
                    682:   dp_mbase(hlist,&rev0);
                    683:   for ( mblist = 0, rev = rev0; rev; rev = NEXT(rev) ) {
                    684:     MKNODE(b1,BDY(rev),mblist); mblist = b1;
                    685:   }
                    686:   dn0 = ONE;
                    687:   for ( hist = 0, t = mblist; t; t = NEXT(t) ) {
                    688:     /* searching a predecessor */
                    689:     for ( m = (DP)BDY(t), s = hist; s; s = NEXT(s) ) {
                    690:       h = (Mono_nf)BDY(s);
                    691:       if ( dp_redble(m,h->mono) )
                    692:         break;
                    693:     }
                    694:     h1 = (Mono_nf)ALLOCA(sizeof(struct oMono_nf));
                    695:     if ( s ) {
                    696:       dp_subd(m,h->mono,&d);
                    697:       muld(CO,d,h->nf,&u);
                    698:       dp_true_nf(b,u,ps,1,&nm1,(P *)&dn1);
                    699:       mulz(h->dn,dn1,&h1->dn);
                    700:     } else {
                    701:       muld(CO,m,nm,&u);
                    702:       dp_true_nf(b,u,ps,1,&nm1,(P *)&dn1);
                    703:       h1->dn = dn1;
                    704:     }
                    705:     h1->mono = m;
                    706:     h1->nf = nm1;
                    707:     MKNODE(b1,(pointer)h1,hist); hist = b1;
                    708:
                    709:     /* dn0 = LCM(dn0,h1->dn) */
1.2     ! noro      710:     gcdz(dn0,h1->dn,&ng); divsz(dn0,ng,&nq);
1.1       noro      711:     mulz(nq,h1->dn,&nl); absz(nl,&dn0);
                    712:   }
                    713:   /* create a matrix */
                    714:   len = length(mblist);
                    715:   MKMAT(mobj,len,len+1);
                    716:   mat = (Q **)BDY(mobj);
                    717:   mat[len-1][len] = (Q)dn0;
                    718:   for ( j = 0, t = hist; j < len; j++, t = NEXT(t) ) {
                    719:     h = (Mono_nf)BDY(t);
                    720:     nm1 = h->nf;
                    721:     divq((Q)dn0,(Q)h->dn,&mul);
                    722:     for ( i = 0, rev = rev0, mp = BDY(nm1); mp && i < len; i++, rev = NEXT(rev) )
                    723:       if ( dl_equal(n,BDY((DP)BDY(rev))->dl,mp->dl) ) {
                    724:         mulq(mul,(Q)mp->c,&mat[i][j]);
                    725:         mp = NEXT(mp);
                    726:       }
                    727:   }
                    728:   generic_gauss_elim_hensel(mobj,&sol,&dnsol,&rinfo,&cinfo);
                    729:   solmat = (Q **)BDY(sol);
                    730:   for ( i = 0, t = rev0, mp0 = 0; i < len; i++, t = NEXT(t) )
                    731:     if ( solmat[i][0] ) {
                    732:       NEXTMP(mp0,mp);
                    733:       mp->c = (Obj)solmat[i][0];
                    734:       mp->dl = BDY((DP)BDY(t))->dl;
                    735:     }
                    736:   NEXT(mp) = 0; MKDP(n,mp0,u);
                    737:   dp_ptozp(u,&u1);
                    738:   divq((Q)BDY(u)->c,(Q)BDY(u1)->c,&cont);
                    739:   dtop(ALG,vl,u1,(Obj *)&ap);
                    740:   MKAlg(ap,inv);
                    741:   mulq((Q)dnsol,(Q)dn,&c1);
                    742:   mulq(c1,c,&c2);
                    743:   divq(c2,cont,&c3);
                    744:   b = mknode(2,inv,c3);
                    745:   MKLIST(*r,b);
                    746: }
                    747:
                    748: void get_algtree(Obj f,VL *r)
                    749: {
                    750:   VL vl1,vl2,vl3;
                    751:   Obj t;
                    752:   DCP dc;
                    753:   NODE b;
                    754:   pointer *a;
                    755:   pointer **m;
                    756:   int len,row,col,i,j,l;
                    757:
                    758:   if ( !f ) *r = 0;
                    759:   else
                    760:     switch ( OID(f) ) {
                    761:       case O_N:
                    762:         if ( NID((Num)f) != N_A ) *r = 0;
                    763:         else  {
                    764:           t = BDY((Alg)f);
                    765:           switch ( OID(t) ) {
                    766:             case O_P:
                    767:               clctalg((P)t,r); break;
                    768:             case O_R:
                    769:               clctalg(NM((R)t),&vl1);
                    770:               clctalg(DN((R)t),&vl2);
                    771:               mergev(ALG,vl1,vl2,r); break;
                    772:             default:
                    773:               *r = 0; break;
                    774:           }
                    775:         }
                    776:         break;
                    777:       case O_P:
                    778:         vl1 = 0;
                    779:         for ( dc = DC((P)f); dc; dc = NEXT(dc) ) {
                    780:           get_algtree((Obj)COEF(dc),&vl2);
                    781:           mergev(ALG,vl1,vl2,&vl3);
                    782:           vl1 = vl3;
                    783:         }
                    784:         *r = vl1;
                    785:         break;
                    786:       case O_R:
                    787:         get_algtree((Obj)NM((R)f),&vl1);
                    788:         get_algtree((Obj)DN((R)f),&vl2);
                    789:         mergev(ALG,vl1,vl2,r);
                    790:         break;
                    791:       case O_LIST:
                    792:         vl1 = 0;
                    793:         for ( b = BDY((LIST)f); b; b = NEXT(b) ) {
                    794:           get_algtree((Obj)BDY(b),&vl2);
                    795:           mergev(ALG,vl1,vl2,&vl3);
                    796:           vl1 = vl3;
                    797:         }
                    798:         *r = vl1;
                    799:         break;
                    800:       case O_VECT:
                    801:         vl1 = 0;
                    802:         l = ((VECT)f)->len;
                    803:         a = BDY((VECT)f);
                    804:         for ( i = 0; i < l; i++ ) {
                    805:           get_algtree((Obj)a[i],&vl2);
                    806:           mergev(ALG,vl1,vl2,&vl3);
                    807:           vl1 = vl3;
                    808:         }
                    809:         *r = vl1;
                    810:         break;
                    811:       case O_MAT:
                    812:         vl1 = 0;
                    813:         row = ((MAT)f)->row; col = ((MAT)f)->col;
                    814:         m = BDY((MAT)f);
                    815:         for ( i = 0; i < row; i++ )
                    816:           for ( j = 0; j < col; j++ ) {
                    817:             get_algtree((Obj)m[i][j],&vl2);
                    818:             mergev(ALG,vl1,vl2,&vl3);
                    819:             vl1 = vl3;
                    820:           }
                    821:         *r = vl1;
                    822:         break;
                    823:       default:
                    824:         *r = 0;
                    825:         break;
                    826:     }
                    827: }
                    828:
                    829: void algobjtorat(Obj f,Obj *r)
                    830: {
                    831:   Obj t;
                    832:   DCP dc,dcr,dcr0;
                    833:   P p,nm,dn;
                    834:   R rat;
                    835:   NODE b,s,s0;
                    836:   VECT v;
                    837:   MAT mat;
                    838:   LIST list;
                    839:   pointer *a;
                    840:   pointer **m;
                    841:   int len,row,col,i,j,l;
                    842:
                    843:   if ( !f ) *r = 0;
                    844:   else
                    845:     switch ( OID(f) ) {
                    846:       case O_N:
                    847:         algtorat((Num)f,r);
                    848:         break;
                    849:       case O_P:
                    850:         dcr0 = 0;
                    851:         for ( dc = DC((P)f); dc; dc = NEXT(dc) ) {
                    852:           NEXTDC(dcr0,dcr);
                    853:           algobjtorat((Obj)COEF(dc),&t);
                    854:           COEF(dcr) = (P)t;
                    855:           DEG(dcr) = DEG(dc);
                    856:         }
                    857:         NEXT(dcr) = 0; MKP(VR((P)f),dcr0,p); *r = (Obj)p;
                    858:         break;
                    859:       case O_R:
                    860:         algobjtorat((Obj)NM((R)f),&t); nm = (P)t;
                    861:         algobjtorat((Obj)DN((R)f),&t); dn = (P)t;
                    862:         MKRAT(nm,dn,0,rat); *r = (Obj)rat;
                    863:         break;
                    864:       case O_LIST:
                    865:         s0 = 0;
                    866:         for ( b = BDY((LIST)f); b; b = NEXT(b) ) {
                    867:           NEXTNODE(s0,s);
                    868:           algobjtorat((Obj)BDY(b),&t);
                    869:           BDY(s) = (pointer)t;
                    870:         }
                    871:         NEXT(s) = 0;
                    872:         MKLIST(list,s0);
                    873:         *r = (Obj)list;
                    874:         break;
                    875:       case O_VECT:
                    876:         l = ((VECT)f)->len;
                    877:         a = BDY((VECT)f);
                    878:         MKVECT(v,l);
                    879:         for ( i = 0; i < l; i++ ) {
                    880:           algobjtorat((Obj)a[i],&t);
                    881:           BDY(v)[i] = (pointer)t;
                    882:         }
                    883:         *r = (Obj)v;
                    884:         break;
                    885:       case O_MAT:
                    886:         row = ((MAT)f)->row; col = ((MAT)f)->col;
                    887:         m = BDY((MAT)f);
                    888:         MKMAT(mat,row,col);
                    889:         for ( i = 0; i < row; i++ )
                    890:           for ( j = 0; j < col; j++ ) {
                    891:             algobjtorat((Obj)m[i][j],&t);
                    892:             BDY(mat)[i][j] = (pointer)t;
                    893:           }
                    894:         *r = (Obj)mat;
                    895:         break;
                    896:       default:
                    897:         *r = f;
                    898:         break;
                    899:     }
                    900: }

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