Annotation of OpenXM/src/Ti/binomial.c, Revision 1.1
1.1 ! maekawa 1: /*
! 2: ** binomial.c Birk Huber, 4/99
! 3: ** -- define binomal type and main operations on binomials
! 4: **
! 5: **
! 6: ** TiGERS, Toric Groebner Basis Enumeration by Reverse Search
! 7: ** copyright (c) 1999 Birk Huber
! 8: **
! 9: */
! 10: #define BINOMIAL_H 1
! 11: #include<stdio.h>
! 12: #include<stdlib.h>
! 13: #include "utils.h"
! 14: #include "binomial.h"
! 15: extern int NT;
! 16:
! 17: /*
! 18: **-------------ring defs-----------------------------------------------------
! 19: **
! 20: ** Monomials in the ambiant polynomial ring will be represented by their
! 21: ** exponent vectors. Before any computations can be done using monomials the
! 22: ** dimension of this ring (and the exponent vectors) must be set and stored
! 23: ** in the global variable "ring_N". The mapping between indeces and variable
! 24: ** names for i.o. purposes is currently done by just using the first ring_N
! 25: ** letters of the alphabet.
! 26: **
! 27: ** Data:
! 28: ** int ring_N: global variable holding dimension of ambiant ring
! 29: ** int ring_lv: global variable used by deg-rev-lex term order, i.e. specify
! 30: ** which variable to make cheepest(others ordered alphabetically)
! 31: **
! 32: ** Functions (or macros):
! 33: ** int ring_set(int n): Set ring_N to n if ring_N has not yet been set.
! 34: ** int ring_read(File *infile): Read in a description of the ring from
! 35: ** infile and set ring values accordingly.
! 36: ** ring_getvar(FILE *): convert next variable name on FILE to variable index
! 37: ** ring_putvar(File *of,int v): convert index to variable name.
! 38: **
! 39: ** Note: for now a ring description is just given the number of variables.
! 40: ** the names are just the first ring_N letters of the alphabet:
! 41: ** i.e. ** name <====> index
! 42: ** 'a' <====> 1
! 43: ** 'b' <====> 1
! 44: ** eventually this scheme may be adjusted to allow names to be set
! 45: ** at run time.
! 46: */
! 47: int ring_N=0;
! 48: int ring_lv=-1;
! 49: int *ring_weight=0;
! 50:
! 51: int ring_set(int n){
! 52: int i;
! 53: if (ring_N!=0) {
! 54: fprintf(stderr,"ring_set(): can't reset dimension\n");
! 55: return FALSE;
! 56: }
! 57: if ((ring_weight=(int *)(malloc(n*sizeof(int))))==0){
! 58: fprintf(stderr,"ring_set(): malloc failed for weight vector\n");
! 59: return FALSE;
! 60: }
! 61: for(i=0;i<n;i++) ring_weight[i]=1;
! 62: return ring_N=n;
! 63: }
! 64:
! 65: int ring_read(FILE *infile){
! 66: int n;
! 67: eatwhite(infile);
! 68: if (fscanf(infile,"%d",&n)!=1){
! 69: fprintf(stderr,"ERROR: read_ring() unable to parse ring description\n");
! 70: return FALSE;
! 71: }
! 72: ring_set(n);
! 73: return TRUE;
! 74: }
! 75:
! 76: int ring_getvar(FILE *ifile){
! 77: char c;
! 78: c=fgetc(ifile);
! 79: if ('a' > c || c >'a'+ring_N-1){
! 80: fprintf(stderr,"ring_getvar(): invalid variable read\n");
! 81: ungetc(c,ifile);
! 82: return -1;
! 83: }
! 84: return c-'a';
! 85: }
! 86:
! 87: /*
! 88: **------------monomial defs-----------------------------------------------
! 89: ** monomials are represented by their exponent vectors:
! 90: ** C integer vectors indexed from 0 to ring_dim-1
! 91: **
! 92: */
! 93:
! 94: /*
! 95: ** void print_monomial(FILE *,int *):
! 96: ** print exponent vector as monomial
! 97: **
! 98: */
! 99: void print_monomial(FILE *of, int *exps){
! 100: int i,jk=0;
! 101: if (NT == 1) {
! 102: fprintf(of,"[");
! 103: for (i=0; i<ring_N; i++) {
! 104: fprintf(of,"%d",exps[i]);
! 105: if (i != ring_N-1) fprintf(of," , ");
! 106: }
! 107: fprintf(of,"]");
! 108: }else{
! 109: for(i=0;i<ring_N;i++){
! 110: if (exps[i]!=0){
! 111: if (jk!=0) fprintf(of,"*");
! 112: else jk=1;
! 113: ring_putvar(of,i);
! 114: if (exps[i]>1) fprintf(of,"^%d",exps[i]);
! 115: }
! 116: }
! 117: }
! 118: }
! 119:
! 120: /*
! 121: ** void get_monomial(FILE *,int *):
! 122: ** Read ascii representation of monomial as power product -- convert
! 123: ** to exponent vector stored in *exps.
! 124: **
! 125: */
! 126: void get_monomial(FILE *is,int *exps){
! 127: char c='*';
! 128: int v,e;
! 129:
! 130: for(v=0;v<ring_N;v++)exps[v]=0;
! 131: while(c=='*'){
! 132: eatwhite(is);
! 133: v=ring_getvar(is);
! 134: eatwhite(is);
! 135: c=fgetc(is);
! 136: if (c=='^'){
! 137: fscanf(is,"%d",&e);
! 138: c=fgetc(is);
! 139: }
! 140: else {
! 141: e=1;
! 142: }
! 143: exps[v]=e;
! 144: }
! 145: ungetc(c,is);
! 146: }
! 147:
! 148: /*
! 149: ** int monomial_divides(monomial m1, monomial m2):
! 150: ** return TRUE if m1 divides m2
! 151: **
! 152: */
! 153: int monomial_divides(monomial m1, monomial m2){
! 154: int i;
! 155: for(i=0;i<ring_N;i++)if (m1[i]>m2[i]) return FALSE;
! 156: return TRUE;
! 157: }
! 158:
! 159: /*
! 160: ** int monomial_rel_prime(monomial m1, monomial m2):
! 161: ** return TRUE if m1 is reletively prime to m2.
! 162: **
! 163: */
! 164: int monomial_rel_prime(monomial m1, monomial m2){
! 165: int i;
! 166: for(i=0;i<ring_N;i++) if (m1[i]!=0 && m2[i]!=0) return FALSE;
! 167: return TRUE;
! 168: }
! 169:
! 170: /*
! 171: ** int monomial_equal(monomial m1, monomial m2):
! 172: ** return TRUE if monomials m1 and m2 have same exponents
! 173: **
! 174: */
! 175: int monomial_equal(monomial m1, monomial m2){
! 176: int i;
! 177: for(i=0;i<ring_N;i++) if (m1[i]-m2[i]!=0) return FALSE;
! 178: return TRUE;
! 179: }
! 180:
! 181: /*
! 182: **int monomial_lcm(monomial m1, monomial m2, monomial m3):
! 183: ** copy least common multiple of m1 and m2 into m3.
! 184: **
! 185: */
! 186: int monomial_lcm(monomial m1, monomial m2, monomial m3){
! 187: int i;
! 188: for(i=0;i<ring_N;i++){
! 189: if (m1[i]>=m2[i]) m3[i]=m1[i];
! 190: else m3[i]=m2[i];
! 191: }
! 192: }
! 193:
! 194: /*
! 195: **
! 196: **
! 197: */
! 198: int monomial_stddegree(monomial m){
! 199: int i,d=0;
! 200: for(i=0;i<ring_N;i++) d+=m[i];
! 201: return d;
! 202: }
! 203:
! 204:
! 205: /*
! 206: ** int monomial_lexcomp(monomial m1, monomial m2):
! 207: ** return >0 if m1 is lexicographically greater then m2
! 208: **
! 209: */
! 210: int monomial_lexcomp(monomial m1, monomial m2){
! 211: int i,jk;
! 212: for(i=0;i<ring_N;i++) if ((jk=m1[i]-m2[i])!=0) break;
! 213: return jk;
! 214: }
! 215:
! 216: /*
! 217: ** int monomial_rlexcomp(monomial m1, monomial m2):
! 218: ** return >0 if m1 is degree reverse lexicographically greater than m2
! 219: ** with variables taken in order a>b...., except that variable ring_lv is
! 220: ** taken last (if it is >=0).
! 221: **
! 222: */
! 223: int monomial_rlexcomp(monomial m1, monomial m2){
! 224: int i,jk,d=0;
! 225: /* compute diference of total degrees */
! 226: for(i=0;i<ring_N;i++) d+=ring_weight[i]*(m1[i]-m2[i]);
! 227: if (d!=0) return d;
! 228: /* test ring_lv entree first */
! 229: if (ring_lv>=0 && ((jk=m1[ring_lv]-m2[ring_lv])!=0)) return -1*jk;
! 230: /* now test entrees in reverse order */
! 231: for(i=ring_N-1;i>=0;i--) if ((jk=m1[i]-m2[i])!=0) return -1*jk;
! 232: return 0;
! 233: }
! 234:
! 235: /*
! 236: **----------binomial defs------------------------------------------------
! 237: **
! 238: **
! 239: */
! 240:
! 241: /*
! 242: ** binomial binomial_new(): allocate storage for a new binomial--
! 243: ** initialize flags and set exponents to zero;
! 244: */
! 245: binomial binomial_new(){
! 246: binomial m;
! 247: int i,*E=0,*E2=0;
! 248:
! 249: if ((m=(binomial)malloc(sizeof(struct bin_tag)))==0){
! 250: fprintf(stderr,"binomial_new(): first malloc failed\n");
! 251: return 0;
! 252: }
! 253: if ((m->E=(int *)malloc(2*ring_N*sizeof(int)))==0){
! 254: fprintf(stderr,"binomial_new(): seccond malloc failed\n");
! 255: free((void*)m);
! 256: return 0;
! 257: }
! 258: m->exps1=m->E;
! 259: m->exps2=m->E+ring_N;
! 260: m->ff=UNKNOWN;
! 261: m->bf=BINOMIAL;
! 262: m->next=0;
! 263: for(i=0;i<ring_N;i++) { m->exps1[i]=(m->exps2[i]=0);}
! 264: return m;
! 265: }
! 266:
! 267:
! 268: /*
! 269: ** void binomial_free(binomial m):
! 270: ** reclaim space allocated by binomial_new()
! 271: **
! 272: */
! 273: void binomial_free(binomial m){
! 274: if (m->E!=0)free((void *)(m->E));
! 275: free((void *)m);
! 276: }
! 277:
! 278: /*
! 279: ** void binomial_read(FILE *is, binomial b):
! 280: ** read data into binomial
! 281: **
! 282: */
! 283: void binomial_read(FILE *is, binomial b){
! 284: char c, d='-';
! 285: eatwhite(is);
! 286: c=getc(is);
! 287: /* read in status of facet flag if present*/
! 288: if (c=='#') b->ff=FACET;
! 289: else if (c=='!') b->ff=NONFACET;
! 290: else if (c=='?') b->ff=UNKNOWN;
! 291: else ungetc(c,is);
! 292:
! 293: /* read in leading and trailing monomials if present*/
! 294: eatwhite(is);
! 295: if ((c=getc(is))=='-') d='+';
! 296: else ungetc(c,is);
! 297: get_monomial(is,b->exps1);
! 298: eatwhite(is);
! 299: if ((c=getc(is))==d){
! 300: get_monomial(is,b->exps2);
! 301: b->bf=BINOMIAL;
! 302: }else{
! 303: b->bf=MONOMIAL;
! 304: ungetc(c,is);
! 305: }
! 306: if (d=='+'){
! 307: if (b->bf==MONOMIAL){
! 308: fprintf(stderr,"WARNING: binomial_read() monomial with negative coef\n");
! 309: }
! 310: binomial_flip(b);
! 311: }
! 312: }
! 313:
! 314:
! 315: /*
! 316: ** void binomial_print(FILE *,binomial):
! 317: ** print binomial
! 318: **
! 319: */
! 320: void binomial_print(FILE *of, binomial b){
! 321: if (NT == 1) {
! 322: if (b==0) fprintf(of,"[ ]");
! 323: else {
! 324: /* if (b->ff==FACET) fprintf(of,"# ");
! 325: else if (b->ff==NONFACET) fprintf(of,"! "); */
! 326: /*else if (b->ff==UNKNOWN) fprintf(of,"? ");*/
! 327: fprintf(of,"[");
! 328: print_monomial(of,b->exps1);
! 329: if (b->bf==BINOMIAL){
! 330: fprintf(of," , ");
! 331: print_monomial(of,b->exps2);
! 332: fprintf(of,"]");
! 333: }
! 334: }
! 335: }else{
! 336: if (b==0) fprintf(of,"(NULL)");
! 337: else {
! 338: if (b->ff==FACET) fprintf(of,"# ");
! 339: else if (b->ff==NONFACET) fprintf(of,"! ");
! 340: /*else if (b->ff==UNKNOWN) fprintf(of,"? ");*/
! 341: print_monomial(of,b->exps1);
! 342: if (b->bf==BINOMIAL){
! 343: fprintf(of,"-");
! 344: print_monomial(of,b->exps2);
! 345: }
! 346: }
! 347: }
! 348: }
! 349:
! 350: /*
! 351: ** void binomial_copy(binomial src,binomial dest):
! 352: ** copy source binomials exponents and flags to those of dest binomial
! 353: **
! 354: */
! 355: void binomial_copy(binomial src,binomial dest){
! 356: int i;
! 357:
! 358: for(i=0;i<ring_N;i++){
! 359: binomial_lead(dest)[i]=binomial_lead(src)[i];
! 360: binomial_trail(dest)[i]=binomial_trail(src)[i];
! 361: }
! 362: binomial_next(dest)=0;
! 363: dest->bf=src->bf;
! 364: }
! 365:
! 366: /*
! 367: ** void binomial_flip(binomial b):
! 368: ** interchange leading and trailing terms of binomial
! 369: **
! 370: */
! 371: void binomial_flip(binomial b){
! 372: int *tmp;
! 373: tmp=binomial_lead(b);
! 374: binomial_lead(b)=binomial_trail(b);
! 375: binomial_trail(b)=tmp;
! 376: }
! 377:
! 378: /*
! 379: ** binomial monomial_spair(binomial b,monomial m):
! 380: ** form spair between marked binomial and marked monomial
! 381: ** and reduce result by binomial as many times as possible
! 382: **
! 383: */
! 384: binomial monomial_spair(binomial b,monomial m){
! 385: binomial S = 0;
! 386: int i,tmp;
! 387:
! 388: S=binomial_new();
! 389:
! 390: /* form monomial spair i.e. trailing term times factor required to */
! 391: /* bump lead term up to monomial -- also set trail terms to zero */
! 392: for(i=0;i<ring_N;i++){
! 393: (binomial_lead(S))[i]=(binomial_trail(b))[i];
! 394: (binomial_trail(S))[i]=0;
! 395: if ((tmp=(m[i]-(binomial_lead(b))[i]))>0)((binomial_lead(S))[i])+=tmp;
! 396: }
! 397:
! 398: /*reduce S by b as many times as possible*/
! 399: while(monomial_divides(binomial_lead(b),binomial_lead(S))==TRUE){
! 400: for(i=0;i<ring_N;i++){
! 401: tmp=(binomial_lead(S))[i]-(binomial_lead(b))[i];
! 402: (binomial_lead(S))[i]=(binomial_trail(b))[i]+tmp;
! 403: }
! 404:
! 405: }
! 406: return S;
! 407: }
! 408:
! 409: /*
! 410: ** int binomial_spair(binomial b1, binomial b2):
! 411: ** replace b1, by spair of b1 and b2 -- the spair is taken with respect
! 412: ** to the markings of b1 and b2, but it's marking is not meaningfull.
! 413: ** returns TRUE if result is equivalent to zero monomial.
! 414: **
! 415: */
! 416: int binomial_spair(binomial b1, binomial b2){
! 417: int i,jk,jk2=TRUE;
! 418: for(i=0;i<ring_N;i++){
! 419: jk=binomial_lead(b1)[i]-binomial_lead(b2)[i];
! 420: if (binomial_lead(b1)[i]!=0 && binomial_lead(b2)!=0) jk2=FALSE;
! 421: binomial_lead(b1)[i]=binomial_trail(b2)[i];
! 422: if (jk>0) binomial_lead(b1)[i]+=jk;
! 423: else binomial_trail(b1)[i]-=jk;
! 424: }
! 425: jk=monomial_equal(binomial_lead(b1),binomial_trail(b1));
! 426: if (jk==TRUE || jk2==TRUE) return TRUE;
! 427: else return FALSE;
! 428: }
! 429:
! 430:
! 431: /*
! 432: **void binomial_bumpto(binomial b1, binomial b2):
! 433: ** assuming that the leading term of b1 divides that of b2
! 434: ** multiply both sides of b1 so that the leading terms of b1
! 435: ** and b2 are equal
! 436: **
! 437: */
! 438: void binomial_bumpto(binomial b1, binomial b2){
! 439: int i,tmp;
! 440: for(i=0;i<ring_N;i++){
! 441: tmp=(binomial_lead(b2))[i]-(binomial_lead(b1))[i];
! 442: (binomial_lead(b1))[i]+=tmp;
! 443: (binomial_trail(b1))[i]+=tmp;
! 444: }
! 445: }
! 446:
! 447: /*
! 448: ** void reducetrail(binomial b1, binomial b2):
! 449: ** assuming that lead(b2) divides trail(b1) change b1 into binomial
! 450: ** resulting from bumping b2 so that lead(b2)=trail(b1) and adding
! 451: ** result to b1.
! 452: **
! 453: */
! 454: void reducetrail(binomial b1, binomial b2){
! 455: int i;
! 456: for( i=0;i<ring_N;i++){
! 457: binomial_trail(b1)[i]+=binomial_trail(b2)[i]-binomial_lead(b2)[i];
! 458: }
! 459: }
! 460:
! 461: /*
! 462: ** int binomial_compair(binomial b1,binomial b2):
! 463: ** return TRUE if the lead term of b1 is lexicographically greater than
! 464: ** that of b2 or if they tie return true if the trail term b1 is greater
! 465: ** or equal to that of b2 otherwise return false
! 466: */
! 467: int binomial_compair(binomial b1,binomial b2){
! 468: int tmp;
! 469:
! 470: tmp=monomial_lexcomp(binomial_lead(b1),binomial_lead(b2));
! 471: if (tmp>0) return TRUE;
! 472: else if (tmp<0) return FALSE;
! 473: else {
! 474: tmp=monomial_lexcomp(binomial_trail(b1),binomial_trail(b2));
! 475: if (tmp>=0) return TRUE;
! 476: else return FALSE;
! 477: }
! 478: }
! 479:
! 480:
! 481:
! 482:
! 483:
! 484:
! 485:
! 486:
! 487:
! 488:
! 489:
! 490:
! 491:
! 492:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>