[BACK]Return to coeff.c CVS log [TXT][DIR] Up to [local] / OpenXM / src / kan96xx / Kan

Annotation of OpenXM/src/kan96xx/Kan/coeff.c, Revision 1.1

1.1     ! maekawa     1: #include <stdio.h>
        !             2: #include "datatype.h"
        !             3: #include "stackm.h"
        !             4: #include "extern.h"
        !             5: #include "extern2.h"
        !             6:
        !             7:
        !             8: static void printTag(coeffType t)
        !             9: {
        !            10:   switch(t) {
        !            11:   case UNKNOWN: fprintf(stderr," UNKNOWN "); break;
        !            12:   case INTEGER: fprintf(stderr," INTEGER "); break;
        !            13:   case MP_INTEGER: fprintf(stderr," MP_INTEGER "); break;
        !            14:   case POLY_COEFF: fprintf(stderr," POLY_COEFF "); break;
        !            15:   default: fprintf(stderr," Unknown tag of coeffType."); break;
        !            16:   }
        !            17: }
        !            18:
        !            19: char *intToString(i)
        !            20: int i;
        !            21: {
        !            22:   char work[80];
        !            23:   char *s;
        !            24:   sprintf(work,"%d",i);
        !            25:   s = (char *)sGC_malloc((strlen(work)+2)*sizeof(char));
        !            26:   if (s == (char *)NULL) errorCoeff("No more memory.");
        !            27:   strcpy(s,work);
        !            28:   return(s);
        !            29: }
        !            30:
        !            31: char *coeffToString(cp)
        !            32: struct coeff *cp;
        !            33: {
        !            34:   char *s;
        !            35:   switch(cp->tag) {
        !            36:   case INTEGER:
        !            37:     return(intToString((cp->val).i));
        !            38:     break;
        !            39:   case MP_INTEGER:
        !            40:     s = mpz_get_str((char *)NULL,10,(cp->val).bigp);
        !            41:     return(s);
        !            42:     break;
        !            43:   case POLY_COEFF:
        !            44:     s = POLYToString((cp->val).f,'*',1);
        !            45:     return(s);
        !            46:     break;
        !            47:   default:
        !            48:     warningCoeff("coeffToString: Unknown tag.");
        !            49:     return(" Unknown-coeff ");
        !            50:     break;
        !            51:   }
        !            52: }
        !            53:
        !            54: /* constructors */
        !            55: struct coeff *intToCoeff(i,ringp)
        !            56: int i;
        !            57: struct ring *ringp;
        !            58: {
        !            59:   struct coeff *c;
        !            60:   int p;
        !            61:   c =newCoeff();
        !            62:   if (ringp->next != (struct ring *)NULL) {
        !            63:     c->tag = POLY_COEFF;
        !            64:     c->val.f = cxx(i,0,0,ringp->next);
        !            65:     c->p = ringp->p;
        !            66:   }else{
        !            67:     p = ringp->p;
        !            68:     if (p) {
        !            69:       c->tag = INTEGER; c->p = p;
        !            70:       c->val.i = i % p;
        !            71:     }else{
        !            72:       c->tag = MP_INTEGER; c->p = 0;
        !            73:       c->val.bigp = newMP_INT();
        !            74:       mpz_set_si(c->val.bigp,(long) i);
        !            75:     }
        !            76:   }
        !            77:   return(c);
        !            78: }
        !            79:
        !            80: struct coeff *mpintToCoeff(b,ringp)
        !            81: MP_INT *b;
        !            82: struct ring *ringp;
        !            83: {
        !            84:   struct coeff *c;
        !            85:   struct coeff *c2;
        !            86:   int p;
        !            87:   c =newCoeff();
        !            88:   p = ringp->p;
        !            89:   if (ringp->next == (struct ring *)NULL) {
        !            90:     if (p) {
        !            91:       c->tag = INTEGER; c->p = p;
        !            92:       c->val.i = ((int) mpz_get_si(b)) % p;
        !            93:     }else{
        !            94:       c->tag = MP_INTEGER; c->p = 0;
        !            95:       c->val.bigp = b;
        !            96:     }
        !            97:     return(c);
        !            98:   }else{
        !            99:     c2 = mpintToCoeff(b,ringp->next);
        !           100:     c->tag = POLY_COEFF;
        !           101:     c->p = ringp->p;
        !           102:     c->val.f = coeffToPoly(c2,ringp->next);
        !           103:     return(c);
        !           104:     /*
        !           105:     errorCoeff("mpintToCoeff(): mpint --> poly_coeff has not yet be supported. Returns 0.");
        !           106:     c->tag = POLY_COEFF;
        !           107:     c->val.f = ZERO;
        !           108:     */
        !           109:   }
        !           110: }
        !           111:
        !           112: struct coeff *polyToCoeff(f,ringp)
        !           113: POLY f;
        !           114: struct ring *ringp;
        !           115: {
        !           116:   struct coeff *c;
        !           117:   if (f ISZERO) {
        !           118:     c =newCoeff();
        !           119:     c->tag = POLY_COEFF; c->p = ringp->p;
        !           120:     c->val.f = f;
        !           121:     return(c);
        !           122:   }
        !           123:   if (f->m->ringp != ringp->next) {
        !           124:     errorCoeff("polyToCoeff(): f->m->ringp != ringp->next. Returns 0.");
        !           125:     f = 0;
        !           126:   }
        !           127:   c =newCoeff();
        !           128:   c->tag = POLY_COEFF; c->p = ringp->p;
        !           129:   c->val.f = f;
        !           130:   return(c);
        !           131: }
        !           132:
        !           133: /* returns -c */
        !           134: struct coeff *coeffNeg(c,ringp)
        !           135: struct coeff *c;
        !           136: struct ring *ringp;
        !           137: {
        !           138:   struct coeff *r;
        !           139:   r = intToCoeff(-1,ringp);
        !           140:   Cmult(r,r,c);
        !           141:   return(r);
        !           142: }
        !           143:
        !           144: int coeffToInt(cp)
        !           145: struct coeff *cp;
        !           146: {
        !           147:   POLY f;
        !           148:   switch(cp->tag) {
        !           149:   case INTEGER:
        !           150:     return(cp->val.i);
        !           151:     break;
        !           152:   case MP_INTEGER:
        !           153:     return(mpz_get_si(cp->val.bigp));
        !           154:     break;
        !           155:   case POLY_COEFF:
        !           156:     f = cp->val.f;
        !           157:     if (f == ZERO) return(0);
        !           158:     else return(coeffToInt(f->coeffp));
        !           159:     break;
        !           160:   default:
        !           161:     errorCoeff("Unknown tag in coeffToInt().\n");
        !           162:   }
        !           163: }
        !           164:
        !           165: void Cadd(r,a,b)
        !           166: struct coeff *r;
        !           167: struct coeff *a;
        !           168: struct coeff *b;
        !           169: {
        !           170:   int p;
        !           171:   POLY f;
        !           172:
        !           173:   if (a->tag == INTEGER && b->tag == INTEGER && r->tag == INTEGER) {
        !           174:     r->p = p = a->p;
        !           175:     r->val.i = ((a->val.i) + (b->val.i)) % p;
        !           176:   }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER
        !           177:            && r->tag == MP_INTEGER) {
        !           178:     mpz_add(r->val.bigp,a->val.bigp,b->val.bigp);
        !           179:   }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF
        !           180:            && r->tag == POLY_COEFF) {
        !           181:     f = ppAdd(a->val.f,b->val.f);
        !           182:     r->val.f = f;
        !           183:   }else {
        !           184:     warningCoeff("Cadd(): The data type is not supported.");
        !           185:   }
        !           186: }
        !           187:
        !           188: void Csub(r,a,b)
        !           189: struct coeff *r;
        !           190: struct coeff *a;
        !           191: struct coeff *b;
        !           192: {
        !           193:   int p;
        !           194:
        !           195:   if (a->tag == INTEGER && b->tag == INTEGER && r->tag == INTEGER) {
        !           196:     r->p = p = a->p;
        !           197:     r->val.i = ((a->val.i) - (b->val.i)) % p;
        !           198:   }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER
        !           199:            && r->tag == MP_INTEGER) {
        !           200:     mpz_sub(r->val.bigp,a->val.bigp,b->val.bigp);
        !           201:   }else {
        !           202:     warningCoeff("Csub(): The data type is not supported.");
        !           203:   }
        !           204: }
        !           205:
        !           206: void Cmult(r,a,b)
        !           207: struct coeff *r;
        !           208: struct coeff *a;
        !           209: struct coeff *b;
        !           210: {
        !           211:   int p;
        !           212:   POLY f;
        !           213:
        !           214:   if (a->tag == INTEGER && b->tag == INTEGER && r->tag == INTEGER) {
        !           215:     r->p = p = a->p;
        !           216:     r->val.i = ((a->val.i) * (b->val.i)) % p;
        !           217:   }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER
        !           218:            && r->tag == MP_INTEGER) {
        !           219:     mpz_mul(r->val.bigp,a->val.bigp,b->val.bigp);
        !           220:   }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF
        !           221:            && r->tag == POLY_COEFF) {
        !           222:     f = ppMult(a->val.f,b->val.f);
        !           223:     r->val.f = f;
        !           224:   }else {
        !           225:     warningCoeff("Cmult(): The data type is not supported.");
        !           226:     printTag(a->tag); printTag(b->tag); printTag(r->tag); fprintf(stderr,"\n");
        !           227:     warningCoeff("Returns coeffCopy(a) ------------------");
        !           228:     printf("Type in return.\n");getchar(); getchar();
        !           229:     *r = *(coeffCopy(a));
        !           230:   }
        !           231: }
        !           232:
        !           233: int isZero(a)
        !           234: struct coeff *a;
        !           235: {
        !           236:   int r;
        !           237:   if (a->tag == INTEGER) {
        !           238:     if (a->val.i) return(0);
        !           239:     else return(1);
        !           240:   }else if (a->tag == MP_INTEGER) {
        !           241:     r = mpz_cmp_si(a->val.bigp,(long)0);
        !           242:     if (r == 0) return(1);
        !           243:     else return(0);
        !           244:   }else if (a->tag == POLY_COEFF) {
        !           245:     if (a->val.f ISZERO) return(1);
        !           246:     else return(0);
        !           247:   }else{
        !           248:     warningCoeff("CisZero(): The data type is not supported.");
        !           249:     return(1);
        !           250:   }
        !           251: }
        !           252:
        !           253: struct coeff *coeffCopy(c)
        !           254: struct coeff *c;
        !           255: /* Deep copy */
        !           256: {
        !           257:   struct coeff *r;
        !           258:   r = newCoeff();
        !           259:   switch(c->tag) {
        !           260:   case INTEGER:
        !           261:     r->tag = INTEGER;
        !           262:     r->p = c->p;
        !           263:     r->val.i = c->val.i;
        !           264:     break;
        !           265:   case MP_INTEGER:
        !           266:     r->tag = MP_INTEGER; r->p = 0;
        !           267:     r->val.bigp = newMP_INT();
        !           268:     mpz_set(r->val.bigp,c->val.bigp);
        !           269:     break;
        !           270:   case POLY_COEFF:
        !           271:     r->tag = POLY_COEFF;
        !           272:     r->p = c->p;
        !           273:     r->val.f = pcmCopy(c->val.f); /* The polynomial is deeply copied. */
        !           274:     break;
        !           275:   default:
        !           276:     warningCoeff("coeffCopy(): Unknown tag for the argument.");
        !           277:     break;
        !           278:   }
        !           279:   return(r);
        !           280: }
        !           281:
        !           282: void CiiComb(r,p,q)
        !           283: struct coeff *r;
        !           284: int p,q;
        !           285: /* r->val.bigp is read only. */
        !           286: {
        !           287:   switch(r->tag) {
        !           288:   case INTEGER:
        !           289:     r->val.i = iiComb(p,q,r->p);
        !           290:     break;
        !           291:   case MP_INTEGER:
        !           292:     r->val.bigp = BiiComb(p,q);
        !           293:     break;
        !           294:   default:
        !           295:     warningCoeff("CiiComb(): Unknown tag.");
        !           296:     break;
        !           297:   }
        !           298: }
        !           299:
        !           300:
        !           301:
        !           302: MP_INT *BiiComb(p,q)
        !           303: int p,q;
        !           304: /* It returns {p \choose q} when p>=0, 0<=q<=p.
        !           305:    The value is read only. DON'T CHANGE IT.
        !           306: p=0         0                1
        !           307: p=1       1   2            1    1
        !           308: p=2     3   4   5        1   2    1
        !           309:        q=0 q=1 q=2
        !           310:        [p(p+1)/2+q]
        !           311: */
        !           312: {
        !           313:   extern MP_INT *Mp_one;
        !           314:   int i,j;
        !           315:   MP_INT **newTable;
        !           316:   static MP_INT **table;
        !           317:   static int tableSize = 0;
        !           318:   static int maxp = 0; /* You have {p \choose q} in the table when p<maxp. */
        !           319:   if (p<=0 || q<=0) return(Mp_one);
        !           320:   if (p<=q) return(Mp_one);
        !           321:   if (p<maxp) return(table[(p*(p+1))/2+q]);
        !           322:   /* Enlarge the table if it's small. */
        !           323:   if ( !(p < tableSize) ) {
        !           324:     /* The new size is 2*p. */
        !           325:     newTable = (MP_INT **)sGC_malloc(sizeof(MP_INT *)*( (2*p*(2*p+1))/2));
        !           326:     if (newTable == (MP_INT **) NULL) errorCoeff("BiiComb(): No more memory.");
        !           327:     for (i=0; i<tableSize; i++) {
        !           328:       for (j=0; j<=i; j++) {
        !           329:        newTable[(i*(i+1))/2 + j] = table[(i*(i+1))/2 + j];
        !           330:       }
        !           331:     }
        !           332:     for (i=tableSize; i< 2*p; i++) {
        !           333:       for (j=0; j<=i; j++) {
        !           334:        if (j==0 || j==i) newTable[(i*(i+1))/2 + j] = Mp_one;
        !           335:        else{
        !           336:          newTable[(i*(i+1))/2 + j] = newMP_INT();
        !           337:        }
        !           338:       }
        !           339:     }
        !           340:     tableSize = 2*p;
        !           341:     table = newTable;
        !           342:   }
        !           343:   /* Compute the binomial coefficients up to {p \choose p} */
        !           344:   for (i=maxp; i<=p; i++) {
        !           345:     for (j=1; j<i; j++) {
        !           346:       mpz_add(table[(i*(i+1))/2 + j],
        !           347:             table[((i-1)*i)/2 + j-1],
        !           348:             table[((i-1)*i)/2 +j]);  /* [p-1,q-1]+[p-1,q] */
        !           349:     }
        !           350:   }
        !           351:   maxp = p+1;
        !           352:   return(table[(p*(p+1))/2 +q]);
        !           353:            /*   ^^^^^^ No problem for the optimizer? */
        !           354: }
        !           355:
        !           356: int iiComb(p,q,P)
        !           357: int p,q,P;
        !           358: {
        !           359: /**
        !           360:  foo[n_]:=Block[{p,q,ans},
        !           361:     ans={};
        !           362:     For[p=0,p<=n,p++,ans=Append[ans,Table[Binomial[p,q],{q,0,n}]]];
        !           363:     Return[ans];
        !           364:  ]
        !           365: **/
        !           366: /* We assume that int is 32 bit */
        !           367: static int table[26][26]=
        !           368: {{1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           369: {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           370: {1,2,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           371: {1,3,3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           372: {1,4,6,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           373: {1,5,10,10,5,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           374: {1,6,15,20,15,6,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           375: {1,7,21,35,35,21,7,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           376: {1,8,28,56,70,56,28,8,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           377: {1,9,36,84,126,126,84,36,9,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           378: {1,10,45,120,210,252,210,120,45,10,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           379: {1,11,55,165,330,462,462,330,165,55,11,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           380: {1,12,66,220,495,792,924,792,495,220,66,12,1,0,0,0,0,0,0,0,0,0,0,0,0,0},
        !           381: {1,13,78,286,715,1287,1716,1716,1287,715,286,78,13,1,0,0,0,0,0,0,0,0,0,0,0,0},
        !           382: {1,14,91,364,1001,2002,3003,3432,3003,2002,1001,364,91,14,1,0,0,0,0,0,0,0,0,0,0,0},
        !           383: {1,15,105,455,1365,3003,5005,6435,6435,5005,3003,1365,455,105,15,1,0,0,0,0,0,0,0,0,0,0},
        !           384: {1,16,120,560,1820,4368,8008,11440,12870,11440,8008,4368,1820,560,120,16,1,0,0,0,0,0,0,0,0,0},
        !           385: {1,17,136,680,2380,6188,12376,19448,24310,24310,19448,12376,6188,2380,680,136,17,1,0,0,0,0,0,0,0,0},
        !           386: {1,18,153,816,3060,8568,18564,31824,43758,48620,43758,31824,18564,8568,3060,816,153,18,1,0,0,0,0,0,0,0},
        !           387: {1,19,171,969,3876,11628,27132,50388,75582,92378,92378,75582,50388,27132,11628,3876,969,171,19,1,0,0,0,0,0,0},
        !           388: {1,20,190,1140,4845,15504,38760,77520,125970,167960,184756,167960,125970,77520,38760,15504,4845,1140,190,20,1,0,0,0,0,0},
        !           389: {1,21,210,1330,5985,20349,54264,116280,203490,293930,352716,352716,293930,203490,116280,54264,20349,5985,1330,210,21,1,0,0,0,0},
        !           390: {1,22,231,1540,7315,26334,74613,170544,319770,497420,646646,705432,646646,497420,319770,170544,74613,26334,7315,1540,231,22,1,0,0,0},
        !           391: {1,23,253,1771,8855,33649,100947,245157,490314,817190,1144066,1352078,1352078,1144066,817190,490314,245157,100947,33649,8855,1771,253,23,1,0,0},
        !           392: {1,24,276,2024,10626,42504,134596,346104,735471,1307504,1961256,2496144,2704156,2496144,1961256,1307504,735471,346104,134596,42504,10626,2024,276,24,1,0},
        !           393: {1,25,300,2300,12650,53130,177100,480700,1081575,2042975,3268760,4457400,5200300,5200300,4457400,3268760,2042975,1081575,480700,177100,53130,12650,2300,300,25,1}};
        !           394:
        !           395:   int a,b;
        !           396:   extern MP_INT Mp_work_iiComb;
        !           397:
        !           398:   if ((p<=0) || (q<=0)) return( 1 );
        !           399:   if (p <= q) return( 1 );
        !           400:   if (p<26)  return( table[p][q] % P);
        !           401:   else {
        !           402:     mpz_mod_ui(&Mp_work_iiComb,BiiComb(p,q),(unsigned long) P);
        !           403:     return((int) mpz_get_si(&Mp_work_iiComb));
        !           404:   }
        !           405:   /*a=iiComb(p-1,q-1,P); b=iiComb(p-1,q,P);
        !           406:     a = a+b; a %= P;
        !           407:     return(a);
        !           408:   */
        !           409: }
        !           410:
        !           411:
        !           412: MP_INT *BiiPoch(p,q)
        !           413: int p,q;
        !           414: {
        !           415: /* It returns  p(p-1) ... (p-q+1) = [p,q] when p>=0 and 0<=q or
        !           416:                                                p<0  and 0<=q.
        !           417:    [p,q] = p*[p-1,q-1].  [p,0] = 1.
        !           418:    The value is read only. DON'T CHANGE IT.
        !           419:
        !           420: When p>=0,
        !           421: p=0         0                1
        !           422: p=1       1   2            1    1
        !           423: p=2     3   4   5        1   2    2*1
        !           424: p=3   6   7   8   9    1   3   3*2    3*2*1,  if p<q,then 0.
        !           425:        [p(p+1)/2+q]
        !           426:
        !           427: When p<0, [p,q] is indexed by (-p+q)(-p+q+1)/2 + q.
        !           428: -p+q = pq.
        !           429:
        !           430: q=3  0  (-1)(-2)(-3)  (-2)(-3)(-4)   (-3)(-4)(-5)
        !           431: q=2  0  (-1)(-2)      (-2)(-3)       (-3)(-4)
        !           432: q=1  0   -1            -2             -3
        !           433: q=0  1    1             1              1
        !           434:    -p=0  -p=2          -p=3           -p=4
        !           435: */
        !           436:   extern MP_INT *Mp_one;
        !           437:   extern MP_INT *Mp_zero;
        !           438:   MP_INT mp_work;
        !           439:   int i,j;
        !           440:   MP_INT **newTable;
        !           441:   static MP_INT **table;
        !           442:   static int tableSize = 0;
        !           443:   static int maxp = 0;
        !           444:   static MP_INT **tablepq;
        !           445:   static int tablepqSize = 0;
        !           446:   static int maxpq = 0;
        !           447:   int pq;
        !           448:
        !           449:   if (p>=0) {
        !           450:     if (q < 0) {
        !           451:       warningCoeff("Negative argument to BiiPoch(). Returns zero.");
        !           452:       return(Mp_zero);
        !           453:     }
        !           454:     if (q == 0) return(Mp_one);
        !           455:     if (p<q) return(Mp_zero);
        !           456:     if (p<maxp) return(table[(p*(p+1))/2+q]);
        !           457:     /* Enlarge the table if it's small. */
        !           458:     if ( !(p < tableSize) ) {
        !           459:       /* The new size is 2*p. */
        !           460:       newTable = (MP_INT **)sGC_malloc(sizeof(MP_INT *)*( (2*p*(2*p+1))/2));
        !           461:       if (newTable == (MP_INT **) NULL) errorCoeff("BiiPoch(): No more memory.");
        !           462:       for (i=0; i<tableSize; i++) {
        !           463:        for (j=0; j<=i; j++) {
        !           464:          newTable[(i*(i+1))/2 + j] = table[(i*(i+1))/2 + j];
        !           465:        }
        !           466:       }
        !           467:       for (i=tableSize; i< 2*p; i++) {
        !           468:        for (j=0; j<=i; j++) {
        !           469:          if (j==0) newTable[(i*(i+1))/2 + j] = Mp_one;
        !           470:          else{
        !           471:            newTable[(i*(i+1))/2 + j] = newMP_INT();
        !           472:          }
        !           473:        }
        !           474:       }
        !           475:       tableSize = 2*p;
        !           476:       table = newTable;
        !           477:     }
        !           478:     /* Compute the binomial coefficients up to {p \choose p} */
        !           479:     for (i=maxp; i<=p; i++) {
        !           480:       for (j=1; j<=i; j++) {
        !           481:        mpz_mul_ui(table[(i*(i+1))/2 + j],
        !           482:                   table[((i-1)*i)/2 + j-1],
        !           483:                   (unsigned long int) i); /* [i,j] = i*[i-1,j-1] */
        !           484:       }
        !           485:     }
        !           486:     maxp = p+1;
        !           487:     return(table[(p*(p+1))/2 +q]);
        !           488:     /*   ^^^^^^ No problem for the optimizer? */
        !           489:   }else{
        !           490:     if (q < 0) {
        !           491:       warningCoeff("Negative argument to BiiPoch(). Returns zero.");
        !           492:       return(Mp_zero);
        !           493:     }
        !           494:     if (q == 0) return(Mp_one);
        !           495:     pq = -p+q;
        !           496:     if (pq<maxpq) return(tablepq[(pq*(pq+1))/2+q]);
        !           497:     /* Enlarge the table if it's small. */
        !           498:     if ( !(pq < tablepqSize) ) {
        !           499:       /* The new size is 2*pq. */
        !           500:       newTable = (MP_INT **)sGC_malloc(sizeof(MP_INT *)*( (2*pq*(2*pq+1))/2));
        !           501:       if (newTable == (MP_INT **) NULL) errorCoeff("BiiPoch(): No more memory.");
        !           502:       for (i=0; i<tablepqSize; i++) {
        !           503:        for (j=0; j<=i; j++) {
        !           504:          newTable[(i*(i+1))/2 + j] = tablepq[(i*(i+1))/2 + j];
        !           505:        }
        !           506:       }
        !           507:       for (i=tablepqSize; i< 2*pq; i++) {
        !           508:        for (j=0; j<=i; j++) {
        !           509:          if (j==0) newTable[(i*(i+1))/2 + j] = Mp_one;
        !           510:          else if (j==i) newTable[(i*(i+1))/2+j] = Mp_zero;
        !           511:          else { /*^^^ no problem for optimizer? */
        !           512:            newTable[(i*(i+1))/2 + j] = newMP_INT();
        !           513:          }
        !           514:        }
        !           515:       }
        !           516:       tablepqSize = 2*pq;
        !           517:       tablepq = newTable;
        !           518:     }
        !           519:     /* Compute the Poch up to [p,q], -p+q<=pq */
        !           520:     mpz_init(&mp_work);
        !           521:     for (i=maxpq; i<=pq; i++) {
        !           522:       for (j=1; j<i; j++) {
        !           523:        mpz_set_si(&mp_work,-(i-j));
        !           524:        mpz_mul(tablepq[(i*(i+1))/2 + j],
        !           525:                tablepq[(i*(i+1))/2 + j-1],
        !           526:                &mp_work); /* [i,j] = i*[i-1,j-1] */
        !           527:       }
        !           528:     }
        !           529:     maxpq = pq+1;
        !           530:     return(tablepq[(pq*(pq+1))/2 +q]);
        !           531:     /*   ^^^^^^ No problem for the optimizer? */
        !           532:   }
        !           533: }
        !           534:
        !           535:
        !           536: int iiPoch(p,k,P) int p,k,P; /* p(p-1)...(p-k+1) */ {
        !           537:   int r,i;
        !           538:
        !           539:   /*
        !           540:   extern MP_INT Mp_work_iiPoch;
        !           541:   mpz_mod_ui(&Mp_work_iiPoch,BiiPoch(p,k),(unsigned long) P);
        !           542:   return((int) mpz_get_si(&Mp_work_iiPoch));
        !           543:   100 test takes 16ms.
        !           544:   */
        !           545:
        !           546:   if (p>=0 && p < k) return(0);
        !           547:   r = 1;
        !           548:   for (i=0;i<k;i++) {
        !           549:     r = r*(p-i);  r %= P;
        !           550:   }
        !           551:   return(r);
        !           552: }
        !           553:
        !           554: void CiiPoch(r,p,q)
        !           555: struct coeff *r;
        !           556: int p,q;
        !           557: /* r->val.bigp is read only. */
        !           558: {
        !           559:   switch(r->tag) {
        !           560:   case INTEGER:
        !           561:     r->val.i = iiPoch(p,q,r->p);
        !           562:     break;
        !           563:   case MP_INTEGER:
        !           564:     r->val.bigp = BiiPoch(p,q);
        !           565:     break;
        !           566:   default:
        !           567:     warningCoeff("CiiPoch(): Unknown tag.");
        !           568:     break;
        !           569:   }
        !           570: }
        !           571:
        !           572: MP_INT *BiiPower(p,q)
        !           573: int p,q;
        !           574: /* It returns  p^q.  q must be >=0.
        !           575:    p^q = [p,q] = p*[p,q-1].
        !           576:    The value is read only. DON'T CHANGE IT.
        !           577: */
        !           578:   /*
        !           579: [p,q] is indexed by table2D[p+q,q]=table1D[(p+q)(p+q+1)/2 + q].
        !           580: p+q = pq.
        !           581:
        !           582: q=3  0    1             8             27
        !           583: q=2  0    1             4              9
        !           584: q=1  0    1             2              3
        !           585: q=0  1    1             1              1
        !           586:    -p=0  -p=1          -p=2           -p=3
        !           587:   */
        !           588: {
        !           589:   extern MP_INT *Mp_one;
        !           590:   extern MP_INT *Mp_zero;
        !           591:   MP_INT mp_work;
        !           592:   int i,j;
        !           593:   MP_INT **newTable;
        !           594:   MP_INT **newTable2;
        !           595:   static MP_INT **table;
        !           596:   static int tableSize = 0;
        !           597:   static int maxp = 0;
        !           598:   static MP_INT **tableneg;
        !           599:   int pq;
        !           600:
        !           601:
        !           602:   if (q < 0) {
        !           603:     warningCoeff("Negative argument to BiiPower(). Returns zero.");
        !           604:     return(Mp_zero);
        !           605:   }
        !           606:   if (q == 0) return(Mp_one);
        !           607:   if (p>=0) {
        !           608:     pq = p+q;
        !           609:   }else {
        !           610:     pq = -p+q;
        !           611:   }
        !           612:   if (pq<maxp && p>=0) return(table[(pq*(pq+1))/2+q]);
        !           613:   if (pq<maxp && p<0) return(tableneg[(pq*(pq+1))/2+q]);
        !           614:
        !           615:   /* Enlarge the table if it's small. */
        !           616:   if ( !(pq < tableSize) ) {
        !           617:     /* The new size is 2*pq. */
        !           618:     newTable = (MP_INT **)sGC_malloc(sizeof(MP_INT *)*( (2*pq*(2*pq+1))/2));
        !           619:     newTable2 = (MP_INT **)sGC_malloc(sizeof(MP_INT *)*( (2*pq*(2*pq+1))/2));
        !           620:     if (newTable == (MP_INT **) NULL || newTable2 == (MP_INT **)NULL)
        !           621:       errorCoeff("BiiPower(): No more memory.");
        !           622:     for (i=0; i<tableSize; i++) {
        !           623:       for (j=0; j<=i; j++) {
        !           624:        newTable[(i*(i+1))/2 + j] = table[(i*(i+1))/2 + j];
        !           625:        newTable2[(i*(i+1))/2 + j] = tableneg[(i*(i+1))/2 + j];
        !           626:       }
        !           627:     }
        !           628:     for (i=tableSize; i< 2*pq; i++) {
        !           629:       for (j=0; j<=i; j++) {
        !           630:        if (j==0) {
        !           631:          newTable[(i*(i+1))/2 + j] = Mp_one;
        !           632:          newTable2[(i*(i+1))/2 + j] = Mp_one;
        !           633:        } else if (j==i) {
        !           634:          newTable[(i*(i+1))/2+j] = Mp_zero;
        !           635:          newTable2[(i*(i+1))/2+j] = Mp_zero;
        !           636:        }else { /*^^^ no problem for optimizer? */
        !           637:          newTable[(i*(i+1))/2 + j] = newMP_INT();
        !           638:          newTable2[(i*(i+1))/2 + j] = newMP_INT();
        !           639:        }
        !           640:       }
        !           641:     }
        !           642:     table = newTable;
        !           643:     tableneg = newTable2;
        !           644:     tableSize = 2*pq;
        !           645:   }
        !           646:   /* Compute the Power up to [p,q], p+q<=pq */
        !           647:   mpz_init(&mp_work);
        !           648:   for (i=maxp; i<=pq; i++) {
        !           649:     for (j=1; j<i; j++) {
        !           650:       mpz_set_si(&mp_work,-(i-j));
        !           651:       mpz_mul(tableneg[(i*(i+1))/2 + j],
        !           652:              tableneg[((i-1)*i)/2 + j-1],
        !           653:              &mp_work); /* (-(i-j))^j=[i,j] = (-i+j)*[i-1,j-1] */
        !           654:       mpz_set_si(&mp_work,i-j);
        !           655:       mpz_mul(table[(i*(i+1))/2 + j],
        !           656:              table[((i-1)*i)/2 + j-1],
        !           657:              &mp_work); /* (i-j)^j=[i,j] = (i-j)*[i-1,j-1] */
        !           658:     }
        !           659:   }
        !           660:   maxp = pq+1;
        !           661:   if (p>=0) {
        !           662:     return(table[(pq*(pq+1))/2 +q]);
        !           663:   }else{
        !           664:     return(tableneg[(pq*(pq+1))/2 +q]);
        !           665:   }
        !           666: }
        !           667:
        !           668: int iiPower(k,s,P)
        !           669: int k;
        !           670: int s;  /* k^s ,  s>=0*/
        !           671: int P;
        !           672: {
        !           673:   int kk,r;
        !           674:   r = 1;
        !           675:   for (kk=0; kk<s; kk++ ) {
        !           676:     r *= k; r %= P;
        !           677:   }
        !           678:   return(r);
        !           679: }
        !           680:
        !           681: void CiiPower(r,p,q)
        !           682: struct coeff *r;
        !           683: int p,q;
        !           684: /* r->val.bigp is read only. */
        !           685: {
        !           686:   switch(r->tag) {
        !           687:   case INTEGER:
        !           688:     r->val.i = iiPower(p,q,r->p);
        !           689:     break;
        !           690:   case MP_INTEGER:
        !           691:     r->val.bigp = BiiPower(p,q);
        !           692:     break;
        !           693:   default:
        !           694:     warningCoeff("CiiPower(): Unknown tag.");
        !           695:     break;
        !           696:   }
        !           697: }
        !           698:
        !           699: struct coeff *stringToUniversalNumber(s,flagp)
        !           700: char *s;
        !           701: int *flagp;
        !           702: {
        !           703:   MP_INT *value;
        !           704:   struct coeff * c;
        !           705:   value =newMP_INT();
        !           706:   *flagp = mpz_set_str(value,s,10);
        !           707:   c = newCoeff();
        !           708:   c->tag = MP_INTEGER; c->p = 0;
        !           709:   c->val.bigp = value;
        !           710:   return(c);
        !           711: }
        !           712:
        !           713: struct coeff *newUniversalNumber(i)
        !           714: int i;
        !           715: { extern struct ring *SmallRingp;
        !           716:   struct coeff *c;
        !           717:   c = intToCoeff(i,SmallRingp);
        !           718:   return(c);
        !           719: }
        !           720:
        !           721: struct coeff *newUniversalNumber2(i)
        !           722: MP_INT *i;
        !           723: { extern struct ring *SmallRingp;
        !           724:   struct coeff *c;
        !           725:   c = mpintToCoeff(i,SmallRingp);
        !           726:   return(c);
        !           727: }
        !           728:
        !           729: int coeffEqual(a,b)
        !           730: struct coeff *a;
        !           731: struct coeff *b;
        !           732: {
        !           733:   if (a->tag == INTEGER && b->tag == INTEGER) {
        !           734:     return((a->val.i) == (b->val.i));
        !           735:   }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER) {
        !           736:     if (mpz_cmp(a->val.bigp,b->val.bigp)==0) return(1);
        !           737:     else return(0);
        !           738:   }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF) {
        !           739:     return(ppSub(a->val.f,b->val.f) ISZERO);
        !           740:   }else {
        !           741:     warningCoeff("coeffEqual(): The data type is not supported.");
        !           742:   }
        !           743: }
        !           744:
        !           745: int coeffGreater(a,b)
        !           746: struct coeff *a;
        !           747: struct coeff *b;
        !           748: {
        !           749:   if (a->tag == INTEGER && b->tag == INTEGER) {
        !           750:     return((a->val.i) - (b->val.i));
        !           751:   }else if (a->tag == MP_INTEGER && b->tag == MP_INTEGER) {
        !           752:     return(mpz_cmp(a->val.bigp,b->val.bigp));
        !           753:   }else if (a->tag == POLY_COEFF && b->tag == POLY_COEFF) {
        !           754:     warningCoeff("coeffGreater(POLY,POLY) always returns 0.");
        !           755:     return(0);
        !           756:   }else {
        !           757:     warningCoeff("coeffGreater(): The data type is not supported.");
        !           758:   }
        !           759: }
        !           760:
        !           761: void universalNumberDiv(r,a,b)
        !           762: struct coeff *r;
        !           763: struct coeff *a;
        !           764: struct coeff *b;
        !           765: {
        !           766:   if (a->tag == MP_INTEGER && b->tag == MP_INTEGER && r->tag == MP_INTEGER) {
        !           767:     mpz_div(r->val.bigp,a->val.bigp,b->val.bigp);
        !           768:   }else {
        !           769:     warningCoeff("universalNumberDiv(): The data type is not supported.");
        !           770:   }
        !           771: }
        !           772:
        !           773: /* Note that it does not check if c is zero or not. cf isZero(). */
        !           774: POLY coeffToPoly(c,ringp)
        !           775: struct coeff *c;
        !           776: struct ring *ringp;
        !           777: { int p;
        !           778:   struct coeff *tc;
        !           779:
        !           780:   if (c->tag == INTEGER) {
        !           781:     tc = intToCoeff(c->val.i,ringp);
        !           782:     return(newCell(tc,newMonomial(ringp)));
        !           783:   }else if (c->tag == MP_INTEGER) {
        !           784:     tc = mpintToCoeff(c->val.bigp,ringp);
        !           785:     return(newCell(tc,newMonomial(ringp)));
        !           786:   } else if (c->tag == POLY_COEFF) {
        !           787:     return(newCell(c,newMonomial(ringp)));
        !           788:   }else {
        !           789:     warningCoeff("coeffToPoly(): The data type is not supported. Return 0.");
        !           790:     return(ZERO);
        !           791:   }
        !           792: }
        !           793: void errorCoeff(str)
        !           794: char *str;
        !           795: {
        !           796:   fprintf(stderr,"Error(coeff.c): %s\n",str);
        !           797:   fprintf(stderr,"Type in ctrl-\\");getchar();
        !           798:   exit(15);
        !           799: }
        !           800:
        !           801: void warningCoeff(str)
        !           802: char *str;
        !           803: {
        !           804:   fprintf(stderr,"Warning(coeff.c): %s\n",str);
        !           805: }
        !           806:

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