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>