Main Page | Class List | File List | Class Members | File Members

vector.c

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

Generated on Mon Apr 23 19:23:53 2007 for polylib by doxygen 1.3.5