Annotation of OpenXM_contrib/TiGERS_0.9/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:
! 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: for(i=0;i<ring_N;i++){
! 102: if (exps[i]!=0){
! 103: if (jk!=0) fprintf(of,"*");
! 104: else jk=1;
! 105: ring_putvar(of,i);
! 106: if (exps[i]>1) fprintf(of,"^%d",exps[i]);
! 107: }
! 108: }
! 109: }
! 110:
! 111: /*
! 112: ** void get_monomial(FILE *,int *):
! 113: ** Read ascii representation of monomial as power product -- convert
! 114: ** to exponent vector stored in *exps.
! 115: **
! 116: */
! 117: void get_monomial(FILE *is,int *exps){
! 118: char c='*';
! 119: int v,e;
! 120:
! 121: for(v=0;v<ring_N;v++)exps[v]=0;
! 122: while(c=='*'){
! 123: eatwhite(is);
! 124: v=ring_getvar(is);
! 125: eatwhite(is);
! 126: c=fgetc(is);
! 127: if (c=='^'){
! 128: fscanf(is,"%d",&e);
! 129: c=fgetc(is);
! 130: }
! 131: else {
! 132: e=1;
! 133: }
! 134: exps[v]=e;
! 135: }
! 136: ungetc(c,is);
! 137: }
! 138:
! 139: /*
! 140: ** int monomial_divides(monomial m1, monomial m2):
! 141: ** return TRUE if m1 divides m2
! 142: **
! 143: */
! 144: int monomial_divides(monomial m1, monomial m2){
! 145: int i;
! 146: for(i=0;i<ring_N;i++)if (m1[i]>m2[i]) return FALSE;
! 147: return TRUE;
! 148: }
! 149:
! 150: /*
! 151: ** int monomial_rel_prime(monomial m1, monomial m2):
! 152: ** return TRUE if m1 is reletively prime to m2.
! 153: **
! 154: */
! 155: int monomial_rel_prime(monomial m1, monomial m2){
! 156: int i;
! 157: for(i=0;i<ring_N;i++) if (m1[i]!=0 && m2[i]!=0) return FALSE;
! 158: return TRUE;
! 159: }
! 160:
! 161: /*
! 162: ** int monomial_equal(monomial m1, monomial m2):
! 163: ** return TRUE if monomials m1 and m2 have same exponents
! 164: **
! 165: */
! 166: int monomial_equal(monomial m1, monomial m2){
! 167: int i;
! 168: for(i=0;i<ring_N;i++) if (m1[i]-m2[i]!=0) return FALSE;
! 169: return TRUE;
! 170: }
! 171:
! 172: /*
! 173: **int monomial_lcm(monomial m1, monomial m2, monomial m3):
! 174: ** copy least common multiple of m1 and m2 into m3.
! 175: **
! 176: */
! 177: int monomial_lcm(monomial m1, monomial m2, monomial m3){
! 178: int i;
! 179: for(i=0;i<ring_N;i++){
! 180: if (m1[i]>=m2[i]) m3[i]=m1[i];
! 181: else m3[i]=m2[i];
! 182: }
! 183: }
! 184:
! 185: /*
! 186: **
! 187: **
! 188: */
! 189: int monomial_stddegree(monomial m){
! 190: int i,d=0;
! 191: for(i=0;i<ring_N;i++) d+=m[i];
! 192: return d;
! 193: }
! 194:
! 195:
! 196: /*
! 197: ** int monomial_lexcomp(monomial m1, monomial m2):
! 198: ** return >0 if m1 is lexicographically greater then m2
! 199: **
! 200: */
! 201: int monomial_lexcomp(monomial m1, monomial m2){
! 202: int i,jk;
! 203: for(i=0;i<ring_N;i++) if ((jk=m1[i]-m2[i])!=0) break;
! 204: return jk;
! 205: }
! 206:
! 207: /*
! 208: ** int monomial_rlexcomp(monomial m1, monomial m2):
! 209: ** return >0 if m1 is degree reverse lexicographically greater than m2
! 210: ** with variables taken in order a>b...., except that variable ring_lv is
! 211: ** taken last (if it is >=0).
! 212: **
! 213: */
! 214: int monomial_rlexcomp(monomial m1, monomial m2){
! 215: int i,jk,d=0;
! 216: /* compute diference of total degrees */
! 217: for(i=0;i<ring_N;i++) d+=ring_weight[i]*(m1[i]-m2[i]);
! 218: if (d!=0) return d;
! 219: /* test ring_lv entree first */
! 220: if (ring_lv>=0 && ((jk=m1[ring_lv]-m2[ring_lv])!=0)) return -1*jk;
! 221: /* now test entrees in reverse order */
! 222: for(i=ring_N-1;i>=0;i--) if ((jk=m1[i]-m2[i])!=0) return -1*jk;
! 223: return 0;
! 224: }
! 225:
! 226: /*
! 227: **----------binomial defs------------------------------------------------
! 228: **
! 229: **
! 230: */
! 231:
! 232: /*
! 233: ** binomial binomial_new(): allocate storage for a new binomial--
! 234: ** initialize flags and set exponents to zero;
! 235: */
! 236: binomial binomial_new(){
! 237: binomial m;
! 238: int i,*E=0,*E2=0;
! 239:
! 240: if ((m=(binomial)malloc(sizeof(struct bin_tag)))==0){
! 241: fprintf(stderr,"binomial_new(): first malloc failed\n");
! 242: return 0;
! 243: }
! 244: if ((m->E=(int *)malloc(2*ring_N*sizeof(int)))==0){
! 245: fprintf(stderr,"binomial_new(): seccond malloc failed\n");
! 246: free((void*)m);
! 247: return 0;
! 248: }
! 249: m->exps1=m->E;
! 250: m->exps2=m->E+ring_N;
! 251: m->ff=UNKNOWN;
! 252: m->bf=BINOMIAL;
! 253: m->next=0;
! 254: for(i=0;i<ring_N;i++) { m->exps1[i]=(m->exps2[i]=0);}
! 255: return m;
! 256: }
! 257:
! 258:
! 259: /*
! 260: ** void binomial_free(binomial m):
! 261: ** reclaim space allocated by binomial_new()
! 262: **
! 263: */
! 264: void binomial_free(binomial m){
! 265: if (m->E!=0)free((void *)(m->E));
! 266: free((void *)m);
! 267: }
! 268:
! 269: /*
! 270: ** void binomial_read(FILE *is, binomial b):
! 271: ** read data into binomial
! 272: **
! 273: */
! 274: void binomial_read(FILE *is, binomial b){
! 275: char c, d='-';
! 276: eatwhite(is);
! 277: c=getc(is);
! 278: /* read in status of facet flag if present*/
! 279: if (c=='#') b->ff=FACET;
! 280: else if (c=='!') b->ff=NONFACET;
! 281: else if (c=='?') b->ff=UNKNOWN;
! 282: else ungetc(c,is);
! 283:
! 284: /* read in leading and trailing monomials if present*/
! 285: eatwhite(is);
! 286: if ((c=getc(is))=='-') d='+';
! 287: else ungetc(c,is);
! 288: get_monomial(is,b->exps1);
! 289: eatwhite(is);
! 290: if ((c=getc(is))==d){
! 291: get_monomial(is,b->exps2);
! 292: b->bf=BINOMIAL;
! 293: }else{
! 294: b->bf=MONOMIAL;
! 295: ungetc(c,is);
! 296: }
! 297: if (d=='+'){
! 298: if (b->bf==MONOMIAL){
! 299: fprintf(stderr,"WARNING: binomial_read() monomial with negative coef\n");
! 300: }
! 301: binomial_flip(b);
! 302: }
! 303: }
! 304:
! 305:
! 306: /*
! 307: ** void binomial_print(FILE *,binomial):
! 308: ** print binomial
! 309: **
! 310: */
! 311: void binomial_print(FILE *of, binomial b){
! 312: if (b==0) fprintf(of,"(NULL)");
! 313: else {
! 314: if (b->ff==FACET) fprintf(of,"# ");
! 315: else if (b->ff==NONFACET) fprintf(of,"! ");
! 316: /*else if (b->ff==UNKNOWN) fprintf(of,"? ");*/
! 317: print_monomial(of,b->exps1);
! 318: if (b->bf==BINOMIAL){
! 319: fprintf(of,"-");
! 320: print_monomial(of,b->exps2);
! 321: }
! 322: }
! 323: }
! 324:
! 325: /*
! 326: ** void binomial_copy(binomial src,binomial dest):
! 327: ** copy source binomials exponents and flags to those of dest binomial
! 328: **
! 329: */
! 330: void binomial_copy(binomial src,binomial dest){
! 331: int i;
! 332:
! 333: for(i=0;i<ring_N;i++){
! 334: binomial_lead(dest)[i]=binomial_lead(src)[i];
! 335: binomial_trail(dest)[i]=binomial_trail(src)[i];
! 336: }
! 337: binomial_next(dest)=0;
! 338: dest->bf=src->bf;
! 339: }
! 340:
! 341: /*
! 342: ** void binomial_flip(binomial b):
! 343: ** interchange leading and trailing terms of binomial
! 344: **
! 345: */
! 346: void binomial_flip(binomial b){
! 347: int *tmp;
! 348: tmp=binomial_lead(b);
! 349: binomial_lead(b)=binomial_trail(b);
! 350: binomial_trail(b)=tmp;
! 351: }
! 352:
! 353: /*
! 354: ** binomial monomial_spair(binomial b,monomial m):
! 355: ** form spair between marked binomial and marked monomial
! 356: ** and reduce result by binomial as many times as possible
! 357: **
! 358: */
! 359: binomial monomial_spair(binomial b,monomial m){
! 360: binomial S = 0;
! 361: int i,tmp;
! 362:
! 363: S=binomial_new();
! 364:
! 365: /* form monomial spair i.e. trailing term times factor required to */
! 366: /* bump lead term up to monomial -- also set trail terms to zero */
! 367: for(i=0;i<ring_N;i++){
! 368: (binomial_lead(S))[i]=(binomial_trail(b))[i];
! 369: (binomial_trail(S))[i]=0;
! 370: if ((tmp=(m[i]-(binomial_lead(b))[i]))>0)((binomial_lead(S))[i])+=tmp;
! 371: }
! 372:
! 373: /*reduce S by b as many times as possible*/
! 374: while(monomial_divides(binomial_lead(b),binomial_lead(S))==TRUE){
! 375: for(i=0;i<ring_N;i++){
! 376: tmp=(binomial_lead(S))[i]-(binomial_lead(b))[i];
! 377: (binomial_lead(S))[i]=(binomial_trail(b))[i]+tmp;
! 378: }
! 379:
! 380: }
! 381: return S;
! 382: }
! 383:
! 384: /*
! 385: ** int binomial_spair(binomial b1, binomial b2):
! 386: ** replace b1, by spair of b1 and b2 -- the spair is taken with respect
! 387: ** to the markings of b1 and b2, but it's marking is not meaningfull.
! 388: ** returns TRUE if result is equivalent to zero monomial.
! 389: **
! 390: */
! 391: int binomial_spair(binomial b1, binomial b2){
! 392: int i,jk,jk2=TRUE;
! 393: for(i=0;i<ring_N;i++){
! 394: jk=binomial_lead(b1)[i]-binomial_lead(b2)[i];
! 395: if (binomial_lead(b1)[i]!=0 && binomial_lead(b2)!=0) jk2=FALSE;
! 396: binomial_lead(b1)[i]=binomial_trail(b2)[i];
! 397: if (jk>0) binomial_lead(b1)[i]+=jk;
! 398: else binomial_trail(b1)[i]-=jk;
! 399: }
! 400: jk=monomial_equal(binomial_lead(b1),binomial_trail(b1));
! 401: if (jk==TRUE || jk2==TRUE) return TRUE;
! 402: else return FALSE;
! 403: }
! 404:
! 405:
! 406: /*
! 407: **void binomial_bumpto(binomial b1, binomial b2):
! 408: ** assuming that the leading term of b1 divides that of b2
! 409: ** multiply both sides of b1 so that the leading terms of b1
! 410: ** and b2 are equal
! 411: **
! 412: */
! 413: void binomial_bumpto(binomial b1, binomial b2){
! 414: int i,tmp;
! 415: for(i=0;i<ring_N;i++){
! 416: tmp=(binomial_lead(b2))[i]-(binomial_lead(b1))[i];
! 417: (binomial_lead(b1))[i]+=tmp;
! 418: (binomial_trail(b1))[i]+=tmp;
! 419: }
! 420: }
! 421:
! 422: /*
! 423: ** void reducetrail(binomial b1, binomial b2):
! 424: ** assuming that lead(b2) divides trail(b1) change b1 into binomial
! 425: ** resulting from bumping b2 so that lead(b2)=trail(b1) and adding
! 426: ** result to b1.
! 427: **
! 428: */
! 429: void reducetrail(binomial b1, binomial b2){
! 430: int i;
! 431: for( i=0;i<ring_N;i++){
! 432: binomial_trail(b1)[i]+=binomial_trail(b2)[i]-binomial_lead(b2)[i];
! 433: }
! 434: }
! 435:
! 436: /*
! 437: ** int binomial_compair(binomial b1,binomial b2):
! 438: ** return TRUE if the lead term of b1 is lexicographically greater than
! 439: ** that of b2 or if they tie return true if the trail term b1 is greater
! 440: ** or equal to that of b2 otherwise return false
! 441: */
! 442: int binomial_compair(binomial b1,binomial b2){
! 443: int tmp;
! 444:
! 445: tmp=monomial_lexcomp(binomial_lead(b1),binomial_lead(b2));
! 446: if (tmp>0) return TRUE;
! 447: else if (tmp<0) return FALSE;
! 448: else {
! 449: tmp=monomial_lexcomp(binomial_trail(b1),binomial_trail(b2));
! 450: if (tmp>=0) return TRUE;
! 451: else return FALSE;
! 452: }
! 453: }
! 454:
! 455:
! 456:
! 457:
! 458:
! 459:
! 460:
! 461:
! 462:
! 463:
! 464:
! 465:
! 466:
! 467:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>