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

Annotation of OpenXM_contrib2/asir2018/builtin/poly.c, Revision 1.4

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.4     ! noro       48:  * $OpenXM: OpenXM_contrib2/asir2018/builtin/poly.c,v 1.3 2019/03/03 05:21:16 noro Exp $
1.1       noro       49: */
                     50: #include "ca.h"
                     51: #include "parse.h"
                     52: #include "base.h"
                     53:
                     54: void Pranp();
                     55:
                     56: void Pheadsgn();
                     57: void Pmul_trunc(),Pquo_trunc();
                     58: void Pumul(),Pumul_ff(),Pusquare(),Pusquare_ff(),Putmul(),Putmul_ff();
                     59: void Pkmul(),Pksquare(),Pktmul();
                     60: void Pord(), Premove_vars(), Pcoef0(), Pcoef(), Pdeg(), Pmindeg(), Psetmod();
                     61: void Pcoef_gf2n();
                     62: void getcoef(), getdeglist(), mergedeglist(), change_mvar(), restore_mvar();
                     63:
                     64: void Pp_mag(),Pmaxblen();
                     65: void Pmergelist(), Pch_mv(), Pre_mv(), Pdeglist();
                     66: void Pptomp(),Pmptop();
                     67: void Pptolmp(),Plmptop();
                     68: void Pptosfp(),Psfptop(),Psf_galois_action(),Psf_embed(),Psf_find_root();
                     69: void Psf_minipoly(),Psf_log(),Psfptopsfp();
                     70: void Pptogf2n(),Pgf2ntop(),Pgf2ntovect();
                     71: void Pptogfpn(),Pgfpntop();
                     72: void Pfind_root_gf2n();
                     73: void Pumul_specialmod(),Pusquare_specialmod(),Putmul_specialmod();
                     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();
                    104: void Pget_next_fft_prime();
                    105: void Puadj_coef();
                    106: void Preorder();
                    107: void Phomogeneous_part();
                    108: void Phomogeneous_deg();
                    109: void simp_ff(Obj,Obj *);
                    110: void ranp(int,UP *);
                    111: void field_order_ff(Z *);
                    112:
                    113: int current_ff;
                    114:
                    115: struct ftab poly_tab[] = {
                    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},
                    231: };
                    232:
                    233: void Pheadsgn(NODE arg,Z *rp)
                    234: {
                    235:   int s;
                    236:
                    237:   s = headsgn((P)ARG0(arg));
1.2       noro      238:   STOZ(s,*rp);
1.1       noro      239: }
                    240:
                    241: void Pmul_trunc(NODE arg,P *rp)
                    242: {
                    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++ );
1.2       noro      263:     vn[i].n = ZTOS(DEG(DC(h)));
1.1       noro      264:   }
                    265:   mulp_trunc(vl,p1,p2,vn,rp);
                    266: }
                    267:
                    268: void Pquo_trunc(NODE arg,P *rp)
                    269: {
                    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++ );
1.2       noro      293:       vn[i].n = ZTOS(DEG(DC(h)));
1.1       noro      294:     }
                    295:     quop_trunc(vl,p1,p2,vn,rp);
                    296:   }
                    297: }
                    298:
                    299: void Phomogeneous_part(NODE arg,P *rp)
                    300: {
                    301:   if ( argc(arg) == 2 )
1.2       noro      302:     exthp(CO,(P)ARG0(arg),ZTOS((Q)ARG1(arg)),rp);
1.1       noro      303:   else
1.2       noro      304:     exthpc_generic(CO,(P)ARG0(arg),ZTOS((Q)ARG2(arg)),
1.1       noro      305:       VR((P)ARG1(arg)),rp);
                    306: }
                    307:
                    308: void Phomogeneous_deg(NODE arg,Z *rp)
                    309: {
                    310:   int d;
                    311:
                    312:   if ( argc(arg) == 1 )
                    313:     d = homdeg((P)ARG0(arg));
                    314:   else
                    315:     d = getchomdeg(VR((P)ARG1(arg)),(P)ARG0(arg));
1.2       noro      316:   STOZ(d,*rp);
1.1       noro      317: }
                    318:
                    319: /*
                    320:   p1 = reorder(p,ovl,nvl) => p1 is 'sorted accoding to nvl.
                    321: */
                    322:
                    323: void Preorder(NODE arg,P *rp)
                    324: {
                    325:   VL ovl,nvl,tvl;
                    326:   NODE n;
                    327:
                    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);
                    345: }
                    346:
                    347: /*
                    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);
                    354: */
                    355:
                    356: void Puadj_coef(NODE arg,P *rp)
                    357: {
                    358:   UP f,r;
                    359:   Z m,m2;
                    360:
                    361:   ptoup((P)ARG0(arg),&f);
                    362:   m = (Z)ARG1(arg);
                    363:   m2 = (Z)ARG2(arg);
                    364:   adj_coefup(f,m,m2,&r);
                    365:   uptop(r,rp);
                    366: }
                    367:
                    368: /*
                    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)
                    373: */
                    374:
                    375: void Pget_next_fft_prime(NODE arg,LIST *rp)
                    376: {
                    377:   unsigned int mod,d;
                    378:   int start,bits,i;
                    379:   NODE n;
                    380:   Z q,ind;
                    381:
1.2       noro      382:   start = ZTOS((Q)ARG0(arg));
                    383:   bits = ZTOS((Q)ARG1(arg));
1.1       noro      384:   for ( i = start; ; i++ ) {
1.4     ! noro      385:     get_fft_prime(i,(int *)&mod,(int *)&d);
1.1       noro      386:     if ( !mod ) {
                    387:       *rp = 0; return;
                    388:     }
                    389:     if ( bits <= (int)d ) {
1.2       noro      390:       UTOZ(mod,q);
                    391:       UTOZ(i,ind);
1.1       noro      392:       n = mknode(2,ind,q);
                    393:       MKLIST(*rp,n);
                    394:       return;
                    395:     }
                    396:   }
                    397: }
                    398:
                    399: void Pranp(NODE arg,P *rp)
                    400: {
                    401:   int n;
                    402:   UP c;
                    403:
1.2       noro      404:   n = ZTOS((Q)ARG0(arg));
1.1       noro      405:   ranp(n,&c);
                    406:   if ( c ) {
                    407:     up_var = VR((P)ARG1(arg));
                    408:     uptop(c,rp);
                    409:   } else
                    410:     *rp = 0;
                    411: }
                    412:
                    413: void ranp(int n,UP *nr)
                    414: {
                    415:   int i;
                    416:   unsigned int r;
                    417:   Z q;
                    418:   UP c;
                    419:
                    420:   *nr = c = UPALLOC(n);
                    421:   for ( i = 0; i <= n; i++ ) {
                    422:     r = random();
1.2       noro      423:     UTOZ(r,q);
1.1       noro      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;
                    431: }
                    432:
                    433: void Pmaxblen(NODE arg,Z *rp)
                    434: {
                    435:   int l;
                    436:   l = maxblenp(ARG0(arg));
1.2       noro      437:   STOZ(l,*rp);
1.1       noro      438: }
                    439:
                    440: void Pp_mag(NODE arg,Z *rp)
                    441: {
                    442:   int l;
                    443:   l = p_mag(ARG0(arg));
1.2       noro      444:   STOZ(l,*rp);
1.1       noro      445: }
                    446:
                    447: void Pord(NODE arg,LIST *listp)
                    448: {
                    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;
                    459:
                    460: #if 0
                    461: printf("LASTCO="); printv(CO,LASTCO->v); printf("\n");
                    462: #endif
                    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;
                    521: }
                    522:
                    523: void Premove_vars(NODE arg,LIST *listp)
                    524: {
                    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;
                    555: }
                    556:
                    557: void Pcoef0(NODE arg,Obj *rp)
                    558: {
                    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 && cmpz(DEG(dc),(Z)n); dc = NEXT(dc) );
                    591:     if ( dc )
                    592:       *rp = (Obj)COEF(dc);
                    593:     else
                    594:       *rp = 0;
                    595:   }
                    596: }
                    597:
                    598: void Pcoef(NODE arg,Obj *rp)
                    599: {
                    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,(Z)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 && cmpz(DEG(dc),(Z)n); dc = NEXT(dc) );
                    631:     if ( dc )
                    632:       *rp = (Obj)COEF(dc);
                    633:     else
                    634:       *rp = 0;
                    635:   }
                    636: }
                    637:
                    638: void Pcoef_gf2n(NODE arg,Obj *rp)
                    639: {
                    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 ) {
1.2       noro      649:     d = ZTOS((Q)n);
1.1       noro      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;
                    657: }
                    658:
                    659: void Pdeg(NODE arg,Z *rp)
                    660: {
                    661:   Obj t,v;
                    662:   int d;
                    663:
                    664: #if 0
                    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));
                    671: #endif
                    672:   if ( !(t = (Obj)ARG0(arg)) )
1.2       noro      673:     STOZ(-1,*rp);
1.1       noro      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);
1.2       noro      678:       STOZ(d,*rp);
1.1       noro      679:     } else
                    680:       *rp = 0;
                    681:   } else
                    682:     degp(VR((P)ARG1(arg)),(P)ARG0(arg),rp);
                    683: }
                    684:
                    685: void Pmindeg(NODE arg,Z *rp)
                    686: {
                    687:   Obj t;
                    688:
                    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);
                    693: }
                    694:
                    695: void Psetmod(NODE arg,Z *rp)
                    696: {
                    697:   if ( arg ) {
                    698:     asir_assert(ARG0(arg),O_N,"setmod");
1.2       noro      699:     current_mod = ZTOS((Q)ARG0(arg));
1.1       noro      700:   }
1.2       noro      701:   STOZ(current_mod,*rp);
1.1       noro      702: }
                    703:
                    704: void Psparsemod_gf2n(NODE arg,Z *rp)
                    705: {
                    706:   int id;
                    707:
                    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;
1.2       noro      714:   STOZ(id,*rp);
1.1       noro      715: }
                    716:
                    717: void Pmultest_gf2n(NODE arg,GF2N *rp)
                    718: {
                    719:   GF2N a,b,c;
                    720:   int i;
                    721:
                    722:   a = (GF2N)ARG0(arg); b = (GF2N)ARG0(arg);
                    723:   for ( i = 0; i < 10000; i++ )
                    724:     mulgf2n(a,b,&c);
                    725:   *rp = c;
                    726: }
                    727:
                    728: void Psquaretest_gf2n(NODE arg,GF2N *rp)
                    729: {
                    730:   GF2N a,c;
                    731:   int i;
                    732:
                    733:   a = (GF2N)ARG0(arg);
                    734:   for ( i = 0; i < 10000; i++ )
                    735:     squaregf2n(a,&c);
                    736:   *rp = c;
                    737: }
                    738:
                    739: void Pinvtest_gf2n(NODE arg,GF2N *rp)
                    740: {
                    741:   GF2N a,c;
                    742:   int i;
                    743:
                    744:   a = (GF2N)ARG0(arg);
                    745:   for ( i = 0; i < 10000; i++ )
                    746:     invgf2n(a,&c);
                    747:   *rp = c;
                    748: }
                    749:
                    750: void Pbininv_gf2n(NODE arg,GF2N *rp)
                    751: {
                    752:   UP2 a,inv;
                    753:   int n;
                    754:
                    755:   a = ((GF2N)ARG0(arg))->body;
1.2       noro      756:   n = ZTOS((Q)ARG1(arg));
1.1       noro      757:   type1_bin_invup2(a,n,&inv);
                    758:   MKGF2N(inv,*rp);
                    759: }
                    760:
                    761: void Prinvtest_gf2n(Real *rp)
                    762: {
                    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);
                    779: }
                    780:
                    781: void Pfind_root_gf2n(NODE arg,GF2N *rp)
                    782: {
                    783:
                    784: #if 0
                    785:   UP p;
                    786:
                    787:   ptoup((P)ARG0(arg),&p);
                    788:   find_root_gf2n(p,rp);
                    789: #else
                    790:   UP2 p;
                    791:
                    792:   ptoup2((P)ARG0(arg),&p);
                    793:   find_root_up2(p,rp);
                    794: #endif
                    795: }
                    796:
                    797: void Pis_irred_gf2(NODE arg,Z *rp)
                    798: {
                    799:   UP2 t;
                    800:
                    801:   ptoup2(ARG0(arg),&t);
                    802:   *rp = irredcheckup2(t) ? ONE : 0;
                    803: }
                    804:
                    805: void Pis_irred_ddd_gf2(NODE arg,Z *rp)
                    806: {
                    807:   UP2 t;
                    808:   int ret;
                    809:
                    810:   ptoup2(ARG0(arg),&t);
                    811:   ret = irredcheck_dddup2(t);
1.2       noro      812:   STOZ(ret,*rp);
1.1       noro      813: }
                    814:
                    815: void Psetmod_ff(NODE arg,Obj *rp)
                    816: {
                    817:   int ac;
                    818:   int d;
                    819:   Obj mod,defpoly;
                    820:   Z n;
                    821:   UP up;
                    822:   UP2 up2;
                    823:   UM dp;
                    824:   Z 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 )
                    833:             current_ff = FF_NOT_SET;
                    834:         else {
                    835:       switch ( OID(mod) ) {
                    836:       case O_N:
                    837:         current_ff = FF_GFP;
                    838:         setmod_lm((Z)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;
1.2       noro      851:       setmod_sf(ZTOS((Q)ARG0(arg)),ZTOS((Q)ARG1(arg)));
1.1       noro      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((Z)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;
1.2       noro      864:     setmod_sf(ZTOS((Q)ARG0(arg)),ZTOS((Q)ARG1(arg)));
                    865:     d = ZTOS((Q)ARG2(arg));
1.1       noro      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); *rp = (Obj)n; break;
                    873:     case FF_GF2N:
                    874:       getmod_gf2n(&up2); up2top(up2,&p); *rp = (Obj)p; break;
                    875:     case FF_GFPN:
                    876:       getmod_lm(&n);
                    877:       getmod_gfpn(&up); uptop(up,&p);
                    878:       MKNODE(n1,n,0); MKNODE(n0,p,n1);
                    879:       MKLIST(list,n0);
                    880:       *rp = (Obj)list; break;
                    881:     case FF_GFS:
                    882:     case FF_GFSN:
1.2       noro      883:       STOZ(current_gfs_p,q);
1.1       noro      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
1.2       noro      893:           STOZ(current_gfs_iton[1],r);
1.1       noro      894:         p = (P)r;
                    895:       }
                    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:   }
                    912: }
                    913:
                    914: void Pextdeg_ff(Z *rp)
                    915: {
                    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:
1.2       noro      925:       getmod_gf2n(&up2); d = degup2(up2); STOZ(d,*rp); break;
1.1       noro      926:     case FF_GFPN:
1.2       noro      927:       getmod_gfpn(&up); STOZ(up->d,*rp); break;
1.1       noro      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);
1.2       noro      936:       STOZ(DEG(dp),*rp);
1.1       noro      937:       break;
                    938:     default:
                    939:       error("extdeg_ff : current_ff is not set");
                    940:   }
                    941: }
                    942:
                    943: void Pcharacteristic_ff(Z *rp)
                    944: {
                    945:   switch ( current_ff ) {
                    946:     case FF_GFP:
                    947:     case FF_GFPN:
                    948:       getmod_lm(rp); break;
                    949:     case FF_GF2N:
1.2       noro      950:       STOZ(2,*rp); break;
1.1       noro      951:     case FF_GFS:
                    952:     case FF_GFSN:
1.2       noro      953:       STOZ(current_gfs_p,*rp); break;
1.1       noro      954:     default:
                    955:       error("characteristic_ff : current_ff is not set");
                    956:   }
                    957: }
                    958:
                    959: void Pfield_type_ff(Z *rp)
                    960: {
1.2       noro      961:   STOZ(current_ff,*rp);
1.1       noro      962: }
                    963:
                    964: void Pfield_order_ff(Z *rp)
                    965: {
                    966:   field_order_ff(rp);
                    967: }
                    968:
                    969: void Prandom_ff(Obj *rp)
                    970: {
                    971:   LM l;
                    972:   GF2N g;
                    973:   GFPN p;
                    974:   GFS s;
                    975:   GFSN spn;
                    976:
                    977:   switch ( current_ff ) {
                    978:     case FF_GFP:
                    979:       random_lm(&l); *rp = (Obj)l; break;
                    980:     case FF_GF2N:
                    981:       randomgf2n(&g); *rp = (Obj)g; break;
                    982:     case FF_GFPN:
                    983:       randomgfpn(&p); *rp = (Obj)p; break;
                    984:     case FF_GFS:
                    985:       randomgfs(&s); *rp = (Obj)s; break;
                    986:     case FF_GFSN:
                    987:       randomgfsn(&spn); *rp = (Obj)spn; break;
                    988:     default:
                    989:       error("random_ff : current_ff is not set");
                    990:   }
                    991: }
                    992:
                    993: void Psimp_ff(NODE arg,Obj *rp)
                    994: {
                    995:   simp_ff((Obj)ARG0(arg),rp);
                    996: }
                    997:
                    998: void getcoef(VL vl,P p,V v,Z d,P *r)
                    999: {
                   1000:   P s,t,u,a,b,x;
                   1001:   DCP dc;
                   1002:   V w;
                   1003:
                   1004:   if ( !p )
                   1005:     *r = 0;
                   1006:   else if ( NUM(p) )
                   1007:     *r = d ? 0 : p;
                   1008:   else if ( (w=VR(p)) == v ) {
                   1009:     for ( dc = DC(p); dc && cmpz(DEG(dc),d); dc = NEXT(dc) );
                   1010:     *r = dc ? COEF(dc) : 0;
                   1011:   } else {
                   1012:     MKV(w,x);
                   1013:     for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
                   1014:       getcoef(vl,COEF(dc),v,d,&t);
                   1015:       if ( t ) {
                   1016:         pwrp(vl,x,DEG(dc),&u); mulp(vl,t,u,&a);
                   1017:         addp(vl,s,a,&b); s = b;
                   1018:       }
                   1019:     }
                   1020:     *r = s;
                   1021:   }
                   1022: }
                   1023:
                   1024: void Pdeglist(NODE arg,LIST *rp)
                   1025: {
                   1026:   NODE d;
                   1027:
                   1028:   getdeglist((P)ARG0(arg),VR((P)ARG1(arg)),&d);
                   1029:   MKLIST(*rp,d);
                   1030: }
                   1031:
                   1032: void Pch_mv(NODE arg,P *rp)
                   1033: {
                   1034:   change_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
                   1035: }
                   1036:
                   1037: void Pre_mv(NODE arg,P *rp)
                   1038: {
                   1039:   restore_mvar(CO,(P)ARG0(arg),VR((P)ARG1(arg)),rp);
                   1040: }
                   1041:
                   1042: void change_mvar(VL vl,P p,V v,P *r)
                   1043: {
                   1044:   Z d;
                   1045:   DCP dc,dc0;
                   1046:   NODE dl;
                   1047:
                   1048:   if ( !p || NUM(p) || (VR(p) == v) )
                   1049:     *r = p;
                   1050:   else {
                   1051:     getdeglist(p,v,&dl);
                   1052:     for ( dc0 = 0; dl; dl = NEXT(dl) ) {
                   1053:       NEXTDC(dc0,dc); DEG(dc) = d = (Z)BDY(dl);
                   1054:       getcoef(vl,p,v,d,&COEF(dc));
                   1055:     }
                   1056:     NEXT(dc) = 0; MKP(v,dc0,*r);
                   1057:   }
                   1058: }
                   1059:
                   1060: void restore_mvar(VL vl,P p,V v,P *r)
                   1061: {
                   1062:   P s,u,a,b,x;
                   1063:   DCP dc;
                   1064:
                   1065:   if ( !p || NUM(p) || (VR(p) != v) )
                   1066:     *r = p;
                   1067:   else {
                   1068:     MKV(v,x);
                   1069:     for ( dc = DC(p), s = 0; dc; dc = NEXT(dc) ) {
                   1070:       pwrp(vl,x,DEG(dc),&u); mulp(vl,COEF(dc),u,&a);
                   1071:       addp(vl,s,a,&b); s = b;
                   1072:     }
                   1073:     *r = s;
                   1074:   }
                   1075: }
                   1076:
                   1077: void getdeglist(P p,V v,NODE *d)
                   1078: {
                   1079:   NODE n,n0,d0,d1,d2;
                   1080:   DCP dc;
                   1081:
                   1082:   if ( !p || NUM(p) ) {
                   1083:     MKNODE(n,0,0); *d = n;
                   1084:   } else if ( VR(p) == v ) {
                   1085:     for ( n0 = 0, dc = DC(p); dc; dc = NEXT(dc) ) {
                   1086:       NEXTNODE(n0,n); BDY(n) = (pointer)DEG(dc);
                   1087:     }
                   1088:     NEXT(n) = 0; *d = n0;
                   1089:   } else {
                   1090:     for ( dc = DC(p), d0 = 0; dc; dc = NEXT(dc) ) {
                   1091:       getdeglist(COEF(dc),v,&d1); mergedeglist(d0,d1,&d2); d0 = d2;
                   1092:     }
                   1093:     *d = d0;
                   1094:   }
                   1095: }
                   1096:
                   1097: void Pmergelist(NODE arg,LIST *rp)
                   1098: {
                   1099:     NODE n;
                   1100:
                   1101:   asir_assert(ARG0(arg),O_LIST,"mergelist");
                   1102:   asir_assert(ARG1(arg),O_LIST,"mergelist");
                   1103:   mergedeglist(BDY((LIST)ARG0(arg)),BDY((LIST)ARG1(arg)),&n);
                   1104:   MKLIST(*rp,n);
                   1105: }
                   1106:
                   1107: void mergedeglist(NODE d0,NODE d1,NODE *dr)
                   1108: {
                   1109:   NODE t0,t,dt;
                   1110:   Z d;
                   1111:   int c;
                   1112:
                   1113:   if ( !d0 )
                   1114:     *dr = d1;
                   1115:   else {
                   1116:     while ( d1 ) {
                   1117:       dt = d1; d1 = NEXT(d1); d = (Z)BDY(dt);
                   1118:       for ( t0 = 0, t = d0; t; t0 = t, t = NEXT(t) ) {
                   1119:         c = cmpz(d,(Z)BDY(t));
                   1120:         if ( !c )
                   1121:           break;
                   1122:         else if ( c > 0 ) {
                   1123:           if ( !t0 ) {
                   1124:             NEXT(dt) = d0; d0 = dt;
                   1125:           } else {
                   1126:             NEXT(t0) = dt; NEXT(dt) = t;
                   1127:           }
                   1128:           break;
                   1129:         }
                   1130:       }
                   1131:       if ( !t ) {
                   1132:         NEXT(t0) = dt; *dr = d0; return;
                   1133:       }
                   1134:     }
                   1135:     *dr = d0;
                   1136:   }
                   1137: }
                   1138:
                   1139: void Pptomp(NODE arg,P *rp)
                   1140: {
                   1141:   int mod;
                   1142:
                   1143:   if ( argc(arg) == 1 ) {
                   1144:     if ( !current_mod )
                   1145:       error("ptomp : current_mod is not set");
                   1146:     else
                   1147:       mod = current_mod;
                   1148:   } else
1.2       noro     1149:     mod = ZTOS((Q)ARG1(arg));
1.1       noro     1150:   ptomp(mod,(P)ARG0(arg),rp);
                   1151: }
                   1152:
                   1153: void Pmptop(NODE arg,P *rp)
                   1154: {
                   1155:   mptop((P)ARG0(arg),rp);
                   1156: }
                   1157:
                   1158: void Pptolmp(NODE arg,P *rp)
                   1159: {
                   1160:   ptolmp((P)ARG0(arg),rp);
                   1161: }
                   1162:
                   1163: void Plmptop(NODE arg,P *rp)
                   1164: {
                   1165:   lmptop((P)ARG0(arg),rp);
                   1166: }
                   1167:
                   1168: void Psf_galois_action(NODE arg,P *rp)
                   1169: {
                   1170:   sf_galois_action(ARG0(arg),ARG1(arg),rp);
                   1171: }
                   1172:
                   1173: /*
                   1174:   sf_embed(F,B,PM)
                   1175:   F : an element of GF(pn)
                   1176:   B : the image of the primitive root of GF(pn)
                   1177:   PM : order of GF(pm)
                   1178: */
                   1179:
                   1180: void Psf_embed(NODE arg,P *rp)
                   1181: {
                   1182:   int k,pm;
                   1183:
                   1184:   /* GF(pn)={0,1,a,a^2,...}->GF(pm)={0,1,b,b^2,...}; a->b^k */
                   1185:   k = CONT((GFS)ARG1(arg));
1.2       noro     1186:   pm = ZTOS((Q)ARG2(arg));
1.1       noro     1187:   sf_embed((P)ARG0(arg),k,pm,rp);
                   1188: }
                   1189:
                   1190: void Psf_log(NODE arg,Z *rp)
                   1191: {
                   1192:   int k;
                   1193:
                   1194:   if ( !ARG0(arg) )
                   1195:     error("sf_log : invalid armument");
                   1196:   k = CONT((GFS)ARG0(arg));
1.2       noro     1197:   STOZ(k,*rp);
1.1       noro     1198: }
                   1199:
                   1200: void Psf_find_root(NODE arg,GFS *rp)
                   1201: {
                   1202:   P p;
                   1203:   Obj t;
                   1204:   int d;
                   1205:   UM u;
                   1206:   int *root;
                   1207:
                   1208:   p = (P)ARG0(arg);
                   1209:   simp_ff((Obj)p,&t); p = (P)t;
                   1210:   d = getdeg(VR(p),p);
                   1211:   u = W_UMALLOC(d);
                   1212:   ptosfum(p,u);
                   1213:   root = (int *)ALLOCA(d*sizeof(int));
                   1214:   find_rootsf(u,root);
                   1215:   MKGFS(IFTOF(root[0]),*rp);
                   1216: }
                   1217:
                   1218: void Psf_minipoly(NODE arg,P *rp)
                   1219: {
                   1220:   Obj t;
                   1221:   P p1,p2;
                   1222:   int d1,d2;
                   1223:   UM up1,up2,m;
                   1224:
                   1225:   p1 = (P)ARG0(arg); simp_ff((Obj)p1,&t); p1 = (P)t;
                   1226:   p2 = (P)ARG1(arg); simp_ff((Obj)p2,&t); p2 = (P)t;
                   1227:   d1 = getdeg(VR(p1),p1); up1 = W_UMALLOC(d1); ptosfum(p1,up1);
                   1228:   d2 = getdeg(VR(p2),p2); up2 = W_UMALLOC(d2); ptosfum(p2,up2);
                   1229:   m = W_UMALLOC(d2);
                   1230:   minipolysf(up1,up2,m);
                   1231:   sfumtop(VR(p2),m,&p1);
                   1232:   sfptop(p1,rp);
                   1233: }
                   1234:
                   1235: void Pptosfp(NODE arg,P *rp)
                   1236: {
                   1237:   ptosfp(ARG0(arg),rp);
                   1238: }
                   1239:
                   1240: void Psfptop(NODE arg,P *rp)
                   1241: {
                   1242:   sfptop((P)ARG0(arg),rp);
                   1243: }
                   1244:
                   1245: void Psfptopsfp(NODE arg,P *rp)
                   1246: {
                   1247:   sfptopsfp((P)ARG0(arg),VR((P)ARG1(arg)),rp);
                   1248: }
                   1249:
                   1250: void Pptogf2n(NODE arg,GF2N *rp)
                   1251: {
                   1252:   ptogf2n((Obj)ARG0(arg),rp);
                   1253: }
                   1254:
                   1255: void Pgf2ntop(NODE arg,P *rp)
                   1256: {
                   1257:   if ( argc(arg) == 2 )
                   1258:     up2_var = VR((P)ARG1(arg));
                   1259:   gf2ntop((GF2N)ARG0(arg),rp);
                   1260: }
                   1261:
                   1262: void Pgf2ntovect(NODE arg,VECT *rp)
                   1263: {
                   1264:   gf2ntovect((GF2N)ARG0(arg),rp);
                   1265: }
                   1266:
                   1267: void Pptogfpn(NODE arg,GFPN *rp)
                   1268: {
                   1269:   ptogfpn((Obj)ARG0(arg),rp);
                   1270: }
                   1271:
                   1272: void Pgfpntop(NODE arg,P *rp)
                   1273: {
                   1274:   if ( argc(arg) == 2 )
                   1275:     up_var = VR((P)ARG1(arg));
                   1276:   gfpntop((GFPN)ARG0(arg),rp);
                   1277: }
                   1278:
                   1279: void Pureverse(NODE arg,P *rp)
                   1280: {
                   1281:   UP p,r;
                   1282:
                   1283:   ptoup((P)ARG0(arg),&p);
                   1284:   if ( argc(arg) == 1 )
                   1285:     reverseup(p,p->d,&r);
                   1286:   else
1.2       noro     1287:     reverseup(p,ZTOS((Q)ARG1(arg)),&r);
1.1       noro     1288:   uptop(r,rp);
                   1289: }
                   1290:
                   1291: void Putrunc(NODE arg,P *rp)
                   1292: {
                   1293:   UP p,r;
                   1294:
                   1295:   ptoup((P)ARG0(arg),&p);
1.2       noro     1296:   truncup(p,ZTOS((Q)ARG1(arg))+1,&r);
1.1       noro     1297:   uptop(r,rp);
                   1298: }
                   1299:
                   1300: void Pudecomp(NODE arg,LIST *rp)
                   1301: {
                   1302:   P u,l;
                   1303:   UP p,up,low;
                   1304:   NODE n0,n1;
                   1305:
                   1306:   ptoup((P)ARG0(arg),&p);
1.2       noro     1307:   decompup(p,ZTOS((Q)ARG1(arg))+1,&low,&up);
1.1       noro     1308:   uptop(low,&l);
                   1309:   uptop(up,&u);
                   1310:   MKNODE(n1,u,0); MKNODE(n0,l,n1);
                   1311:   MKLIST(*rp,n0);
                   1312: }
                   1313:
                   1314: void Purembymul(NODE arg,P *rp)
                   1315: {
                   1316:   UP p1,p2,r;
                   1317:
                   1318:   if ( !ARG0(arg) || !ARG1(arg) )
                   1319:     *rp = 0;
                   1320:   else {
                   1321:     ptoup((P)ARG0(arg),&p1);
                   1322:     ptoup((P)ARG1(arg),&p2);
                   1323:     rembymulup(p1,p2,&r);
                   1324:     uptop(r,rp);
                   1325:   }
                   1326: }
                   1327:
                   1328: /*
                   1329:  * d1 = deg(p1), d2 = deg(p2)
                   1330:  * d1 <= 2*d2-1
                   1331:  * p2*inv = 1 mod x^d2
                   1332:  */
                   1333:
                   1334: void Purembymul_precomp(NODE arg,P *rp)
                   1335: {
                   1336:   UP p1,p2,inv,r;
                   1337:
                   1338:   if ( !ARG0(arg) || !ARG1(arg) )
                   1339:     *rp = 0;
                   1340:   else {
                   1341:     ptoup((P)ARG0(arg),&p1);
                   1342:     ptoup((P)ARG1(arg),&p2);
                   1343:     ptoup((P)ARG2(arg),&inv);
                   1344:     if ( p1->d >= 2*p2->d ) {
                   1345:       error("urembymul_precomp : degree of 1st arg is too large");
                   1346: /*      fprintf(stderr,"urembymul_precomp : degree of 1st arg is too large"); */
                   1347:       remup(p1,p2,&r);
                   1348:     } else
                   1349:       hybrid_rembymulup_special(current_ff,p1,p2,inv,&r);
                   1350:     uptop(r,rp);
                   1351:   }
                   1352: }
                   1353:
                   1354: void Puinvmod(NODE arg,P *rp)
                   1355: {
                   1356:   UP p,r;
                   1357:
                   1358:   ptoup((P)ARG0(arg),&p);
1.2       noro     1359:   invmodup(p,ZTOS((Q)ARG1(arg)),&r);
1.1       noro     1360:   uptop(r,rp);
                   1361: }
                   1362:
                   1363: void Purevinvmod(NODE arg,P *rp)
                   1364: {
                   1365:   UP p,pr,r;
                   1366:
                   1367:   ptoup((P)ARG0(arg),&p);
                   1368:   reverseup(p,p->d,&pr);
1.2       noro     1369:   invmodup(pr,ZTOS((Q)ARG1(arg)),&r);
1.1       noro     1370:   uptop(r,rp);
                   1371: }
                   1372:
                   1373: void Ppwrmod_ff(NODE arg,P *rp)
                   1374: {
                   1375:   UP p1,p2;
                   1376:
                   1377:   ptoup((P)ARG0(arg),&p1);
                   1378:   switch ( current_ff ) {
                   1379:     case FF_GFP:
1.3       noro     1380: /* XXX : hybrid version may not be useful ... */
                   1381: #if 1
1.1       noro     1382:       hybrid_powermodup(p1,&p2); break;
1.3       noro     1383: #else
                   1384:       powermodup(p1,&p2); break;
                   1385: #endif
1.1       noro     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);
                   1396: }
                   1397:
                   1398: void Pgeneric_pwrmod_ff(NODE arg,P *rp)
                   1399: {
                   1400:   UP g,f,r;
                   1401:
                   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,(Z)ARG2(arg),&r); break;
                   1407:     case FF_GF2N:
                   1408:       generic_powermodup_gf2n(g,f,(Z)ARG2(arg),&r); break;
                   1409:     case FF_GFPN:
                   1410:     case FF_GFS:
                   1411:     case FF_GFSN:
                   1412:       generic_powermodup(g,f,(Z)ARG2(arg),&r); break;
                   1413:     default:
                   1414:       error("generic_pwrmod_ff : current_ff is not set");
                   1415:   }
                   1416:   uptop(r,rp);
                   1417: }
                   1418:
                   1419: void Ppwrtab_ff(NODE arg,VECT *rp)
                   1420: {
                   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]);
                   1446: }
                   1447:
                   1448: void Pkpwrmod_lm(NODE arg,P *rp)
                   1449: {
                   1450:   UP p1,p2;
                   1451:
                   1452:   ptoup((P)ARG0(arg),&p1);
                   1453:   powermodup(p1,&p2);
                   1454:   uptop(p2,rp);
                   1455: }
                   1456:
                   1457: void Pkgeneric_pwrmod_lm(NODE arg,P *rp)
                   1458: {
                   1459:   UP g,f,r;
                   1460:
                   1461:   ptoup((P)ARG0(arg),&g);
                   1462:   ptoup((P)ARG1(arg),&f);
                   1463:   generic_powermodup(g,f,(Z)ARG2(arg),&r);
                   1464:   uptop(r,rp);
                   1465: }
                   1466:
                   1467: void Pkpwrtab_lm(NODE arg,VECT *rp)
                   1468: {
                   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]);
                   1483: }
                   1484:
                   1485: void Plazy_lm(NODE arg,Q *rp)
                   1486: {
1.2       noro     1487:   lm_lazy = ZTOS((Q)ARG0(arg));
1.1       noro     1488:   *rp = 0;
                   1489: }
                   1490:
                   1491: void Pkmul(NODE arg,P *rp)
                   1492: {
                   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);
                   1499: }
                   1500:
                   1501: void Pksquare(NODE arg,P *rp)
                   1502: {
                   1503:   P n1;
                   1504:
                   1505:   n1 = (P)ARG0(arg);
                   1506:   asir_assert(n1,O_P,"ksquare");
                   1507:   ksquarep(CO,n1,rp);
                   1508: }
                   1509:
                   1510: void Pktmul(NODE arg,P *rp)
                   1511: {
                   1512:   UP p1,p2,r;
                   1513:
                   1514:   ptoup((P)ARG0(arg),&p1);
                   1515:   ptoup((P)ARG1(arg),&p2);
1.2       noro     1516:   tkmulup(p1,p2,ZTOS((Q)ARG2(arg))+1,&r);
1.1       noro     1517:   uptop(r,rp);
                   1518: }
                   1519:
                   1520: void Pumul(NODE arg,P *rp)
                   1521: {
                   1522:   P a1,a2;
                   1523:   UP p1,p2,r;
                   1524:
                   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:   }
                   1536: }
                   1537:
                   1538: void Pusquare(NODE arg,P *rp)
                   1539: {
                   1540:   UP p1,r;
                   1541:
                   1542:   ptoup((P)ARG0(arg),&p1);
                   1543:   hybrid_squareup(0,p1,&r);
                   1544:   uptop(r,rp);
                   1545: }
                   1546:
                   1547: void Putmul(NODE arg,P *rp)
                   1548: {
                   1549:   UP p1,p2,r;
                   1550:
                   1551:   ptoup((P)ARG0(arg),&p1);
                   1552:   ptoup((P)ARG1(arg),&p2);
1.2       noro     1553:   hybrid_tmulup(0,p1,p2,ZTOS((Q)ARG2(arg))+1,&r);
1.1       noro     1554:   uptop(r,rp);
                   1555: }
                   1556:
                   1557: void Pumul_ff(NODE arg,Obj *rp)
                   1558: {
                   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);
                   1569: }
                   1570:
                   1571: void Pusquare_ff(NODE arg,Obj *rp)
                   1572: {
                   1573:   UP p1,r;
                   1574:   P p;
                   1575:
                   1576:   ptoup((P)ARG0(arg),&p1);
                   1577:   hybrid_squareup(current_ff,p1,&r);
                   1578:   uptop(r,&p);
                   1579:   simp_ff((Obj)p,rp);
                   1580: }
                   1581:
                   1582: void Putmul_ff(NODE arg,Obj *rp)
                   1583: {
                   1584:   UP p1,p2,r;
                   1585:   P p;
                   1586:
                   1587:   ptoup((P)ARG0(arg),&p1);
                   1588:   ptoup((P)ARG1(arg),&p2);
1.2       noro     1589:   hybrid_tmulup(current_ff,p1,p2,ZTOS((Q)ARG2(arg))+1,&r);
1.1       noro     1590:   uptop(r,&p);
                   1591:   simp_ff((Obj)p,rp);
                   1592: }
                   1593:
                   1594: void Phfmul_lm(NODE arg,P *rp)
                   1595: {
                   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);
                   1633: }
                   1634:
                   1635: void Pfmultest(NODE arg,LIST *rp)
                   1636: {
                   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:   Z prime;
                   1644:   NODE n0,n1;
                   1645:
1.2       noro     1646:   p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); index = ZTOS((Q)ARG2(arg));
1.1       noro     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);
1.2       noro     1673:     STOZ(mod,prime);
1.1       noro     1674:     MKNODE(n1,prime,0);
                   1675:     MKNODE(n0,r,n1);
                   1676:     MKLIST(*rp,n0);
                   1677:   }
                   1678: }
                   1679:
                   1680: void Pkmulum(NODE arg,P *rp)
                   1681: {
                   1682:   P p1,p2;
                   1683:   int d1,d2,mod;
                   1684:   UM w1,w2,wr;
                   1685:
1.2       noro     1686:   p1 = (P)ARG0(arg); p2 = (P)ARG1(arg); mod = ZTOS((Q)ARG2(arg));
1.1       noro     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);
                   1693: }
                   1694:
                   1695: void Pksquareum(NODE arg,P *rp)
                   1696: {
                   1697:   P p1;
                   1698:   int d1,mod;
                   1699:   UM w1,wr;
                   1700:
1.2       noro     1701:   p1 = (P)ARG0(arg); mod = ZTOS((Q)ARG1(arg));
1.1       noro     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);
                   1708: }
                   1709:
                   1710: void Ptracemod_gf2n(NODE arg,P *rp)
                   1711: {
                   1712:   UP g,f,r;
                   1713:
                   1714:   ptoup((P)ARG0(arg),&g);
                   1715:   ptoup((P)ARG1(arg),&f);
                   1716:   tracemodup_gf2n(g,f,(Z)ARG2(arg),&r);
                   1717:   uptop(r,rp);
                   1718: }
                   1719:
                   1720: void Pumul_specialmod(NODE arg,P *rp)
                   1721: {
                   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) )
1.2       noro     1740:       modind[i] = ZTOS((Q)BDY(t));
1.1       noro     1741:     fft_mulup_specialmod_main(p1,p2,0,modind,nmod,&r);
                   1742:     uptop(r,rp);
                   1743:   }
                   1744: }
                   1745:
                   1746: void Pusquare_specialmod(NODE arg,P *rp)
                   1747: {
                   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) )
1.2       noro     1765:       modind[i] = ZTOS((Q)BDY(t));
1.1       noro     1766:     fft_mulup_specialmod_main(p1,p1,0,modind,nmod,&r);
                   1767:     uptop(r,rp);
                   1768:   }
                   1769: }
                   1770:
                   1771: void Putmul_specialmod(NODE arg,P *rp)
                   1772: {
                   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) )
1.2       noro     1791:       modind[i] = ZTOS((Q)BDY(t));
                   1792:     fft_mulup_specialmod_main(p1,p2,ZTOS((Q)ARG2(arg))+1,modind,nmod,&r);
1.1       noro     1793:     uptop(r,rp);
                   1794:   }
                   1795: }

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