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

Annotation of OpenXM_contrib2/asir2000/builtin/poly.c, Revision 1.30

1.4       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
1.5       noro       26:  * e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
1.4       noro       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.30    ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2000/builtin/poly.c,v 1.29 2018/03/28 05:27:22 noro Exp $
1.4       noro       49: */
1.1       noro       50: #include "ca.h"
                     51: #include "parse.h"
                     52: #include "base.h"
                     53:
                     54: void Pranp();
                     55:
1.20      noro       56: void Pheadsgn();
1.21      noro       57: void Pmul_trunc(),Pquo_trunc();
1.1       noro       58: void Pumul(),Pumul_ff(),Pusquare(),Pusquare_ff(),Putmul(),Putmul_ff();
                     59: void Pkmul(),Pksquare(),Pktmul();
1.22      noro       60: void Pord(), Premove_vars(), Pcoef0(), Pcoef(), Pdeg(), Pmindeg(), Psetmod();
1.1       noro       61: void Pcoef_gf2n();
                     62: void getcoef(), getdeglist(), mergedeglist(), change_mvar(), restore_mvar();
                     63:
1.2       noro       64: void Pp_mag(),Pmaxblen();
1.1       noro       65: void Pmergelist(), Pch_mv(), Pre_mv(), Pdeglist();
                     66: void Pptomp(),Pmptop();
                     67: void Pptolmp(),Plmptop();
1.12      noro       68: void Pptosfp(),Psfptop(),Psf_galois_action(),Psf_embed(),Psf_find_root();
1.18      noro       69: void Psf_minipoly(),Psf_log(),Psfptopsfp();
1.1       noro       70: void Pptogf2n(),Pgf2ntop(),Pgf2ntovect();
                     71: void Pptogfpn(),Pgfpntop();
                     72: void Pfind_root_gf2n();
1.2       noro       73: void Pumul_specialmod(),Pusquare_specialmod(),Putmul_specialmod();
1.1       noro       74:
                     75: void Pureverse(),Putrunc(),Pudecomp(),Purembymul(),Purembymul_precomp();
                     76: void Puinvmod(),Purevinvmod();
                     77: void Ppwrmod_ff(),Ppwrtab_ff(),Pgeneric_pwrmod_ff();
                     78: void Pkpwrmod_lm(),Pkpwrtab_lm(),Pkgeneric_pwrmod_lm();
                     79:
                     80: void Pkmulum();
                     81: void Pksquareum();
                     82:
                     83: void Pfmultest();
                     84: void Phfmul_lm();
                     85: void Plazy_lm();
                     86:
                     87: void Psetmod_ff();
                     88: void Psimp_ff();
                     89: void Pextdeg_ff();
                     90: void Pcharacteristic_ff();
                     91: void Pfield_type_ff();
                     92: void Pfield_order_ff();
                     93: void Prandom_ff();
                     94:
                     95: void Ptracemod_gf2n();
                     96: void Psparsemod_gf2n();
                     97: void Pmultest_gf2n();
                     98: void Psquaretest_gf2n();
                     99: void Pinvtest_gf2n();
                    100: void Pbininv_gf2n();
                    101: void Prinvtest_gf2n();
                    102: void Pis_irred_gf2();
                    103: void Pis_irred_ddd_gf2();
1.2       noro      104: void Pget_next_fft_prime();
1.3       noro      105: void Puadj_coef();
1.9       noro      106: void Preorder();
                    107: void Phomogeneous_part();
                    108: void Phomogeneous_deg();
1.1       noro      109: void simp_ff(Obj,Obj *);
                    110: void ranp(int,UP *);
                    111: void field_order_ff(N *);
                    112:
                    113: int current_ff;
                    114:
                    115: struct ftab poly_tab[] = {
1.30    ! noro      116:   {"headsgn",Pheadsgn,1},
        !           117:   {"quo_trunc",Pquo_trunc,2},
        !           118:   {"mul_trunc",Pmul_trunc,3},
        !           119:   {"homogeneous_deg",Phomogeneous_deg,-2},
        !           120:   {"homogeneous_part",Phomogeneous_part,-3},
        !           121:   {"reorder",Preorder,3},
        !           122:   {"uadj_coef",Puadj_coef,3},
        !           123:   {"ranp",Pranp,2},
        !           124:   {"p_mag",Pp_mag,1},
        !           125:   {"maxblen",Pmaxblen,1},
        !           126:   {"ord",Pord,-1},
        !           127:   {"remove_vars",Premove_vars,1},
        !           128:   {"delete_vars",Premove_vars,1},
        !           129:   {"coef0",Pcoef0,-3},
        !           130:   {"coef",Pcoef,-3},
        !           131:   {"coef_gf2n",Pcoef_gf2n,2},
        !           132:   {"deg",Pdeg,2},
        !           133:   {"mindeg",Pmindeg,2},
        !           134:   {"setmod",Psetmod,-1},
        !           135:
        !           136:   {"sparsemod_gf2n",Psparsemod_gf2n,-1},
        !           137:
        !           138:   {"setmod_ff",Psetmod_ff,-3},
        !           139:   {"simp_ff",Psimp_ff,1},
        !           140:   {"extdeg_ff",Pextdeg_ff,0},
        !           141:   {"characteristic_ff",Pcharacteristic_ff,0},
        !           142:   {"field_type_ff",Pfield_type_ff,0},
        !           143:   {"field_order_ff",Pfield_order_ff,0},
        !           144:   {"random_ff",Prandom_ff,0},
        !           145:
        !           146:   {"deglist",Pdeglist,2},
        !           147:   {"mergelist",Pmergelist,2},
        !           148:   {"ch_mv",Pch_mv,2},
        !           149:   {"re_mv",Pre_mv,2},
        !           150:
        !           151:   {"ptomp",Pptomp,-2},
        !           152:   {"mptop",Pmptop,1},
        !           153:
        !           154:   {"ptolmp",Pptolmp,1},
        !           155:   {"lmptop",Plmptop,1},
        !           156:
        !           157:   {"sf_galois_action",Psf_galois_action,2},
        !           158:   {"sf_find_root",Psf_find_root,1},
        !           159:   {"sf_minipoly",Psf_minipoly,2},
        !           160:   {"sf_embed",Psf_embed,3},
        !           161:   {"sf_log",Psf_log,1},
        !           162:
        !           163:   {"ptosfp",Pptosfp,1},
        !           164:   {"sfptop",Psfptop,1},
        !           165:   {"sfptopsfp",Psfptopsfp,2},
        !           166:   {"ptogf2n",Pptogf2n,1},
        !           167:   {"gf2ntop",Pgf2ntop,-2},
        !           168:   {"gf2ntovect",Pgf2ntovect,1},
        !           169:
        !           170:   {"ptogfpn",Pptogfpn,1},
        !           171:   {"gfpntop",Pgfpntop,-2},
        !           172:
        !           173:   {"kmul",Pkmul,2},
        !           174:   {"ksquare",Pksquare,1},
        !           175:   {"ktmul",Pktmul,3},
        !           176:
        !           177:   {"umul",Pumul,2},
        !           178:   {"usquare",Pusquare,1},
        !           179:   {"ureverse_inv_as_power_series",Purevinvmod,2},
        !           180:   {"uinv_as_power_series",Puinvmod,2},
        !           181:
        !           182:   {"umul_specialmod",Pumul_specialmod,3},
        !           183:   {"usquare_specialmod",Pusquare_specialmod,2},
        !           184:   {"utmul_specialmod",Putmul_specialmod,4},
        !           185:
        !           186:   {"utmul",Putmul,3},
        !           187:   {"umul_ff",Pumul_ff,2},
        !           188:   {"usquare_ff",Pusquare_ff,1},
        !           189:   {"utmul_ff",Putmul_ff,3},
        !           190:
        !           191:   /* for historical reason */
        !           192:   {"trunc",Putrunc,2},
        !           193:   {"decomp",Pudecomp,2},
        !           194:
        !           195:   {"utrunc",Putrunc,2},
        !           196:   {"udecomp",Pudecomp,2},
        !           197:   {"ureverse",Pureverse,-2},
        !           198:   {"urembymul",Purembymul,2},
        !           199:   {"urembymul_precomp",Purembymul_precomp,3},
        !           200:
        !           201:   {"lazy_lm",Plazy_lm,1},
        !           202:   {"lazy_ff",Plazy_lm,1},
        !           203:
        !           204:   {"pwrmod_ff",Ppwrmod_ff,1},
        !           205:   {"generic_pwrmod_ff",Pgeneric_pwrmod_ff,3},
        !           206:   {"pwrtab_ff",Ppwrtab_ff,2},
        !           207:
        !           208:   {"tracemod_gf2n",Ptracemod_gf2n,3},
        !           209:   {"b_find_root_gf2n",Pfind_root_gf2n,1},
        !           210:
        !           211:   {"is_irred_gf2",Pis_irred_gf2,1},
        !           212:   {"is_irred_ddd_gf2",Pis_irred_ddd_gf2,1},
        !           213:
        !           214:   {"kpwrmod_lm",Pkpwrmod_lm,1},
        !           215:   {"kgeneric_pwrmod_lm",Pkgeneric_pwrmod_lm,3},
        !           216:   {"kpwrtab_lm",Pkpwrtab_lm,2},
        !           217:
        !           218:   {"kmulum",Pkmulum,3},
        !           219:   {"ksquareum",Pksquareum,2},
        !           220:
        !           221:   {"fmultest",Pfmultest,3},
        !           222:   {"hfmul_lm",Phfmul_lm,2},
        !           223:
        !           224:   {"multest_gf2n",Pmultest_gf2n,2},
        !           225:   {"squaretest_gf2n",Psquaretest_gf2n,1},
        !           226:   {"bininv_gf2n",Pbininv_gf2n,2},
        !           227:   {"invtest_gf2n",Pinvtest_gf2n,1},
        !           228:   {"rinvtest_gf2n",Prinvtest_gf2n,0},
        !           229:   {"get_next_fft_prime",Pget_next_fft_prime,2},
        !           230:   {0,0,0},
1.1       noro      231: };
1.20      noro      232:
                    233: void Pheadsgn(NODE arg,Q *rp)
                    234: {
1.30    ! noro      235:   int s;
1.20      noro      236:
1.30    ! noro      237:   s = headsgn((P)ARG0(arg));
        !           238:   STOQ(s,*rp);
1.20      noro      239: }
1.19      noro      240:
                    241: void Pmul_trunc(NODE arg,P *rp)
                    242: {
1.30    ! noro      243:   P p1,p2,p,h;
        !           244:   VL vl0,vl1,vl2,tvl,vl;
        !           245:   VN vn;
        !           246:   int i,n;
        !           247:
        !           248:   p1 = (P)ARG0(arg);
        !           249:   p2 = (P)ARG1(arg);
        !           250:   get_vars((Obj)p1,&vl1); get_vars((Obj)p2,&vl2); mergev(CO,vl1,vl2,&tvl);
        !           251:   p = (P)ARG2(arg);
        !           252:   get_vars((Obj)p,&vl0); mergev(CO,tvl,vl0,&vl);
        !           253:   for ( tvl = vl, n = 0; tvl; tvl = NEXT(tvl), n++ );
        !           254:   vn = (VN) ALLOCA((n+1)*sizeof(struct oVN));
        !           255:   for ( i = 0, tvl = vl; i < n; tvl = NEXT(tvl), i++ ) {
        !           256:     vn[i].v = tvl->v;
        !           257:     vn[i].n = 0;
        !           258:   }
        !           259:   vn[i].v = 0;
        !           260:   vn[i].n = 0;
        !           261:   for ( h = p, i = 0; OID(h) == O_P; h = COEF(DC(h)) ) {
        !           262:     for ( ; vn[i].v != VR(h); i++ );
        !           263:     vn[i].n = QTOS(DEG(DC(h)));
        !           264:   }
        !           265:   mulp_trunc(vl,p1,p2,vn,rp);
1.21      noro      266: }
                    267:
                    268: void Pquo_trunc(NODE arg,P *rp)
                    269: {
1.30    ! noro      270:   P p1,p2,p,h;
        !           271:   VL vl0,vl1,vl2,tvl,vl;
        !           272:   VN vn;
        !           273:   int i,n;
        !           274:
        !           275:   p1 = (P)ARG0(arg);
        !           276:   p2 = (P)ARG1(arg);
        !           277:   if ( !p1 )
        !           278:     *rp = 0;
        !           279:   else if ( NUM(p2) )
        !           280:     divsp(CO,p1,p2,rp);
        !           281:   else {
        !           282:     get_vars((Obj)p1,&vl1); get_vars((Obj)p2,&vl2); mergev(CO,vl1,vl2,&vl);
        !           283:     for ( tvl = vl, n = 0; tvl; tvl = NEXT(tvl), n++ );
        !           284:     vn = (VN) ALLOCA((n+1)*sizeof(struct oVN));
        !           285:     for ( i = 0, tvl = vl; i < n; tvl = NEXT(tvl), i++ ) {
        !           286:       vn[i].v = tvl->v;
        !           287:       vn[i].n = 0;
        !           288:     }
        !           289:     vn[i].v = 0;
        !           290:     vn[i].n = 0;
        !           291:     for ( h = p2, i = 0; OID(h) == O_P; h = COEF(DC(h)) ) {
        !           292:       for ( ; vn[i].v != VR(h); i++ );
        !           293:       vn[i].n = QTOS(DEG(DC(h)));
        !           294:     }
        !           295:     quop_trunc(vl,p1,p2,vn,rp);
        !           296:   }
1.19      noro      297: }
1.1       noro      298:
1.16      noro      299: void Phomogeneous_part(NODE arg,P *rp)
1.9       noro      300: {
1.30    ! noro      301:   if ( argc(arg) == 2 )
        !           302:     exthp(CO,(P)ARG0(arg),QTOS((Q)ARG1(arg)),rp);
        !           303:   else
        !           304:     exthpc_generic(CO,(P)ARG0(arg),QTOS((Q)ARG2(arg)),
        !           305:       VR((P)ARG1(arg)),rp);
1.9       noro      306: }
                    307:
1.16      noro      308: void Phomogeneous_deg(NODE arg,Q *rp)
1.9       noro      309: {
1.30    ! noro      310:   int d;
1.9       noro      311:
1.30    ! noro      312:   if ( argc(arg) == 1 )
        !           313:     d = homdeg((P)ARG0(arg));
        !           314:   else
        !           315:     d = getchomdeg(VR((P)ARG1(arg)),(P)ARG0(arg));
        !           316:   STOQ(d,*rp);
1.9       noro      317: }
                    318:
                    319: /*
1.30    ! noro      320:   p1 = reorder(p,ovl,nvl) => p1 is 'sorted accoding to nvl.
1.9       noro      321: */
                    322:
1.16      noro      323: void Preorder(NODE arg,P *rp)
1.9       noro      324: {
1.30    ! noro      325:   VL ovl,nvl,tvl;
        !           326:   NODE n;
1.9       noro      327:
1.30    ! noro      328:   for ( ovl = 0, n = BDY((LIST)ARG1(arg)); n; n = NEXT(n) ) {
        !           329:     if ( !ovl ) {
        !           330:       NEWVL(ovl); tvl = ovl;
        !           331:     } else {
        !           332:       NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
        !           333:     }
        !           334:       VR(tvl) = VR((P)BDY(n));
        !           335:   }
        !           336:   for ( nvl = 0, n = BDY((LIST)ARG2(arg)); n; n = NEXT(n) ) {
        !           337:     if ( !nvl ) {
        !           338:       NEWVL(nvl); tvl = nvl;
        !           339:     } else {
        !           340:       NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
        !           341:     }
        !           342:       VR(tvl) = VR((P)BDY(n));
        !           343:   }
        !           344:   reorderp(nvl,ovl,(P)ARG0(arg),rp);
1.9       noro      345: }
1.3       noro      346:
                    347: /*
1.30    ! noro      348:   uadj_coef(F,M,M2)
        !           349:   if ( F is a non-negative integer )
        !           350:     return F > M2 ? F-M : M2;
        !           351:   else
        !           352:     F = CN*V^N+...+C0
        !           353:     return uadj_coef(CN,M,M2)*V^N+...+uadj_coef(C0,M,M2);
1.3       noro      354: */
                    355:
1.16      noro      356: void Puadj_coef(NODE arg,P *rp)
1.3       noro      357: {
1.30    ! noro      358:   UP f,r;
        !           359:   N m,m2;
1.3       noro      360:
1.30    ! noro      361:   ptoup((P)ARG0(arg),&f);
        !           362:   m = NM((Q)ARG1(arg));
        !           363:   m2 = NM((Q)ARG2(arg));
        !           364:   adj_coefup(f,m,m2,&r);
        !           365:   uptop(r,rp);
1.3       noro      366: }
                    367:
1.2       noro      368: /*
1.30    ! noro      369:   get_next_fft_prime(StartIndex,Bits)
        !           370:   tries to find smallest Index >= StartIndex s.t.
        !           371:     2^(Bits-1)|FFTprime[Index]-1
        !           372:   return [Index,Mod] or 0 (not exist)
1.2       noro      373: */
                    374:
1.16      noro      375: void Pget_next_fft_prime(NODE arg,LIST *rp)
1.2       noro      376: {
1.30    ! noro      377:   unsigned int mod,d;
        !           378:   int start,bits,i;
        !           379:   NODE n;
        !           380:   Q q,ind;
        !           381:
        !           382:   start = QTOS((Q)ARG0(arg));
        !           383:   bits = QTOS((Q)ARG1(arg));
        !           384:   for ( i = start; ; i++ ) {
        !           385:     get_fft_prime(i,&mod,&d);
        !           386:     if ( !mod ) {
        !           387:       *rp = 0; return;
        !           388:     }
        !           389:     if ( bits <= (int)d ) {
        !           390:       UTOQ(mod,q);
        !           391:       UTOQ(i,ind);
        !           392:       n = mknode(2,ind,q);
        !           393:       MKLIST(*rp,n);
        !           394:       return;
        !           395:     }
        !           396:   }
1.2       noro      397: }
1.1       noro      398:
1.16      noro      399: void Pranp(NODE arg,P *rp)
1.1       noro      400: {
1.30    ! noro      401:   int n;
        !           402:   UP c;
1.1       noro      403:
1.30    ! noro      404:   n = QTOS((Q)ARG0(arg));
        !           405:   ranp(n,&c);
        !           406:   if ( c ) {
        !           407:     up_var = VR((P)ARG1(arg));
        !           408:     uptop(c,rp);
        !           409:   } else
        !           410:     *rp = 0;
1.1       noro      411: }
                    412:
1.16      noro      413: void ranp(int n,UP *nr)
1.1       noro      414: {
1.30    ! noro      415:   int i;
        !           416:   unsigned int r;
        !           417:   Q q;
        !           418:   UP c;
        !           419:
        !           420:   *nr = c = UPALLOC(n);
        !           421:   for ( i = 0; i <= n; i++ ) {
        !           422:     r = random();
        !           423:     UTOQ(r,q);
        !           424:     c->c[i] = (Num)q;
        !           425:   }
        !           426:   for ( i = n; i >= 0 && !c->c[i]; i-- );
        !           427:   if ( i >= 0 )
        !           428:     c->d = i;
        !           429:   else
        !           430:     *nr = 0;
1.1       noro      431: }
                    432:
1.16      noro      433: void Pmaxblen(NODE arg,Q *rp)
1.2       noro      434: {
1.30    ! noro      435:   int l;
        !           436:   l = maxblenp(ARG0(arg));
        !           437:   STOQ(l,*rp);
1.2       noro      438: }
                    439:
1.16      noro      440: void Pp_mag(NODE arg,Q *rp)
1.1       noro      441: {
1.30    ! noro      442:   int l;
        !           443:   l = p_mag(ARG0(arg));
        !           444:   STOQ(l,*rp);
1.1       noro      445: }
                    446:
1.16      noro      447: void Pord(NODE arg,LIST *listp)
1.1       noro      448: {
1.30    ! noro      449:   NODE n,tn,p,opt;
        !           450:   char *key;
        !           451:   Obj value;
        !           452:   int overwrite=0;
        !           453:   LIST l;
        !           454:   VL vl,tvl,svl;
        !           455:   P t;
        !           456:   int i,j;
        !           457:   V *va;
        !           458:   V v;
1.1       noro      459:
1.29      noro      460: #if 0
1.28      noro      461: printf("LASTCO="); printv(CO,LASTCO->v); printf("\n");
1.29      noro      462: #endif
1.30    ! noro      463:   if ( current_option ) {
        !           464:     for ( opt = current_option; opt; opt = NEXT(opt) ) {
        !           465:       p = BDY((LIST)BDY(opt));
        !           466:       key = BDY((STRING)BDY(p));
        !           467:       value = (Obj)BDY(NEXT(p));
        !           468:       if ( !strcmp(key,"overwrite") && value ) {
        !           469:         overwrite = value ? 1 : 0;
        !           470:         break;
        !           471:       }
        !           472:     }
        !           473:   }
        !           474:
        !           475:   if ( argc(arg) ) {
        !           476:     asir_assert(ARG0(arg),O_LIST,"ord");
        !           477:     for ( vl = 0, i = 0, n = BDY((LIST)ARG0(arg));
        !           478:       n; n = NEXT(n), i++ ) {
        !           479:       if ( !vl ) {
        !           480:         NEWVL(vl); tvl = vl;
        !           481:       } else {
        !           482:         NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
        !           483:       }
        !           484:       if ( !(t = (P)BDY(n)) || (OID(t) != O_P) )
        !           485:         error("ord : invalid argument");
        !           486:       VR(tvl) = VR(t);
        !           487:     }
        !           488:     if ( !overwrite ) {
        !           489:       va = (V *)ALLOCA(i*sizeof(V));
        !           490:       for ( j = 0, svl = vl; j < i; j++, svl = NEXT(svl) )
        !           491:         va[j] = VR(svl);
        !           492:       for ( svl = CO; svl; svl = NEXT(svl) ) {
        !           493:         v = VR(svl);
        !           494:         for ( j = 0; j < i; j++ )
        !           495:           if ( v == va[j] )
        !           496:             break;
        !           497:         if ( j == i ) {
        !           498:           if ( !vl ) {
        !           499:             NEWVL(vl); tvl = vl;
        !           500:           } else {
        !           501:             NEWVL(NEXT(tvl)); tvl = NEXT(tvl);
        !           502:           }
        !           503:           VR(tvl) = v;
        !           504:         }
        !           505:       }
        !           506:     } else {
        !           507:       for ( svl = vl; svl; svl = NEXT(svl) ) {
        !           508:         if ( svl->v->attr == (pointer)V_PF )
        !           509:           ((PFINS)svl->v->priv)->pf->ins = 0;
        !           510:       }
        !           511:     }
        !           512:     if ( vl )
        !           513:       NEXT(tvl) = 0;
        !           514:     CO = vl;
        !           515:     update_LASTCO();
        !           516:   }
        !           517:   for ( n = 0, vl = CO; vl; vl = NEXT(vl) ) {
        !           518:     NEXTNODE(n,tn); MKV(VR(vl),t); BDY(tn) = (pointer)t;
        !           519:   }
        !           520:   NEXT(tn) = 0; MKLIST(l,n); *listp = l;
1.1       noro      521: }
                    522:
1.22      noro      523: void Premove_vars(NODE arg,LIST *listp)
                    524: {
1.30    ! noro      525:   NODE l,nd,tnd;
        !           526:   V *v,*va;
        !           527:   int n,na,i,j;
        !           528:   VL vl,vl1;
        !           529:   P t;
        !           530:   LIST list;
        !           531:
        !           532:   asir_assert(ARG0(arg),O_LIST,"remove_vars");
        !           533:   l = BDY((LIST)ARG0(arg)); n = length(l);
        !           534:   v = (V *)ALLOCA(n*sizeof(V));
        !           535:   for ( i = 0; i < n; i++, l = NEXT(l) )
        !           536:     if ( !(t = (P)BDY(l)) || (OID(t) != O_P) )
        !           537:       error("ord : invalid argument");
        !           538:     else v[i] = VR(t);
        !           539:
        !           540:   for ( na = 0, vl = CO; vl; vl = NEXT(vl), na++ );
        !           541:   va = (V *)ALLOCA(na*sizeof(V));
        !           542:   for ( i = 0, vl = CO; i < na; i++, vl = NEXT(vl) ) va[i] = VR(vl);
        !           543:   for ( i = 0; i < na; i++ )
        !           544:     for ( j = 0; j < n; j++ ) if ( va[i] == v[j] ) va[i] = 0;
        !           545:   for ( vl = 0, i = na-1; i >= 0; i-- )
        !           546:     if ( va[i] ) {
        !           547:       NEWVL(vl1); VR(vl1) = va[i]; NEXT(vl1) = vl; vl = vl1;
        !           548:     }
        !           549:   CO = vl;
        !           550:   for ( nd = 0, vl = CO; vl; vl = NEXT(vl) ) {
        !           551:     NEXTNODE(nd,tnd); MKV(VR(vl),t); BDY(tnd) = (pointer)t;
        !           552:   }
        !           553:   if ( nd ) NEXT(tnd) = 0;
        !           554:   MKLIST(list,nd); *listp = list;
1.22      noro      555: }
                    556:
1.16      noro      557: void Pcoef0(NODE arg,Obj *rp)
1.1       noro      558: {
1.30    ! noro      559:   Obj t,n;
        !           560:   P s;
        !           561:   DCP dc;
        !           562:   int id;
        !           563:   V v;
        !           564:   VL vl;
        !           565:
        !           566:   if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
        !           567:     *rp = 0;
        !           568:   else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
        !           569:     *rp = 0;
        !           570:   else if ( id == O_N )
        !           571:     if ( !n )
        !           572:       *rp = t;
        !           573:     else
        !           574:       *rp = 0;
        !           575:   else {
        !           576:     if ( argc(arg) == 3 ) {
        !           577:       if ( (v = VR((P)ARG2(arg))) != VR((P)t) ) {
        !           578:         reordvar(CO,v,&vl); reorderp(vl,CO,(P)t,&s);
        !           579:       } else
        !           580:         s = (P)t;
        !           581:       if ( VR(s) != v ) {
        !           582:         if ( n )
        !           583:           *rp = 0;
        !           584:         else
        !           585:           *rp = t;
        !           586:         return;
        !           587:       }
        !           588:     } else
        !           589:       s = (P)t;
        !           590:     for ( dc = DC(s); dc && cmpq(DEG(dc),(Q)n); dc = NEXT(dc) );
        !           591:     if ( dc )
        !           592:       *rp = (Obj)COEF(dc);
        !           593:     else
        !           594:       *rp = 0;
        !           595:   }
1.1       noro      596: }
                    597:
1.16      noro      598: void Pcoef(NODE arg,Obj *rp)
1.1       noro      599: {
1.30    ! noro      600:   Obj t,n;
        !           601:   P s;
        !           602:   DCP dc;
        !           603:   int id;
        !           604:   V v;
        !           605:
        !           606:   if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
        !           607:     *rp = 0;
        !           608:   else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
        !           609:     *rp = 0;
        !           610:   else if ( id == O_N ) {
        !           611:     if ( !n )
        !           612:       *rp = t;
        !           613:     else
        !           614:       *rp = 0;
        !           615:   } else {
        !           616:     if ( argc(arg) == 3 ) {
        !           617:       if ( (v = VR((P)ARG2(arg))) != VR((P)t) ) {
        !           618:         getcoef(CO,(P)t,v,(Q)n,(P *)rp); return;
        !           619:       } else
        !           620:         s = (P)t;
        !           621:       if ( VR(s) != v ) {
        !           622:         if ( n )
        !           623:           *rp = 0;
        !           624:         else
        !           625:           *rp = t;
        !           626:         return;
        !           627:       }
        !           628:     } else
        !           629:       s = (P)t;
        !           630:     for ( dc = DC(s); dc && cmpq(DEG(dc),(Q)n); dc = NEXT(dc) );
        !           631:     if ( dc )
        !           632:       *rp = (Obj)COEF(dc);
        !           633:     else
        !           634:       *rp = 0;
        !           635:   }
1.1       noro      636: }
                    637:
1.16      noro      638: void Pcoef_gf2n(NODE arg,Obj *rp)
1.1       noro      639: {
1.30    ! noro      640:   Obj t,n;
        !           641:   int id,d;
        !           642:   UP2 up2;
        !           643:
        !           644:   if ( !(t = (Obj)ARG0(arg)) || ((id = OID(ARG0(arg))) > O_P) )
        !           645:     *rp = 0;
        !           646:   else if ( (n = (Obj)ARG1(arg)) && (OID(n) > O_N) )
        !           647:     *rp = 0;
        !           648:   else if ( id == O_N && NID((Num)t) == N_GF2N ) {
        !           649:     d = QTOS((Q)n);
        !           650:     up2 = ((GF2N)t)->body;
        !           651:     if ( d > degup2(up2) )
        !           652:       *rp = 0;
        !           653:     else
        !           654:       *rp = (Obj)(up2->b[d/BSH]&(((unsigned long)1)<<(d%BSH))?ONE:0);
        !           655:   } else
        !           656:     *rp = 0;
1.1       noro      657: }
                    658:
1.16      noro      659: void Pdeg(NODE arg,Q *rp)
1.1       noro      660: {
1.30    ! noro      661:   Obj t,v;
        !           662:   int d;
1.1       noro      663:
                    664: #if 0
1.30    ! noro      665:   if ( !(t = (Obj)ARG0(arg)) || (OID(t) != O_P) )
        !           666:     *rp = 0;
        !           667:   else if ( !(v = (Obj)ARG1(arg)) || (VR((P)v) != VR((P)t)) )
        !           668:     *rp = 0;
        !           669:   else
        !           670:     *rp = (Obj)DEG(DC((P)t));
1.1       noro      671: #endif
1.30    ! noro      672:   if ( !(t = (Obj)ARG0(arg)) )
        !           673:     STOQ(-1,*rp);
        !           674:   else if ( OID(t) != O_P ) {
        !           675:     if ( OID(t) == O_N && NID(t) == N_GF2N
        !           676:       && (v=(Obj)ARG1(arg)) && OID(v)== O_N && NID(v) == N_GF2N ) {
        !           677:       d = degup2(((GF2N)t)->body);
        !           678:       STOQ(d,*rp);
        !           679:     } else
        !           680:       *rp = 0;
        !           681:   } else
        !           682:     degp(VR((P)ARG1(arg)),(P)ARG0(arg),rp);
1.1       noro      683: }
                    684:
1.16      noro      685: void Pmindeg(NODE arg,Q *rp)
1.1       noro      686: {
1.30    ! noro      687:   Obj t;
1.1       noro      688:
1.30    ! noro      689:   if ( !(t = (Obj)ARG0(arg)) || (OID(t) != O_P) )
        !           690:     *rp = 0;
        !           691:   else
        !           692:     getmindeg(VR((P)ARG1(arg)),(P)ARG0(arg),rp);
1.1       noro      693: }
                    694:
1.16      noro      695: void Psetmod(NODE arg,Q *rp)
1.1       noro      696: {
1.30    ! noro      697:   if ( arg ) {
        !           698:     asir_assert(ARG0(arg),O_N,"setmod");
        !           699:     current_mod = QTOS((Q)ARG0(arg));
        !           700:   }
        !           701:   STOQ(current_mod,*rp);
1.1       noro      702: }
                    703:
1.16      noro      704: void Psparsemod_gf2n(NODE arg,Q *rp)
1.1       noro      705: {
1.30    ! noro      706:   int id;
1.1       noro      707:
1.30    ! noro      708:   if ( arg && current_mod_gf2n )
        !           709:     current_mod_gf2n->id = ARG0(arg)?1:0;
        !           710:   if ( !current_mod_gf2n )
        !           711:     id = -1;
        !           712:   else
        !           713:     id = current_mod_gf2n->id;
        !           714:   STOQ(id,*rp);
1.1       noro      715: }
                    716:
1.16      noro      717: void Pmultest_gf2n(NODE arg,GF2N *rp)
1.1       noro      718: {
1.30    ! noro      719:   GF2N a,b,c;
        !           720:   int i;
1.1       noro      721:
1.30    ! noro      722:   a = (GF2N)ARG0(arg); b = (GF2N)ARG0(arg);
        !           723:   for ( i = 0; i < 10000; i++ )
        !           724:     mulgf2n(a,b,&c);
        !           725:   *rp = c;
1.1       noro      726: }
                    727:
1.16      noro      728: void Psquaretest_gf2n(NODE arg,GF2N *rp)
1.1       noro      729: {
1.30    ! noro      730:   GF2N a,c;
        !           731:   int i;
1.1       noro      732:
1.30    ! noro      733:   a = (GF2N)ARG0(arg);
        !           734:   for ( i = 0; i < 10000; i++ )
        !           735:     squaregf2n(a,&c);
        !           736:   *rp = c;
1.1       noro      737: }
                    738:
1.16      noro      739: void Pinvtest_gf2n(NODE arg,GF2N *rp)
1.1       noro      740: {
1.30    ! noro      741:   GF2N a,c;
        !           742:   int i;
1.1       noro      743:
1.30    ! noro      744:   a = (GF2N)ARG0(arg);
        !           745:   for ( i = 0; i < 10000; i++ )
        !           746:     invgf2n(a,&c);
        !           747:   *rp = c;
1.1       noro      748: }
                    749:
1.16      noro      750: void Pbininv_gf2n(NODE arg,GF2N *rp)
1.1       noro      751: {
1.30    ! noro      752:   UP2 a,inv;
        !           753:   int n;
1.1       noro      754:
1.30    ! noro      755:   a = ((GF2N)ARG0(arg))->body;
        !           756:   n = QTOS((Q)ARG1(arg));
        !           757:   type1_bin_invup2(a,n,&inv);
        !           758:   MKGF2N(inv,*rp);
1.1       noro      759: }
                    760:
1.16      noro      761: void Prinvtest_gf2n(Real *rp)
1.1       noro      762: {
1.30    ! noro      763:   GF2N *a;
        !           764:   GF2N c;
        !           765:   double t0,t1,r;
        !           766:   int i;
        !           767:   double get_clock();
        !           768:
        !           769:   a = (GF2N *)ALLOCA(1000*sizeof(GF2N));
        !           770:   for ( i = 0; i < 1000; i++ ) {
        !           771:     randomgf2n(&a[i]);
        !           772:   }
        !           773:   t0 = get_clock();
        !           774:   for ( i = 0; i < 1000; i++ )
        !           775:     invgf2n(a[i],&c);
        !           776:   t1 = get_clock();
        !           777:   r = (t1-t0)/1000;
        !           778:   MKReal(r,*rp);
1.1       noro      779: }
                    780:
1.16      noro      781: void Pfind_root_gf2n(NODE arg,GF2N *rp)
1.1       noro      782: {
                    783:
                    784: #if 0
1.30    ! noro      785:   UP p;
1.1       noro      786:
1.30    ! noro      787:   ptoup((P)ARG0(arg),&p);
        !           788:   find_root_gf2n(p,rp);
1.1       noro      789: #else
1.30    ! noro      790:   UP2 p;
1.1       noro      791:
1.30    ! noro      792:   ptoup2((P)ARG0(arg),&p);
        !           793:   find_root_up2(p,rp);
1.1       noro      794: #endif
                    795: }
                    796:
1.16      noro      797: void Pis_irred_gf2(NODE arg,Q *rp)
1.1       noro      798: {
1.30    ! noro      799:   UP2 t;
1.1       noro      800:
1.30    ! noro      801:   ptoup2(ARG0(arg),&t);
        !           802:   *rp = irredcheckup2(t) ? ONE : 0;
1.1       noro      803: }
                    804:
1.16      noro      805: void Pis_irred_ddd_gf2(NODE arg,Q *rp)
1.1       noro      806: {
1.30    ! noro      807:   UP2 t;
        !           808:   int ret;
1.1       noro      809:
1.30    ! noro      810:   ptoup2(ARG0(arg),&t);
        !           811:   ret = irredcheck_dddup2(t);
        !           812:   STOQ(ret,*rp);
1.1       noro      813: }
                    814:
1.16      noro      815: void Psetmod_ff(NODE arg,Obj *rp)
1.1       noro      816: {
1.30    ! noro      817:   int ac;
        !           818:   int d;
        !           819:   Obj mod,defpoly;
        !           820:   N n;
        !           821:   UP up;
        !           822:   UP2 up2;
        !           823:   UM dp;
        !           824:   Q q,r;
        !           825:   P p,p1,y;
        !           826:   NODE n0,n1;
        !           827:   LIST list;
        !           828:
        !           829:   ac = argc(arg);
        !           830:   if ( ac == 1 ) {
        !           831:     mod = (Obj)ARG0(arg);
        !           832:     if ( !mod )
1.26      noro      833:             current_ff = FF_NOT_SET;
                    834:         else {
1.30    ! noro      835:       switch ( OID(mod) ) {
        !           836:       case O_N:
        !           837:         current_ff = FF_GFP;
        !           838:         setmod_lm(NM((Q)mod));
        !           839:         break;
        !           840:       case O_P:
        !           841:         current_ff = FF_GF2N;
        !           842:         setmod_gf2n((P)mod); break;
        !           843:       default:
        !           844:         error("setmod_ff : invalid argument");
        !           845:       }
        !           846:       }
        !           847:   } else if ( ac == 2 ) {
        !           848:     if ( OID(ARG0(arg)) == O_N ) {
        !           849:       /* small finite field; primitive root representation */
        !           850:       current_ff = FF_GFS;
        !           851:       setmod_sf(QTOS((Q)ARG0(arg)),QTOS((Q)ARG1(arg)));
        !           852:     } else {
        !           853:       mod = (Obj)ARG1(arg);
        !           854:       current_ff = FF_GFPN;
        !           855:       defpoly = (Obj)ARG0(arg);
        !           856:       if ( !mod || !defpoly )
        !           857:         error("setmod_ff : invalid argument");
        !           858:       setmod_lm(NM((Q)mod));
        !           859:       setmod_gfpn((P)defpoly);
        !           860:     }
        !           861:   } else if ( ac == 3 ) {
        !           862:     /* finite extension of a small finite field */
        !           863:     current_ff = FF_GFS;
        !           864:     setmod_sf(QTOS((Q)ARG0(arg)),QTOS((Q)ARG1(arg)));
        !           865:     d = QTOS((Q)ARG2(arg));
        !           866:     generate_defpoly_sfum(d,&dp);
        !           867:     setmod_gfsn(dp);
        !           868:     current_ff = FF_GFSN;
        !           869:   }
        !           870:   switch ( current_ff ) {
        !           871:     case FF_GFP:
        !           872:       getmod_lm(&n); NTOQ(n,1,q); *rp = (Obj)q; break;
        !           873:     case FF_GF2N:
        !           874:       getmod_gf2n(&up2); up2top(up2,&p); *rp = (Obj)p; break;
        !           875:     case FF_GFPN:
        !           876:       getmod_lm(&n); NTOQ(n,1,q);
        !           877:       getmod_gfpn(&up); uptop(up,&p);
        !           878:       MKNODE(n1,q,0); MKNODE(n0,p,n1);
        !           879:       MKLIST(list,n0);
        !           880:       *rp = (Obj)list; break;
        !           881:     case FF_GFS:
        !           882:     case FF_GFSN:
        !           883:       STOQ(current_gfs_p,q);
        !           884:       if ( current_gfs_ext )
        !           885:         enc_to_p(current_gfs_p,current_gfs_iton[1],
        !           886:           VR(current_gfs_ext),&p);
        !           887:       else {
        !           888:         if ( current_gfs_p == 2 )
        !           889:           r = ONE;
        !           890:         else if ( !current_gfs_ntoi )
        !           891:           r = 0;
        !           892:         else
        !           893:           STOQ(current_gfs_iton[1],r);
        !           894:         p = (P)r;
1.26      noro      895:       }
1.30    ! noro      896:       switch ( current_ff ) {
        !           897:         case FF_GFS:
        !           898:           n0 = mknode(3,q,current_gfs_ext,p);
        !           899:           break;
        !           900:         case FF_GFSN:
        !           901:           getmod_gfsn(&dp);
        !           902:           makevar("y",&y);
        !           903:           sfumtop(VR(y),dp,&p1);
        !           904:           n0 = mknode(4,q,current_gfs_ext,p,p1);
        !           905:           break;
        !           906:       }
        !           907:       MKLIST(list,n0);
        !           908:       *rp = (Obj)list; break;
        !           909:     default:
        !           910:       *rp = 0; break;
        !           911:   }
1.1       noro      912: }
                    913:
1.16      noro      914: void Pextdeg_ff(Q *rp)
1.1       noro      915: {
1.30    ! noro      916:   int d;
        !           917:   UP2 up2;
        !           918:   UP up;
        !           919:   UM dp;
        !           920:
        !           921:   switch ( current_ff ) {
        !           922:     case FF_GFP:
        !           923:       *rp = ONE; break;
        !           924:     case FF_GF2N:
        !           925:       getmod_gf2n(&up2); d = degup2(up2); STOQ(d,*rp); break;
        !           926:     case FF_GFPN:
        !           927:       getmod_gfpn(&up); STOQ(up->d,*rp); break;
        !           928:     case FF_GFS:
        !           929:       if ( !current_gfs_ext )
        !           930:         *rp = ONE;
        !           931:       else
        !           932:         *rp = DEG(DC(current_gfs_ext));
        !           933:       break;
        !           934:     case FF_GFSN:
        !           935:       getmod_gfsn(&dp);
        !           936:       STOQ(DEG(dp),*rp);
        !           937:       break;
        !           938:     default:
        !           939:       error("extdeg_ff : current_ff is not set");
        !           940:   }
1.1       noro      941: }
                    942:
1.16      noro      943: void Pcharacteristic_ff(Q *rp)
1.1       noro      944: {
1.30    ! noro      945:   N lm;
1.1       noro      946:
1.30    ! noro      947:   switch ( current_ff ) {
        !           948:     case FF_GFP:
        !           949:     case FF_GFPN:
        !           950:       getmod_lm(&lm); NTOQ(lm,1,*rp); break;
        !           951:     case FF_GF2N:
        !           952:       STOQ(2,*rp); break;
        !           953:     case FF_GFS:
        !           954:     case FF_GFSN:
        !           955:       STOQ(current_gfs_p,*rp); break;
        !           956:     default:
        !           957:       error("characteristic_ff : current_ff is not set");
        !           958:   }
1.1       noro      959: }
                    960:
1.16      noro      961: void Pfield_type_ff(Q *rp)
1.1       noro      962: {
1.30    ! noro      963:   STOQ(current_ff,*rp);
1.1       noro      964: }
                    965:
1.16      noro      966: void Pfield_order_ff(Q *rp)
1.1       noro      967: {
1.30    ! noro      968:   N n;
1.1       noro      969:
1.30    ! noro      970:   field_order_ff(&n);
        !           971:   NTOQ(n,1,*rp);
1.1       noro      972: }
                    973:
1.16      noro      974: void Prandom_ff(Obj *rp)
1.1       noro      975: {
1.30    ! noro      976:   LM l;
        !           977:   GF2N g;
        !           978:   GFPN p;
        !           979:   GFS s;
        !           980:   GFSN spn;
        !           981:
        !           982:   switch ( current_ff ) {
        !           983:     case FF_GFP:
        !           984:       random_lm(&l); *rp = (Obj)l; break;
        !           985:     case FF_GF2N:
        !           986:       randomgf2n(&g); *rp = (Obj)g; break;
        !           987:     case FF_GFPN:
        !           988:       randomgfpn(&p); *rp = (Obj)p; break;
        !           989:     case FF_GFS:
        !           990:       randomgfs(&s); *rp = (Obj)s; break;
        !           991:     case FF_GFSN:
        !           992:       randomgfsn(&spn); *rp = (Obj)spn; break;
        !           993:     default:
        !           994:       error("random_ff : current_ff is not set");
        !           995:   }
1.1       noro      996: }
                    997:
1.16      noro      998: void Psimp_ff(NODE arg,Obj *rp)
                    999: {
1.30    ! noro     1000:   simp_ff((Obj)ARG0(arg),rp);
1.1       noro     1001: }
                   1002:
1.16      noro     1003: void getcoef(VL vl,P p,V v,Q d,P *r)
1.1       noro     1004: {
1.30    ! noro     1005:   P s,t,u,a,b,x;
        !          1006:   DCP dc;
        !          1007:   V w;
        !          1008:
        !          1009:   if ( !p )
        !          1010:     *r = 0;
        !          1011:   else if ( NUM(p) )
        !          1012:     *r = d ? 0 : p;
        !          1013:   else if ( (w=VR(p)) == v ) {
        !          1014:     for ( dc = DC(p); dc && cmpq(DEG(dc),d); dc = NEXT(dc) );
        !          1015:     *r = dc ? COEF(dc) : 0;
        !          1016:   } else {
        !          1017:     MKV(w,x);
        !          1018:     for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
        !          1019:       getcoef(vl,COEF(dc),v,d,&t);
        !          1020:       if ( t ) {
        !          1021:         pwrp(vl,x,DEG(dc),&u); mulp(vl,t,u,&a);
        !          1022:         addp(vl,s,a,&b); s = b;
        !          1023:       }
        !          1024:     }
        !          1025:     *r = s;
        !          1026:   }
1.1       noro     1027: }
                   1028:
1.16      noro     1029: void Pdeglist(NODE arg,LIST *rp)
1.1       noro     1030: {
1.30    ! noro     1031:   NODE d;
1.1       noro     1032:
1.30    ! noro     1033:   getdeglist((P)ARG0(arg),VR((P)ARG1(arg)),&d);
        !          1034:   MKLIST(*rp,d);
1.1       noro     1035: }
                   1036:
1.16      noro     1037: void Pch_mv(NODE arg,P *rp)
1.1       noro     1038: {
1.30    ! noro     1039:   change_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
1.1       noro     1040: }
                   1041:
1.16      noro     1042: void Pre_mv(NODE arg,P *rp)
1.1       noro     1043: {
1.30    ! noro     1044:   restore_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
1.1       noro     1045: }
                   1046:
1.16      noro     1047: void change_mvar(VL vl,P p,V v,P *r)
1.1       noro     1048: {
1.30    ! noro     1049:   Q d;
        !          1050:   DCP dc,dc0;
        !          1051:   NODE dl;
        !          1052:
        !          1053:   if ( !p || NUM(p) || (VR(p) == v) )
        !          1054:     *r = p;
        !          1055:   else {
        !          1056:     getdeglist(p,v,&dl);
        !          1057:     for ( dc0 = 0; dl; dl = NEXT(dl) ) {
        !          1058:       NEXTDC(dc0,dc); DEG(dc) = d = (Q)BDY(dl);
        !          1059:       getcoef(vl,p,v,d,&COEF(dc));
        !          1060:     }
        !          1061:     NEXT(dc) = 0; MKP(v,dc0,*r);
        !          1062:   }
1.1       noro     1063: }
                   1064:
1.16      noro     1065: void restore_mvar(VL vl,P p,V v,P *r)
1.1       noro     1066: {
1.30    ! noro     1067:   P s,u,a,b,x;
        !          1068:   DCP dc;
1.1       noro     1069:
1.30    ! noro     1070:   if ( !p || NUM(p) || (VR(p) != v) )
        !          1071:     *r = p;
        !          1072:   else {
        !          1073:     MKV(v,x);
        !          1074:     for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
        !          1075:       pwrp(vl,x,DEG(dc),&u); mulp(vl,COEF(dc),u,&a);
        !          1076:       addp(vl,s,a,&b); s = b;
        !          1077:     }
        !          1078:     *r = s;
        !          1079:   }
1.1       noro     1080: }
                   1081:
1.16      noro     1082: void getdeglist(P p,V v,NODE *d)
1.1       noro     1083: {
1.30    ! noro     1084:   NODE n,n0,d0,d1,d2;
        !          1085:   DCP dc;
1.1       noro     1086:
1.30    ! noro     1087:   if ( !p || NUM(p) ) {
        !          1088:     MKNODE(n,0,0); *d = n;
        !          1089:   } else if ( VR(p) == v ) {
        !          1090:     for ( n0 = 0, dc = DC(p); dc; dc = NEXT(dc) ) {
        !          1091:       NEXTNODE(n0,n); BDY(n) = (pointer)DEG(dc);
        !          1092:     }
        !          1093:     NEXT(n) = 0; *d = n0;
        !          1094:   } else {
        !          1095:     for ( dc = DC(p), d0 = 0; dc; dc = NEXT(dc) ) {
        !          1096:       getdeglist(COEF(dc),v,&d1); mergedeglist(d0,d1,&d2); d0 = d2;
        !          1097:     }
        !          1098:     *d = d0;
        !          1099:   }
1.1       noro     1100: }
1.16      noro     1101:
                   1102: void Pmergelist(NODE arg,LIST *rp)
1.1       noro     1103: {
                   1104:     NODE n;
                   1105:
1.30    ! noro     1106:   asir_assert(ARG0(arg),O_LIST,"mergelist");
        !          1107:   asir_assert(ARG1(arg),O_LIST,"mergelist");
        !          1108:   mergedeglist(BDY((LIST)ARG0(arg)),BDY((LIST)ARG1(arg)),&n);
        !          1109:   MKLIST(*rp,n);
1.1       noro     1110: }
                   1111:
1.16      noro     1112: void mergedeglist(NODE d0,NODE d1,NODE *dr)
1.1       noro     1113: {
1.30    ! noro     1114:   NODE t0,t,dt;
        !          1115:   Q d;
        !          1116:   int c;
        !          1117:
        !          1118:   if ( !d0 )
        !          1119:     *dr = d1;
        !          1120:   else {
        !          1121:     while ( d1 ) {
        !          1122:       dt = d1; d1 = NEXT(d1); d = (Q)BDY(dt);
        !          1123:       for ( t0 = 0, t = d0; t; t0 = t, t = NEXT(t) ) {
        !          1124:         c = cmpq(d,(Q)BDY(t));
        !          1125:         if ( !c )
        !          1126:           break;
        !          1127:         else if ( c > 0 ) {
        !          1128:           if ( !t0 ) {
        !          1129:             NEXT(dt) = d0; d0 = dt;
        !          1130:           } else {
        !          1131:             NEXT(t0) = dt; NEXT(dt) = t;
        !          1132:           }
        !          1133:           break;
        !          1134:         }
        !          1135:       }
        !          1136:       if ( !t ) {
        !          1137:         NEXT(t0) = dt; *dr = d0; return;
        !          1138:       }
        !          1139:     }
        !          1140:     *dr = d0;
        !          1141:   }
1.1       noro     1142: }
                   1143:
1.16      noro     1144: void Pptomp(NODE arg,P *rp)
1.1       noro     1145: {
1.27      noro     1146:   int mod;
                   1147:
                   1148:   if ( argc(arg) == 1 ) {
                   1149:     if ( !current_mod )
                   1150:       error("ptomp : current_mod is not set");
                   1151:     else
                   1152:       mod = current_mod;
                   1153:   } else
                   1154:     mod = QTOS((Q)ARG1(arg));
1.30    ! noro     1155:   ptomp(mod,(P)ARG0(arg),rp);
1.1       noro     1156: }
                   1157:
1.16      noro     1158: void Pmptop(NODE arg,P *rp)
1.1       noro     1159: {
1.30    ! noro     1160:   mptop((P)ARG0(arg),rp);
1.1       noro     1161: }
                   1162:
1.16      noro     1163: void Pptolmp(NODE arg,P *rp)
1.1       noro     1164: {
1.30    ! noro     1165:   ptolmp((P)ARG0(arg),rp);
1.1       noro     1166: }
                   1167:
1.16      noro     1168: void Plmptop(NODE arg,P *rp)
1.1       noro     1169: {
1.30    ! noro     1170:   lmptop((P)ARG0(arg),rp);
1.11      noro     1171: }
                   1172:
1.16      noro     1173: void Psf_galois_action(NODE arg,P *rp)
1.11      noro     1174: {
1.30    ! noro     1175:   sf_galois_action(ARG0(arg),ARG1(arg),rp);
1.12      noro     1176: }
                   1177:
                   1178: /*
                   1179:   sf_embed(F,B,PM)
                   1180:   F : an element of GF(pn)
                   1181:   B : the image of the primitive root of GF(pn)
                   1182:   PM : order of GF(pm)
                   1183: */
                   1184:
1.16      noro     1185: void Psf_embed(NODE arg,P *rp)
1.12      noro     1186: {
1.30    ! noro     1187:   int k,pm;
1.12      noro     1188:
1.30    ! noro     1189:   /* GF(pn)={0,1,a,a^2,...}->GF(pm)={0,1,b,b^2,...}; a->b^k */
        !          1190:   k = CONT((GFS)ARG1(arg));
        !          1191:   pm = QTOS((Q)ARG2(arg));
        !          1192:   sf_embed((P)ARG0(arg),k,pm,rp);
1.13      noro     1193: }
                   1194:
1.16      noro     1195: void Psf_log(NODE arg,Q *rp)
1.13      noro     1196: {
1.30    ! noro     1197:   int k;
1.13      noro     1198:
1.30    ! noro     1199:   if ( !ARG0(arg) )
        !          1200:     error("sf_log : invalid armument");
        !          1201:   k = CONT((GFS)ARG0(arg));
        !          1202:   STOQ(k,*rp);
1.12      noro     1203: }
                   1204:
1.16      noro     1205: void Psf_find_root(NODE arg,GFS *rp)
1.12      noro     1206: {
1.30    ! noro     1207:   P p;
        !          1208:   Obj t;
        !          1209:   int d;
        !          1210:   UM u;
        !          1211:   int *root;
        !          1212:
        !          1213:   p = (P)ARG0(arg);
        !          1214:   simp_ff((Obj)p,&t); p = (P)t;
        !          1215:   d = getdeg(VR(p),p);
        !          1216:   u = W_UMALLOC(d);
        !          1217:   ptosfum(p,u);
        !          1218:   root = (int *)ALLOCA(d*sizeof(int));
        !          1219:   find_rootsf(u,root);
        !          1220:   MKGFS(IFTOF(root[0]),*rp);
1.12      noro     1221: }
                   1222:
1.16      noro     1223: void Psf_minipoly(NODE arg,P *rp)
1.12      noro     1224: {
1.30    ! noro     1225:   Obj t;
        !          1226:   P p1,p2;
        !          1227:   int d1,d2;
        !          1228:   UM up1,up2,m;
        !          1229:
        !          1230:   p1 = (P)ARG0(arg); simp_ff((Obj)p1,&t); p1 = (P)t;
        !          1231:   p2 = (P)ARG1(arg); simp_ff((Obj)p2,&t); p2 = (P)t;
        !          1232:   d1 = getdeg(VR(p1),p1); up1 = W_UMALLOC(d1); ptosfum(p1,up1);
        !          1233:   d2 = getdeg(VR(p2),p2); up2 = W_UMALLOC(d2); ptosfum(p2,up2);
        !          1234:   m = W_UMALLOC(d2);
        !          1235:   minipolysf(up1,up2,m);
        !          1236:   sfumtop(VR(p2),m,&p1);
        !          1237:   sfptop(p1,rp);
1.11      noro     1238: }
                   1239:
1.16      noro     1240: void Pptosfp(NODE arg,P *rp)
1.11      noro     1241: {
1.30    ! noro     1242:   ptosfp(ARG0(arg),rp);
1.6       noro     1243: }
                   1244:
1.16      noro     1245: void Psfptop(NODE arg,P *rp)
1.6       noro     1246: {
1.30    ! noro     1247:   sfptop((P)ARG0(arg),rp);
1.18      noro     1248: }
                   1249:
                   1250: void Psfptopsfp(NODE arg,P *rp)
                   1251: {
1.30    ! noro     1252:   sfptopsfp((P)ARG0(arg),VR((P)ARG1(arg)),rp);
1.1       noro     1253: }
                   1254:
1.16      noro     1255: void Pptogf2n(NODE arg,GF2N *rp)
1.1       noro     1256: {
1.30    ! noro     1257:   ptogf2n((Obj)ARG0(arg),rp);
1.1       noro     1258: }
                   1259:
1.16      noro     1260: void Pgf2ntop(NODE arg,P *rp)
1.1       noro     1261: {
1.30    ! noro     1262:   if ( argc(arg) == 2 )
        !          1263:     up2_var = VR((P)ARG1(arg));
        !          1264:   gf2ntop((GF2N)ARG0(arg),rp);
1.1       noro     1265: }
                   1266:
1.16      noro     1267: void Pgf2ntovect(NODE arg,VECT *rp)
1.1       noro     1268: {
1.30    ! noro     1269:   gf2ntovect((GF2N)ARG0(arg),rp);
1.1       noro     1270: }
                   1271:
1.16      noro     1272: void Pptogfpn(NODE arg,GFPN *rp)
1.1       noro     1273: {
1.30    ! noro     1274:   ptogfpn((Obj)ARG0(arg),rp);
1.1       noro     1275: }
                   1276:
1.16      noro     1277: void Pgfpntop(NODE arg,P *rp)
1.1       noro     1278: {
1.30    ! noro     1279:   if ( argc(arg) == 2 )
        !          1280:     up_var = VR((P)ARG1(arg));
        !          1281:   gfpntop((GFPN)ARG0(arg),rp);
1.1       noro     1282: }
                   1283:
1.16      noro     1284: void Pureverse(NODE arg,P *rp)
1.1       noro     1285: {
1.30    ! noro     1286:   UP p,r;
1.1       noro     1287:
1.30    ! noro     1288:   ptoup((P)ARG0(arg),&p);
        !          1289:   if ( argc(arg) == 1 )
        !          1290:     reverseup(p,p->d,&r);
        !          1291:   else
        !          1292:     reverseup(p,QTOS((Q)ARG1(arg)),&r);
        !          1293:   uptop(r,rp);
1.1       noro     1294: }
                   1295:
1.16      noro     1296: void Putrunc(NODE arg,P *rp)
1.1       noro     1297: {
1.30    ! noro     1298:   UP p,r;
1.1       noro     1299:
1.30    ! noro     1300:   ptoup((P)ARG0(arg),&p);
        !          1301:   truncup(p,QTOS((Q)ARG1(arg))+1,&r);
        !          1302:   uptop(r,rp);
1.1       noro     1303: }
                   1304:
1.16      noro     1305: void Pudecomp(NODE arg,LIST *rp)
1.1       noro     1306: {
1.30    ! noro     1307:   P u,l;
        !          1308:   UP p,up,low;
        !          1309:   NODE n0,n1;
        !          1310:
        !          1311:   ptoup((P)ARG0(arg),&p);
        !          1312:   decompup(p,QTOS((Q)ARG1(arg))+1,&low,&up);
        !          1313:   uptop(low,&l);
        !          1314:   uptop(up,&u);
        !          1315:   MKNODE(n1,u,0); MKNODE(n0,l,n1);
        !          1316:   MKLIST(*rp,n0);
1.1       noro     1317: }
                   1318:
1.16      noro     1319: void Purembymul(NODE arg,P *rp)
1.1       noro     1320: {
1.30    ! noro     1321:   UP p1,p2,r;
1.1       noro     1322:
1.30    ! noro     1323:   if ( !ARG0(arg) || !ARG1(arg) )
        !          1324:     *rp = 0;
        !          1325:   else {
        !          1326:     ptoup((P)ARG0(arg),&p1);
        !          1327:     ptoup((P)ARG1(arg),&p2);
        !          1328:     rembymulup(p1,p2,&r);
        !          1329:     uptop(r,rp);
        !          1330:   }
1.1       noro     1331: }
                   1332:
                   1333: /*
                   1334:  * d1 = deg(p1), d2 = deg(p2)
                   1335:  * d1 <= 2*d2-1
                   1336:  * p2*inv = 1 mod x^d2
                   1337:  */
                   1338:
1.16      noro     1339: void Purembymul_precomp(NODE arg,P *rp)
1.1       noro     1340: {
1.30    ! noro     1341:   UP p1,p2,inv,r;
1.1       noro     1342:
1.30    ! noro     1343:   if ( !ARG0(arg) || !ARG1(arg) )
        !          1344:     *rp = 0;
        !          1345:   else {
        !          1346:     ptoup((P)ARG0(arg),&p1);
        !          1347:     ptoup((P)ARG1(arg),&p2);
        !          1348:     ptoup((P)ARG2(arg),&inv);
        !          1349:     if ( p1->d >= 2*p2->d ) {
        !          1350:       error("urembymul_precomp : degree of 1st arg is too large");
        !          1351: /*      fprintf(stderr,"urembymul_precomp : degree of 1st arg is too large"); */
        !          1352:       remup(p1,p2,&r);
        !          1353:     } else
        !          1354:       hybrid_rembymulup_special(current_ff,p1,p2,inv,&r);
        !          1355:     uptop(r,rp);
        !          1356:   }
1.1       noro     1357: }
                   1358:
1.16      noro     1359: void Puinvmod(NODE arg,P *rp)
1.1       noro     1360: {
1.30    ! noro     1361:   UP p,r;
1.1       noro     1362:
1.30    ! noro     1363:   ptoup((P)ARG0(arg),&p);
        !          1364:   invmodup(p,QTOS((Q)ARG1(arg)),&r);
        !          1365:   uptop(r,rp);
1.1       noro     1366: }
                   1367:
1.16      noro     1368: void Purevinvmod(NODE arg,P *rp)
1.1       noro     1369: {
1.30    ! noro     1370:   UP p,pr,r;
1.1       noro     1371:
1.30    ! noro     1372:   ptoup((P)ARG0(arg),&p);
        !          1373:   reverseup(p,p->d,&pr);
        !          1374:   invmodup(pr,QTOS((Q)ARG1(arg)),&r);
        !          1375:   uptop(r,rp);
1.1       noro     1376: }
                   1377:
1.16      noro     1378: void Ppwrmod_ff(NODE arg,P *rp)
1.1       noro     1379: {
1.30    ! noro     1380:   UP p1,p2;
1.1       noro     1381:
1.30    ! noro     1382:   ptoup((P)ARG0(arg),&p1);
        !          1383:   switch ( current_ff ) {
        !          1384:     case FF_GFP:
        !          1385:       hybrid_powermodup(p1,&p2); break;
        !          1386:     case FF_GF2N:
        !          1387:       powermodup_gf2n(p1,&p2); break;
        !          1388:     case FF_GFPN:
        !          1389:     case FF_GFS:
        !          1390:     case FF_GFSN:
        !          1391:       powermodup(p1,&p2); break;
        !          1392:     default:
        !          1393:       error("pwrmod_ff : current_ff is not set");
        !          1394:   }
        !          1395:   uptop(p2,rp);
1.1       noro     1396: }
                   1397:
1.16      noro     1398: void Pgeneric_pwrmod_ff(NODE arg,P *rp)
1.1       noro     1399: {
1.30    ! noro     1400:   UP g,f,r;
1.1       noro     1401:
1.30    ! noro     1402:   ptoup((P)ARG0(arg),&g);
        !          1403:   ptoup((P)ARG1(arg),&f);
        !          1404:   switch ( current_ff ) {
        !          1405:     case FF_GFP:
        !          1406:       hybrid_generic_powermodup(g,f,(Q)ARG2(arg),&r); break;
        !          1407:     case FF_GF2N:
        !          1408:       generic_powermodup_gf2n(g,f,(Q)ARG2(arg),&r); break;
        !          1409:     case FF_GFPN:
        !          1410:     case FF_GFS:
        !          1411:     case FF_GFSN:
        !          1412:       generic_powermodup(g,f,(Q)ARG2(arg),&r); break;
        !          1413:     default:
        !          1414:       error("generic_pwrmod_ff : current_ff is not set");
        !          1415:   }
        !          1416:   uptop(r,rp);
1.1       noro     1417: }
                   1418:
1.16      noro     1419: void Ppwrtab_ff(NODE arg,VECT *rp)
1.1       noro     1420: {
1.30    ! noro     1421:   UP f,xp;
        !          1422:   UP *tab;
        !          1423:   VECT r;
        !          1424:   int i,d;
        !          1425:
        !          1426:   ptoup((P)ARG0(arg),&f);
        !          1427:   ptoup((P)ARG1(arg),&xp);
        !          1428:   d = f->d;
        !          1429:
        !          1430:   tab = (UP *)ALLOCA(d*sizeof(UP));
        !          1431:   switch ( current_ff ) {
        !          1432:     case FF_GFP:
        !          1433:       hybrid_powertabup(f,xp,tab); break;
        !          1434:     case FF_GF2N:
        !          1435:       powertabup_gf2n(f,xp,tab); break;
        !          1436:     case FF_GFPN:
        !          1437:     case FF_GFS:
        !          1438:     case FF_GFSN:
        !          1439:       powertabup(f,xp,tab); break;
        !          1440:     default:
        !          1441:       error("pwrtab_ff : current_ff is not set");
        !          1442:   }
        !          1443:   MKVECT(r,d); *rp = r;
        !          1444:   for ( i = 0; i < d; i++ )
        !          1445:     uptop(tab[i],(P *)&BDY(r)[i]);
1.1       noro     1446: }
                   1447:
1.16      noro     1448: void Pkpwrmod_lm(NODE arg,P *rp)
1.1       noro     1449: {
1.30    ! noro     1450:   UP p1,p2;
1.1       noro     1451:
1.30    ! noro     1452:   ptoup((P)ARG0(arg),&p1);
        !          1453:   powermodup(p1,&p2);
        !          1454:   uptop(p2,rp);
1.1       noro     1455: }
                   1456:
1.16      noro     1457: void Pkgeneric_pwrmod_lm(NODE arg,P *rp)
1.1       noro     1458: {
1.30    ! noro     1459:   UP g,f,r;
1.1       noro     1460:
1.30    ! noro     1461:   ptoup((P)ARG0(arg),&g);
        !          1462:   ptoup((P)ARG1(arg),&f);
        !          1463:   generic_powermodup(g,f,(Q)ARG2(arg),&r);
        !          1464:   uptop(r,rp);
1.1       noro     1465: }
                   1466:
1.16      noro     1467: void Pkpwrtab_lm(NODE arg,VECT *rp)
1.1       noro     1468: {
1.30    ! noro     1469:   UP f,xp;
        !          1470:   UP *tab;
        !          1471:   VECT r;
        !          1472:   int i,d;
        !          1473:
        !          1474:   ptoup((P)ARG0(arg),&f);
        !          1475:   ptoup((P)ARG1(arg),&xp);
        !          1476:   d = f->d;
        !          1477:
        !          1478:   tab = (UP *)ALLOCA(d*sizeof(UP));
        !          1479:   powertabup(f,xp,tab);
        !          1480:   MKVECT(r,d); *rp = r;
        !          1481:   for ( i = 0; i < d; i++ )
        !          1482:     uptop(tab[i],(P *)&BDY(r)[i]);
1.1       noro     1483: }
                   1484:
1.16      noro     1485: void Plazy_lm(NODE arg,Q *rp)
1.1       noro     1486: {
1.30    ! noro     1487:   lm_lazy = QTOS((Q)ARG0(arg));
        !          1488:   *rp = 0;
1.1       noro     1489: }
                   1490:
1.16      noro     1491: void Pkmul(NODE arg,P *rp)
1.1       noro     1492: {
1.30    ! noro     1493:   P n1,n2;
        !          1494:
        !          1495:   n1 = (P)ARG0(arg); n2 = (P)ARG1(arg);
        !          1496:   asir_assert(n1,O_P,"kmul");
        !          1497:   asir_assert(n2,O_P,"kmul");
        !          1498:   kmulp(CO,n1,n2,rp);
1.1       noro     1499: }
                   1500:
1.16      noro     1501: void Pksquare(NODE arg,P *rp)
1.1       noro     1502: {
1.30    ! noro     1503:   P n1;
        !          1504:
        !          1505:   n1 = (P)ARG0(arg);
        !          1506:   asir_assert(n1,O_P,"ksquare");
        !          1507:   ksquarep(CO,n1,rp);
1.1       noro     1508: }
                   1509:
1.16      noro     1510: void Pktmul(NODE arg,P *rp)
1.1       noro     1511: {
1.30    ! noro     1512:   UP p1,p2,r;
1.1       noro     1513:
1.30    ! noro     1514:   ptoup((P)ARG0(arg),&p1);
        !          1515:   ptoup((P)ARG1(arg),&p2);
        !          1516:   tkmulup(p1,p2,QTOS((Q)ARG2(arg))+1,&r);
        !          1517:   uptop(r,rp);
1.1       noro     1518: }
                   1519:
1.16      noro     1520: void Pumul(NODE arg,P *rp)
1.1       noro     1521: {
1.30    ! noro     1522:   P a1,a2;
        !          1523:   UP p1,p2,r;
1.1       noro     1524:
1.30    ! noro     1525:   a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
        !          1526:   if ( !a1 || !a2 || NUM(a1) || NUM(a2) )
        !          1527:     mulp(CO,a1,a2,rp);
        !          1528:   else {
        !          1529:     if ( !uzpcheck((Obj)a1) || !uzpcheck((Obj)a2) || VR(a1) != VR(a2) )
        !          1530:       error("umul : invalid argument");
        !          1531:     ptoup(a1,&p1);
        !          1532:     ptoup(a2,&p2);
        !          1533:     hybrid_mulup(0,p1,p2,&r);
        !          1534:     uptop(r,rp);
        !          1535:   }
1.1       noro     1536: }
                   1537:
1.16      noro     1538: void Pusquare(NODE arg,P *rp)
1.1       noro     1539: {
1.30    ! noro     1540:   UP p1,r;
1.1       noro     1541:
1.30    ! noro     1542:   ptoup((P)ARG0(arg),&p1);
        !          1543:   hybrid_squareup(0,p1,&r);
        !          1544:   uptop(r,rp);
1.1       noro     1545: }
                   1546:
1.16      noro     1547: void Putmul(NODE arg,P *rp)
1.1       noro     1548: {
1.30    ! noro     1549:   UP p1,p2,r;
1.1       noro     1550:
1.30    ! noro     1551:   ptoup((P)ARG0(arg),&p1);
        !          1552:   ptoup((P)ARG1(arg),&p2);
        !          1553:   hybrid_tmulup(0,p1,p2,QTOS((Q)ARG2(arg))+1,&r);
        !          1554:   uptop(r,rp);
1.1       noro     1555: }
                   1556:
1.16      noro     1557: void Pumul_ff(NODE arg,Obj *rp)
1.1       noro     1558: {
1.30    ! noro     1559:   P a1,a2;
        !          1560:   UP p1,p2,r;
        !          1561:   P p;
        !          1562:
        !          1563:   a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
        !          1564:   ptoup(a1,&p1);
        !          1565:   ptoup(a2,&p2);
        !          1566:   hybrid_mulup(current_ff,p1,p2,&r);
        !          1567:   uptop(r,&p);
        !          1568:   simp_ff((Obj)p,rp);
1.1       noro     1569: }
                   1570:
1.16      noro     1571: void Pusquare_ff(NODE arg,Obj *rp)
1.1       noro     1572: {
1.30    ! noro     1573:   UP p1,r;
        !          1574:   P p;
1.1       noro     1575:
1.30    ! noro     1576:   ptoup((P)ARG0(arg),&p1);
        !          1577:   hybrid_squareup(current_ff,p1,&r);
        !          1578:   uptop(r,&p);
        !          1579:   simp_ff((Obj)p,rp);
1.1       noro     1580: }
                   1581:
1.16      noro     1582: void Putmul_ff(NODE arg,Obj *rp)
1.1       noro     1583: {
1.30    ! noro     1584:   UP p1,p2,r;
        !          1585:   P p;
1.1       noro     1586:
1.30    ! noro     1587:   ptoup((P)ARG0(arg),&p1);
        !          1588:   ptoup((P)ARG1(arg),&p2);
        !          1589:   hybrid_tmulup(current_ff,p1,p2,QTOS((Q)ARG2(arg))+1,&r);
        !          1590:   uptop(r,&p);
        !          1591:   simp_ff((Obj)p,rp);
1.1       noro     1592: }
                   1593:
1.16      noro     1594: void Phfmul_lm(NODE arg,P *rp)
1.1       noro     1595: {
1.30    ! noro     1596:   UP p1,p2,r;
        !          1597:   UP hi,lo,mid,t,s,p10,p11,p20,p21;
        !          1598:   unsigned int m,d;
        !          1599:   int i;
        !          1600:
        !          1601:   ptoup((P)ARG0(arg),&p1);
        !          1602:   ptoup((P)ARG1(arg),&p2);
        !          1603:   d = MAX(p1->d,p2->d);
        !          1604:   for ( m = 1; m < d; m <<= 1 );
        !          1605:   if ( m > d )
        !          1606:     m >>= 1;
        !          1607:   if ( d-m < 10000 ) {
        !          1608:     decompup(p1,m,&p10,&p11); /* p1 = p11*x^m+p10 */
        !          1609:     decompup(p2,m,&p20,&p21); /* p2 = p21*x^m+p20 */
        !          1610:     fft_mulup_lm(p10,p20,&lo);
        !          1611:     kmulup(p11,p21,&hi);
        !          1612:     kmulup(p11,p20,&t); kmulup(p10,p21,&s); addup(t,s,&mid);
        !          1613:     r = UPALLOC(2*d);
        !          1614:     bzero((char *)COEF(r),(2*d+1)*sizeof(Num));
        !          1615:     if ( lo )
        !          1616:       bcopy((char *)COEF(lo),(char *)COEF(r),(DEG(lo)+1)*sizeof(Num));
        !          1617:     if ( hi )
        !          1618:       bcopy((char *)COEF(hi),(char *)(COEF(r)+2*m),(DEG(hi)+1)*sizeof(Num));
        !          1619:     for ( i = 2*d; i >= 0 && !COEF(r)[i]; i-- );
        !          1620:     if ( i < 0 )
        !          1621:       r = 0;
        !          1622:     else {
        !          1623:       DEG(r) = i;
        !          1624:       t = UPALLOC(DEG(mid)+m); DEG(t) = DEG(mid)+m;
        !          1625:       bzero((char *)COEF(t),(DEG(mid)+m+1)*sizeof(Num));
        !          1626:       bcopy((char *)COEF(mid),(char *)(COEF(t)+m),(DEG(mid)+1)*sizeof(Num));
        !          1627:       addup(t,r,&s);
        !          1628:       r = s;
        !          1629:     }
        !          1630:   } else
        !          1631:     fft_mulup_lm(p1,p2,&r);
        !          1632:   uptop(r,rp);
1.1       noro     1633: }
                   1634:
1.16      noro     1635: void Pfmultest(NODE arg,LIST *rp)
1.1       noro     1636: {
1.30    ! noro     1637:   P p1,p2,r;
        !          1638:   int d1,d2;
        !          1639:   UM w1,w2,wr;
        !          1640:   unsigned int *f1,*f2,*fr,*w;
        !          1641:   int index,mod,root,d,maxint,i;
        !          1642:   int cond;
        !          1643:   Q prime;
        !          1644:   NODE n0,n1;
        !          1645:
        !          1646:   p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); index = QTOS((Q)ARG2(arg));
        !          1647:   FFT_primes(index,&mod,&root,&d);
        !          1648:   maxint = 1<<d;
        !          1649:   d1 = UDEG(p1); d2 = UDEG(p2);
        !          1650:   if ( maxint < d1+d2+1 )
        !          1651:     *rp = 0;
        !          1652:   else {
        !          1653:     w1 = W_UMALLOC(d1); w2 = W_UMALLOC(d2);
        !          1654:     wr = W_UMALLOC(d1+d2);
        !          1655:     ptoum(mod,p1,w1); ptoum(mod,p2,w2);
        !          1656:     f1 = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
        !          1657:     f2 = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
        !          1658:     fr = (unsigned int *)ALLOCA(maxint*sizeof(unsigned int));
        !          1659:     w = (unsigned int *)ALLOCA(12*maxint*sizeof(unsigned int));
        !          1660:
        !          1661:     for ( i = 0; i <= d1; i++ )
        !          1662:       f1[i] = (unsigned int)w1->c[i];
        !          1663:     for ( i = 0; i <= d2; i++ )
        !          1664:       f2[i] = (unsigned int)w2->c[i];
        !          1665:
        !          1666:     cond = FFT_pol_product(d1,f1,d2,f2,fr,index,w);
        !          1667:     if ( cond )
        !          1668:       error("fmultest : ???");
        !          1669:     wr->d = d1+d2;
        !          1670:     for ( i = 0; i <= d1+d2; i++ )
        !          1671:       wr->c[i] = (unsigned int)fr[i];
        !          1672:     umtop(VR(p1),wr,&r);
        !          1673:     STOQ(mod,prime);
        !          1674:     MKNODE(n1,prime,0);
        !          1675:     MKNODE(n0,r,n1);
        !          1676:     MKLIST(*rp,n0);
        !          1677:   }
1.1       noro     1678: }
                   1679:
1.16      noro     1680: void Pkmulum(NODE arg,P *rp)
1.1       noro     1681: {
1.30    ! noro     1682:   P p1,p2;
        !          1683:   int d1,d2,mod;
        !          1684:   UM w1,w2,wr;
        !          1685:
        !          1686:   p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); mod = QTOS((Q)ARG2(arg));
        !          1687:   d1 = UDEG(p1); d2 = UDEG(p2);
        !          1688:   w1 = W_UMALLOC(d1); w2 = W_UMALLOC(d2);
        !          1689:   wr = W_UMALLOC(d1+d2);
        !          1690:   ptoum(mod,p1,w1); ptoum(mod,p2,w2);
        !          1691:   kmulum(mod,w1,w2,wr);
        !          1692:   umtop(VR(p1),wr,rp);
1.1       noro     1693: }
                   1694:
1.16      noro     1695: void Pksquareum(NODE arg,P *rp)
1.1       noro     1696: {
1.30    ! noro     1697:   P p1;
        !          1698:   int d1,mod;
        !          1699:   UM w1,wr;
        !          1700:
        !          1701:   p1 = (P)ARG0(arg); mod = QTOS((Q)ARG1(arg));
        !          1702:   d1 = UDEG(p1);
        !          1703:   w1 = W_UMALLOC(d1);
        !          1704:   wr = W_UMALLOC(2*d1);
        !          1705:   ptoum(mod,p1,w1);
        !          1706:   kmulum(mod,w1,w1,wr);
        !          1707:   umtop(VR(p1),wr,rp);
1.1       noro     1708: }
                   1709:
1.16      noro     1710: void Ptracemod_gf2n(NODE arg,P *rp)
1.1       noro     1711: {
1.30    ! noro     1712:   UP g,f,r;
1.1       noro     1713:
1.30    ! noro     1714:   ptoup((P)ARG0(arg),&g);
        !          1715:   ptoup((P)ARG1(arg),&f);
        !          1716:   tracemodup_gf2n(g,f,(Q)ARG2(arg),&r);
        !          1717:   uptop(r,rp);
1.2       noro     1718: }
                   1719:
1.16      noro     1720: void Pumul_specialmod(NODE arg,P *rp)
1.2       noro     1721: {
1.30    ! noro     1722:   P a1,a2;
        !          1723:   UP p1,p2,r;
        !          1724:   int i,nmod;
        !          1725:   int *modind;
        !          1726:   NODE t,n;
        !          1727:
        !          1728:   a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
        !          1729:   if ( !a1 || !a2 || NUM(a1) || NUM(a2) )
        !          1730:     mulp(CO,a1,a2,rp);
        !          1731:   else {
        !          1732:     if ( !uzpcheck((Obj)a1) || !uzpcheck((Obj)a2) || VR(a1) != VR(a2) )
        !          1733:       error("umul_specialmod : invalid argument");
        !          1734:     ptoup(a1,&p1);
        !          1735:     ptoup(a2,&p2);
        !          1736:     n = BDY((LIST)ARG2(arg));
        !          1737:     nmod = length(n);
        !          1738:     modind = (int *)MALLOC_ATOMIC(nmod*sizeof(int));
        !          1739:     for ( i = 0, t = n; i < nmod; i++, t = NEXT(t) )
        !          1740:       modind[i] = QTOS((Q)BDY(t));
        !          1741:     fft_mulup_specialmod_main(p1,p2,0,modind,nmod,&r);
        !          1742:     uptop(r,rp);
        !          1743:   }
1.2       noro     1744: }
                   1745:
1.16      noro     1746: void Pusquare_specialmod(NODE arg,P *rp)
1.2       noro     1747: {
1.30    ! noro     1748:   P a1;
        !          1749:   UP p1,r;
        !          1750:   int i,nmod;
        !          1751:   int *modind;
        !          1752:   NODE t,n;
        !          1753:
        !          1754:   a1 = (P)ARG0(arg);
        !          1755:   if ( !a1 || NUM(a1) )
        !          1756:     mulp(CO,a1,a1,rp);
        !          1757:   else {
        !          1758:     if ( !uzpcheck((Obj)a1) )
        !          1759:       error("usquare_specialmod : invalid argument");
        !          1760:     ptoup(a1,&p1);
        !          1761:     n = BDY((LIST)ARG1(arg));
        !          1762:     nmod = length(n);
        !          1763:     modind = (int *)MALLOC_ATOMIC(nmod*sizeof(int));
        !          1764:     for ( i = 0, t = n; i < nmod; i++, t = NEXT(t) )
        !          1765:       modind[i] = QTOS((Q)BDY(t));
        !          1766:     fft_mulup_specialmod_main(p1,p1,0,modind,nmod,&r);
        !          1767:     uptop(r,rp);
        !          1768:   }
1.2       noro     1769: }
                   1770:
1.16      noro     1771: void Putmul_specialmod(NODE arg,P *rp)
1.2       noro     1772: {
1.30    ! noro     1773:   P a1,a2;
        !          1774:   UP p1,p2,r;
        !          1775:   int i,nmod;
        !          1776:   int *modind;
        !          1777:   NODE t,n;
        !          1778:
        !          1779:   a1 = (P)ARG0(arg); a2 = (P)ARG1(arg);
        !          1780:   if ( !a1 || !a2 || NUM(a1) || NUM(a2) )
        !          1781:     mulp(CO,a1,a2,rp);
        !          1782:   else {
        !          1783:     if ( !uzpcheck((Obj)a1) || !uzpcheck((Obj)a2) || VR(a1) != VR(a2) )
        !          1784:       error("utmul_specialmod : invalid argument");
        !          1785:     ptoup(a1,&p1);
        !          1786:     ptoup(a2,&p2);
        !          1787:     n = BDY((LIST)ARG3(arg));
        !          1788:     nmod = length(n);
        !          1789:     modind = (int *)MALLOC_ATOMIC(nmod*sizeof(int));
        !          1790:     for ( i = 0, t = n; i < nmod; i++, t = NEXT(t) )
        !          1791:       modind[i] = QTOS((Q)BDY(t));
        !          1792:     fft_mulup_specialmod_main(p1,p2,QTOS((Q)ARG2(arg))+1,modind,nmod,&r);
        !          1793:     uptop(r,rp);
        !          1794:   }
1.1       noro     1795: }

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