polylib: vector.c Source File

- Main Page
- Classes
- Files

- File List
- File Members

# vector.c

Go to the documentation of this file.

    00001 /*
    00002     This file is part of PolyLib.
    00003
    00004     PolyLib is free software: you can redistribute it and/or modify
    00005     it under the terms of the GNU General Public License as published by
    00006     the Free Software Foundation, either version 3 of the License, or
    00007     (at your option) any later version.
    00008
    00009     PolyLib is distributed in the hope that it will be useful,
    00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    00012     GNU General Public License for more details.
    00013
    00014     You should have received a copy of the GNU General Public License
    00015     along with PolyLib.  If not, see <http://www.gnu.org/licenses/>.
    00016 */
    00017
    00018 /* vector.c
    00019           COPYRIGHT
    00020           Both this software and its documentation are
    00021
    00022               Copyrighted 1993 by IRISA /Universite de Rennes I - France,
    00023               Copyright 1995,1996 by BYU, Provo, Utah
    00024                          all rights reserved.
    00025
    00026           Permission is granted to copy, use, and distribute
    00027           for any commercial or noncommercial purpose under the terms
    00028           of the GNU General Public license, version 2, June 1991
    00029           (see file : LICENSING).
    00030 */
    00031
    00032 #include <stdio.h>
    00033 #include <stdlib.h>
    00034 #include <polylib/polylib.h>
    00035
    00036 #ifdef MAC_OS
    00037   #define abs __abs
    00038 #endif
    00039
    00040 /*
    00041  * Compute n!
    00042  */
    00043 void Factorial(int n, Value *fact) {
    00044
    00045   int i;
    00046   Value tmp;
    00047
    00048   value_init(tmp);
    00049
    00050   value_set_si(*fact,1);
    00051   for (i=1;i<=n;i++) {
    00052     value_set_si(tmp,i);
    00053     value_multiply(*fact,*fact,tmp);
    00054   }
    00055   value_clear(tmp);
    00056 } /* Factorial */
    00057
    00058 /*
    00059  * Compute n!/(p!(n-p)!)
    00060  */
    00061 void Binomial(int n, int p, Value *result) {
    00062
    00063   int i;
    00064   Value tmp;
    00065   Value f;
    00066
    00067   value_init(tmp);value_init(f);
    00068
    00069   if (n-p<p)
    00070     p=n-p;
    00071   if (p!=0) {
    00072     value_set_si(*result,(n-p+1));
    00073     for (i=n-p+2;i<=n;i++) {
    00074       value_set_si(tmp,i);
    00075       value_multiply(*result,*result,tmp);
    00076     }
    00077     Factorial(p,&f);
    00078     value_division(*result,*result,f);
    00079   }
    00080   else
    00081     value_set_si(*result,1);
    00082   value_clear(f);value_clear(tmp);
    00083 } /* Binomial */
    00084
    00085 /*
    00086  * Return the number of ways to choose 'b' items from 'a' items, that is,
    00087  * return a!/(b!(a-b)!)
    00088  */
    00089 void CNP(int a,int b, Value *result) {
    00090
    00091   int i;
    00092   Value tmp;
    00093   value_init(tmp);
    00094
    00095   value_set_si(*result,1);
    00096
    00097   /* If number of items is less than the number to be choosen, return 1 */
    00098   if(a <= b) {
    00099     value_clear(tmp);
    00100     return;
    00101   }
    00102   for(i=a;i>b;--i) {
    00103     value_set_si(tmp,i);
    00104     value_multiply(*result,*result,tmp);
    00105   }
    00106   for(i=1;i<=(a-b);++i) {
    00107     value_set_si(tmp,i);
    00108     value_division(*result,*result,tmp);
    00109   }
    00110   value_clear(tmp);
    00111 } /* CNP */
    00112
    00113 /*
    00114  * Compute GCD of 'a' and 'b'
    00115  */
    00116 void Gcd(Value a,Value b,Value *result) {
    00117
    00118   Value acopy, bcopy;
    00119
    00120   value_init(acopy);
    00121   value_init(bcopy);
    00122   value_assign(acopy,a);
    00123   value_assign(bcopy,b);
    00124   while(value_notzero_p(acopy)) {
    00125     value_modulus(*result,bcopy,acopy);
    00126     value_assign(bcopy,acopy);
    00127     value_assign(acopy,*result);
    00128   }
    00129   value_absolute(*result,bcopy);
    00130   value_clear(acopy);
    00131   value_clear(bcopy);
    00132 } /* Gcd */
    00133
    00134 /*
    00135  * Return the smallest component index in 'p' whose value is non-zero
    00136  */
    00137 int First_Non_Zero(Value *p,unsigned length) {
    00138
    00139   Value *cp;
    00140   int i;
    00141
    00142   cp = p;
    00143   for (i=0;i<length;i++) {
    00144     if (value_notzero_p(*cp))
    00145       break;
    00146     cp++;
    00147   }
    00148   return((i==length) ? -1 : i );
    00149 } /* First_Non_Zero */
    00150
    00151 /*
    00152  * Allocate memory space for Vector
    00153  */
    00154 Vector *Vector_Alloc(unsigned length) {
    00155
    00156   int i;
    00157   Vector *vector;
    00158
    00159   vector = (Vector *)malloc(sizeof(Vector));
    00160   if (!vector) {
    00161     errormsg1("Vector_Alloc", "outofmem", "out of memory space");
    00162     return 0;
    00163   }
    00164   vector->Size=length;
    00165   vector->p=(Value *)malloc(length * sizeof(Value));
    00166   if (!vector->p) {
    00167     errormsg1("Vector_Alloc", "outofmem", "out of memory space");
    00168     free(vector);
    00169     return 0;
    00170   }
    00171   for(i=0;i<length;i++)
    00172     value_init(vector->p[i]);
    00173   return vector;
    00174 } /* Vector_Alloc */
    00175
    00176 /*
    00177  * Free the memory space occupied by Vector
    00178  */
    00179 void Vector_Free(Vector *vector) {
    00180
    00181   int i;
    00182
    00183   if (!vector) return;
    00184   for(i=0;i<vector->Size;i++)
    00185     value_clear(vector->p[i]);
    00186   free(vector->p);
    00187   free(vector);
    00188 } /* Vector_Free */
    00189
    00190 /*
    00191  * Print the contents of a Vector
    00192  */
    00193 void Vector_Print(FILE *Dst, const char *Format, Vector *vector)
    00194 {
    00195   int i;
    00196   Value *p;
    00197   unsigned length;
    00198
    00199   fprintf(Dst, "%d\n", length=vector->Size);
    00200   p = vector->p;
    00201   for (i=0;i<length;i++) {
    00202     if (Format) {
    00203       value_print(Dst,Format,*p++);
    00204     }
    00205     else {
    00206       value_print(Dst,P_VALUE_FMT,*p++);
    00207     }
    00208   }
    00209   fprintf(Dst, "\n");
    00210 } /* Vector_Print */
    00211
    00212 /*
    00213  * Read the contents of a Vector
    00214  */
    00215 Vector *Vector_Read() {
    00216
    00217   Vector *vector;
    00218   unsigned length;
    00219   int i;
    00220   char str[1024];
    00221   Value *p;
    00222
    00223   scanf("%d", &length);
    00224   vector = Vector_Alloc(length);
    00225   if (!vector) {
    00226     errormsg1("Vector_Read", "outofmem", "out of memory space");
    00227     return 0;
    00228   }
    00229   p = vector->p;
    00230   for (i=0;i<length;i++) {
    00231     scanf("%s",str);
    00232     value_read(*(p++),str);
    00233   }
    00234   return vector;
    00235 } /* Vector_Read */
    00236
    00237 /*
    00238  * Assign 'n' to each component of Vector 'p'
    00239  */
    00240 void Vector_Set(Value *p,int n,unsigned length) {
    00241
    00242   Value *cp;
    00243   int i;
    00244
    00245   cp = p;
    00246   for (i=0;i<length;i++) {
    00247     value_set_si(*cp,n);
    00248     cp++;
    00249   }
    00250   return;
    00251 } /* Vector_Set */
    00252
    00253 /*
    00254  * Exchange the components of the vectors 'p1' and 'p2' of length 'length'
    00255  */
    00256 void Vector_Exchange(Value *p1, Value *p2, unsigned length) {
    00257
    00258   int i;
    00259
    00260   for(i=0;i<length;i++) {
    00261     value_swap(p1[i],p2[i]);
    00262   }
    00263   return;
    00264 }
    00265
    00266 /*
    00267  * Copy Vector 'p1' to Vector 'p2'
    00268  */
    00269 void Vector_Copy(Value *p1,Value *p2,unsigned length) {
    00270
    00271   int i;
    00272   Value *cp1, *cp2;
    00273
    00274   cp1 = p1;
    00275   cp2 = p2;
    00276
    00277   for(i=0;i<length;i++)
    00278     value_assign(*cp2++,*cp1++);
    00279
    00280   return;
    00281 }
    00282
    00283 /*
    00284  * Add two vectors 'p1' and 'p2' and store the result in 'p3'
    00285  */
    00286 void Vector_Add(Value *p1,Value *p2,Value *p3,unsigned length) {
    00287
    00288   Value *cp1, *cp2, *cp3;
    00289   int i;
    00290
    00291   cp1=p1;
    00292   cp2=p2;
    00293   cp3=p3;
    00294   for (i=0;i<length;i++) {
    00295
    00296     /* *cp3++ = *cp1++ + *cp2++ */
    00297     value_addto(*cp3,*cp1,*cp2);
    00298     cp1++; cp2++; cp3++;
    00299   }
    00300 } /* Vector_Add */
    00301
    00302 /*
    00303  * Subtract two vectors 'p1' and 'p2' and store the result in 'p3'
    00304  */
    00305 void Vector_Sub(Value *p1,Value *p2,Value *p3,unsigned length) {
    00306
    00307   Value *cp1, *cp2, *cp3;
    00308   int i;
    00309
    00310   cp1=p1;
    00311   cp2=p2;
    00312   cp3=p3;
    00313   for (i=0;i<length;i++) {
    00314
    00315     /* *cp3++= *cp1++ - *cp2++ */
    00316     value_subtract(*cp3,*cp1,*cp2);
    00317     cp1++; cp2++; cp3++;
    00318   }
    00319 } /* Vector_Sub */
    00320
    00321 /*
    00322  * Compute Bitwise OR of Vectors 'p1' and 'p2' and store in 'p3'
    00323  */
    00324 void Vector_Or(Value *p1,Value *p2,Value *p3,unsigned length) {
    00325
    00326   Value *cp1, *cp2, *cp3;
    00327   int i;
    00328
    00329   cp1=p1;
    00330   cp2=p2;
    00331   cp3=p3;
    00332   for (i=0;i<length;i++) {
    00333
    00334     /* *cp3++=*cp1++ | *cp2++ */
    00335     value_orto(*cp3,*cp1,*cp2);
    00336     cp1++; cp2++; cp3++;
    00337   }
    00338 } /* Vector_Or */
    00339
    00340 /*
    00341  * Scale Vector 'p1' lambda times and store in 'p2'
    00342  */
    00343 void Vector_Scale(Value *p1,Value *p2,Value lambda,unsigned length) {
    00344
    00345   Value *cp1, *cp2;
    00346   int i;
    00347
    00348   cp1=p1;
    00349   cp2=p2;
    00350   for (i=0;i<length;i++) {
    00351
    00352     /* *cp2++=*cp1++ * lambda */
    00353     value_multiply(*cp2,*cp1,lambda);
    00354     cp1++; cp2++;
    00355   }
    00356 } /* Vector_Scale */
    00357
    00358 /*
    00359  * Antiscale Vector 'p1' by lambda and store in 'p2'
    00360  * Assumes all elements of 'p1' are divisble by lambda.
    00361  */
    00362 void Vector_AntiScale(Value *p1, Value *p2, Value lambda, unsigned length)
    00363 {
    00364   int i;
    00365
    00366   for (i = 0; i < length; i++)
    00367     value_divexact(p2[i], p1[i], lambda);
    00368 } /* Vector_AntiScale */
    00369
    00370 /*
    00371  * Puts negative of 'p1' in 'p2'
    00372  */
    00373 void Vector_Oppose(Value *p1, Value *p2, unsigned len)
    00374 {
    00375   unsigned i;
    00376
    00377   for (i = 0; i < len; ++i)
    00378     value_oppose(p2[i], p1[i]);
    00379 }
    00380
    00381 /*
    00382  * Return the inner product of the two Vectors 'p1' and 'p2'
    00383  */
    00384 void Inner_Product(Value *p1, Value *p2, unsigned length, Value *ip)
    00385 {
    00386   int i;
    00387
    00388   if (length != 0)
    00389     value_multiply(*ip, p1[0], p2[0]);
    00390   else
    00391     value_set_si(*ip, 0);
    00392   for(i = 1; i < length; i++)
    00393     value_addmul(*ip, p1[i], p2[i]);
    00394 } /* Inner_Product */
    00395
    00396 /*
    00397  * Return the maximum of the components of 'p'
    00398  */
    00399 void Vector_Max(Value *p,unsigned length, Value *max) {
    00400
    00401   Value *cp;
    00402   int i;
    00403
    00404   cp=p;
    00405   value_assign(*max,*cp);
    00406   cp++;
    00407   for (i=1;i<length;i++) {
    00408     value_maximum(*max,*max,*cp);
    00409     cp++;
    00410   }
    00411 } /* Vector_Max */
    00412
    00413 /*
    00414  * Return the minimum of the components of Vector 'p'
    00415  */
    00416 void Vector_Min(Value *p,unsigned length,Value *min) {
    00417
    00418   Value *cp;
    00419   int i;
    00420
    00421   cp=p;
    00422   value_assign(*min,*cp);
    00423   cp++;
    00424   for (i=1;i<length;i++) {
    00425     value_minimum(*min,*min,*cp);
    00426     cp++;
    00427   }
    00428   return;
    00429 } /* Vector_Min */
    00430
    00431 /*
    00432  * Given Vectors 'p1' and 'p2', return Vector 'p3' = lambda * p1 + mu * p2.
    00433  */
    00434 void Vector_Combine(Value *p1, Value *p2, Value *p3, Value lambda, Value mu,
    00435                     unsigned length)
    00436 {
    00437   Value tmp;
    00438   int i;
    00439
    00440   value_init(tmp);
    00441   for (i = 0; i < length; i++) {
    00442     value_multiply(tmp, lambda, p1[i]);
    00443     value_addmul(tmp, mu, p2[i]);
    00444     value_assign(p3[i], tmp);
    00445   }
    00446   value_clear(tmp);
    00447   return;
    00448 } /* Vector_Combine */
    00449
    00450 /*
    00451  * Return 1 if 'Vec1' equals 'Vec2', otherwise return 0
    00452  */
    00453 int Vector_Equal(Value *Vec1, Value *Vec2, unsigned n)
    00454 {
    00455   int i;
    00456
    00457   for (i = 0; i < n; ++i)
    00458     if (value_ne(Vec1[i], Vec2[i]))
    00459       return 0;
    00460
    00461   return 1;
    00462 } /* Vector_Equal */
    00463
    00464 /*
    00465  * Return the component of 'p' with minimum non-zero absolute value. 'index'
    00466  * points to the component index that has the minimum value. If no such value
    00467  * and index is found, Value 1 is returned.
    00468  */
    00469 void Vector_Min_Not_Zero(Value *p,unsigned length,int *index,Value *min)
    00470 {
    00471   Value aux;
    00472   int i;
    00473
    00474
    00475   i = First_Non_Zero(p, length);
    00476   if (i == -1) {
    00477     value_set_si(*min,1);
    00478     return;
    00479   }
    00480   *index = i;
    00481   value_absolute(*min, p[i]);
    00482   value_init(aux);
    00483   for (i = i+1; i < length; i++) {
    00484     if (value_zero_p(p[i]))
    00485       continue;
    00486     value_absolute(aux, p[i]);
    00487     if (value_lt(aux,*min)) {
    00488       value_assign(*min,aux);
    00489       *index = i;
    00490     }
    00491   }
    00492   value_clear(aux);
    00493 } /* Vector_Min_Not_Zero */
    00494
    00495 /*
    00496  * Return the GCD of components of Vector 'p'
    00497  */
    00498 void Vector_Gcd(Value *p,unsigned length,Value *min) {
    00499
    00500   Value *q,*cq, *cp;
    00501   int i, Not_Zero, Index_Min=0;
    00502
    00503   q  = (Value *)malloc(length*sizeof(Value));
    00504
    00505   /* Initialize all the 'Value' variables */
    00506   for(i=0;i<length;i++)
    00507     value_init(q[i]);
    00508
    00509   /* 'cp' points to vector 'p' and cq points to vector 'q' that holds the */
    00510   /* absolute value of elements of vector 'p'.                            */
    00511   cp=p;
    00512   for (cq = q,i=0;i<length;i++) {
    00513     value_absolute(*cq,*cp);
    00514     cq++;
    00515     cp++;
    00516   }
    00517   do {
    00518     Vector_Min_Not_Zero(q,length,&Index_Min,min);
    00519
    00520     /* if (*min != 1) */
    00521     if (value_notone_p(*min)) {
    00522
    00523       cq=q;
    00524       Not_Zero=0;
    00525       for (i=0;i<length;i++,cq++)
    00526         if (i!=Index_Min) {
    00527
    00528           /* Not_Zero |= (*cq %= *min) */
    00529           value_modulus(*cq,*cq,*min);
    00530           Not_Zero |= value_notzero_p(*cq);
    00531         }
    00532     }
    00533     else
    00534       break;
    00535   } while (Not_Zero);
    00536
    00537   /* Clear all the 'Value' variables */
    00538   for(i=0;i<length;i++)
    00539     value_clear(q[i]);
    00540   free(q);
    00541 } /* Vector_Gcd */
    00542
    00543 /*
    00544  * Given vectors 'p1', 'p2', and a pointer to a function returning 'Value type,
    00545  * compute p3[i] = f(p1[i],p2[i]).
    00546  */
    00547 void Vector_Map(Value *p1,Value *p2,Value *p3,unsigned length,
    00548                 Value *(*f)(Value,Value))
    00549 {
    00550   Value *cp1, *cp2, *cp3;
    00551   int i;
    00552
    00553   cp1=p1;
    00554   cp2=p2;
    00555   cp3=p3;
    00556   for(i=0;i<length;i++) {
    00557     value_assign(*cp3,*(*f)(*cp1, *cp2));
    00558     cp1++; cp2++; cp3++;
    00559   }
    00560   return;
    00561 } /* Vector_Map */
    00562
    00563 /*
    00564  * Reduce a vector by dividing it by GCD. There is no restriction on
    00565  * components of Vector 'p'. Making the last element positive is *not* OK
    00566  * for equalities.
    00567  */
    00568 void Vector_Normalize(Value *p,unsigned length) {
    00569
    00570   Value gcd;
    00571   int i;
    00572
    00573   value_init(gcd);
    00574
    00575   Vector_Gcd(p,length,&gcd);
    00576
    00577   if (value_notone_p(gcd))
    00578     Vector_AntiScale(p, p, gcd, length);
    00579
    00580   value_clear(gcd);
    00581 } /* Vector_Normalize */
    00582
    00583 /*
    00584  * Reduce a vector by dividing it by GCD and making sure its pos-th
    00585  * element is positive.
    00586  */
    00587 void Vector_Normalize_Positive(Value *p,int length,int pos) {
    00588
    00589   Value gcd;
    00590   int i;
    00591
    00592   value_init(gcd);
    00593   Vector_Gcd(p,length,&gcd);
    00594   if (value_neg_p(p[pos]))
    00595     value_oppose(gcd,gcd);
    00596   if(value_notone_p(gcd))
    00597     Vector_AntiScale(p, p, gcd, length);
    00598   value_clear(gcd);
    00599 } /* Vector_Normalize_Positive */
    00600
    00601 /*
    00602  * Reduce 'p' by operating binary function on its components successively
    00603  */
    00604 void Vector_Reduce(Value *p,unsigned length,void(*f)(Value,Value *),Value *r) {
    00605
    00606   Value *cp;
    00607   int i;
    00608
    00609   cp = p;
    00610   value_assign(*r,*cp);
    00611   for(i=1;i<length;i++) {
    00612     cp++;
    00613     (*f)(*cp,r);
    00614   }
    00615 } /* Vector_Reduce */
    00616
    00617 /*
    00618  * Sort the components of a Vector 'vector' using Heap Sort.
    00619  */
    00620 void Vector_Sort(Value *vector,unsigned n) {
    00621
    00622   int i, j;
    00623   Value temp;
    00624   Value *current_node=(Value *)0;
    00625   Value *left_son,*right_son;
    00626
    00627   value_init(temp);
    00628
    00629   for (i=(n-1)/2;i>=0;i--) {
    00630
    00631     /* Phase 1 : build the heap */
    00632     j=i;
    00633     value_assign(temp,*(vector+i));
    00634
    00635     /* While not a leaf */
    00636     while (j<=(n-1)/2) {
    00637       current_node = vector+j;
    00638       left_son = vector+(j<<1)+1;
    00639
    00640       /* If only one son */
    00641       if ((j<<1)+2>=n) {
    00642         if (value_lt(temp,*left_son)) {
    00643           value_assign(*current_node,*left_son);
    00644           j=(j<<1)+1;
    00645         }
    00646         else
    00647           break;
    00648       }
    00649       else {
    00650
    00651         /* If two sons */
    00652         right_son=left_son+1;
    00653         if (value_lt(*right_son,*left_son)) {
    00654           if (value_lt(temp,*left_son)) {
    00655             value_assign(*current_node,*left_son);
    00656             j=(j<<1)+1;
    00657           }
    00658           else
    00659             break;
    00660         }
    00661         else {
    00662           if (value_lt(temp,*right_son)) {
    00663             value_assign(*current_node,*right_son );
    00664             j=(j<<1)+2;
    00665           }
    00666           else
    00667             break;
    00668         }
    00669       }
    00670     }
    00671     value_assign(*current_node,temp);
    00672   }
    00673   for(i=n-1;i>0;i--) {
    00674
    00675     /* Phase 2 : sort the heap */
    00676     value_assign(temp, *(vector+i));
    00677     value_assign(*(vector+i),*vector);
    00678     j=0;
    00679
    00680     /* While not a leaf */
    00681     while (j<i/2) {
    00682       current_node=vector+j;
    00683       left_son=vector+(j<<1)+1;
    00684
    00685       /* If only one son */
    00686       if ((j<<1)+2>=i) {
    00687         if (value_lt(temp,*left_son)) {
    00688           value_assign(*current_node,*left_son);
    00689           j=(j<<1)+1;
    00690         }
    00691         else
    00692           break;
    00693       }
    00694       else {
    00695
    00696         /* If two sons */
    00697         right_son=left_son+1;
    00698         if (value_lt(*right_son,*left_son)) {
    00699           if (value_lt(temp,*left_son)) {
    00700             value_assign(*current_node,*left_son);
    00701             j=(j<<1)+1;
    00702           }
    00703           else
    00704             break;
    00705         }
    00706         else {
    00707           if (value_lt(temp,*right_son)) {
    00708             value_assign(*current_node,*right_son );
    00709             j=(j<<1)+2;
    00710           }
    00711           else
    00712             break;
    00713         }
    00714       }
    00715     }
    00716     value_assign(*current_node,temp);
    00717   }
    00718   value_clear(temp);
    00719   return;
    00720 } /* Vector_Sort */
    00721
    00722 /*
    00723  * Replaces constraint a x >= c by x >= ceil(c/a)
    00724  * where "a" is a common factor in the coefficients
    00725  * old is the constraint; v points to an initialized
    00726  * value that this procedure can use.
    00727  * Return non-zero if something changed.
    00728  * Result is placed in newp.
    00729  */
    00730 int ConstraintSimplify(Value *old, Value *newp, int len, Value* v)
    00731 {
    00732     /* first remove common factor of all coefficients (including "c") */
    00733     Vector_Gcd(old+1, len - 1, v);
    00734     if (value_notone_p(*v))
    00735         Vector_AntiScale(old+1, newp+1, *v, len-1);
    00736
    00737     Vector_Gcd(old+1, len - 2, v);
    00738
    00739     if (value_one_p(*v))
    00740         return 0;
    00741
    00742     Vector_AntiScale(old+1, newp+1, *v, len-2);
    00743     value_pdivision(newp[len-1], old[len-1], *v);
    00744     return 1;
    00745 }
    00746
    00747 int Vector_IsZero(Value * v, unsigned length) {
    00748   unsigned i;
    00749   if (value_notzero_p(v[0])) return 0;
    00750   else {
    00751     value_set_si(v[0], 1);
    00752     for (i=length-1; value_zero_p(v[i]); i--);
    00753     value_set_si(v[0], 0);
    00754     return (i==0);
    00755   }
    00756 }
    00757
    00758 #define MAX_CACHE_SIZE 20
    00759 static struct {
    00760   Value *p;
    00761   int   size;
    00762 } cache[MAX_CACHE_SIZE];
    00763 static int cache_size = 0;
    00764
    00765 Value* value_alloc(int want, int *got)
    00766 {
    00767     int i;
    00768     Value *p;
    00769
    00770     if (cache_size) {
    00771       int best;
    00772       for (i = 0; i < cache_size; ++i) {
    00773         if (cache[i].size >= want) {
    00774           Value *p = cache[i].p;
    00775           *got = cache[i].size;
    00776           if (--cache_size != i)
    00777             cache[i] = cache[cache_size];
    00778           Vector_Set(p, 0, want);
    00779           return p;
    00780         }
    00781         if (i == 0)
    00782           best = 0;
    00783         else if (cache[i].size > cache[best].size)
    00784           best = i;
    00785       }
    00786
    00787       p = (Value *)realloc(cache[best].p, want * sizeof(Value));
    00788       *got = cache[best].size;
    00789       if (--cache_size != best)
    00790         cache[best] = cache[cache_size];
    00791       Vector_Set(p, 0, *got);
    00792     } else {
    00793       p = (Value *)malloc(want * sizeof(Value));
    00794       *got = 0;
    00795     }
    00796
    00797     if (!p)
    00798       return p;
    00799
    00800     for (i = *got; i < want; ++i)
    00801       value_init(p[i]);
    00802     *got = want;
    00803
    00804     return p;
    00805 }
    00806
    00807 void value_free(Value *p, int size)
    00808 {
    00809     int i;
    00810
    00811     if (cache_size < MAX_CACHE_SIZE) {
    00812       cache[cache_size].p = p;
    00813       cache[cache_size].size = size;
    00814       ++cache_size;
    00815       return;
    00816     }
    00817
    00818     for (i=0; i < size; i++)
    00819       value_clear(p[i]);
    00820     free(p);
    00821 }
    00822