[BACK]Return to binomial.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / TiGERS_0.9

Annotation of OpenXM_contrib/TiGERS_0.9/binomial.c, Revision 1.1.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>