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,unsigned length) {
00413   
00414   Value *cp1, *cp2, *cp3;
00415   Value tmp1, tmp2;
00416   int i;
00417   
00418   value_init(tmp1); value_init(tmp2);
00419   cp1=p1;
00420   cp2=p2;
00421   cp3=p3;
00422   
00423   for (i=0;i<length;i++) {
00424     
00425     /* tmp1 = lambda * *cp1 */
00426     value_multiply(tmp1,lambda,*cp1);
00427     
00428     /* tmp2 = mu * *cp2 */
00429     value_multiply(tmp2,mu,*cp2);
00430     
00431     /* *cp3 = tmp1 + tmp2 */
00432     value_addto(*cp3,tmp1,tmp2);
00433     cp1++; cp2++; cp3++;
00434   }
00435   value_clear(tmp1);
00436   value_clear(tmp2);
00437   return;
00438 } /* Vector_Combine */
00439 
00440 /* 
00441  * Return 1 if 'Vec1' equals 'Vec2', otherwise return 0 
00442  */
00443 int Vector_Equal(Value *Vec1,Value *Vec2,unsigned n) {
00444   
00445   int i;
00446   Value *p1, *p2;
00447   
00448   p1=Vec1;
00449   p2=Vec2;
00450   for(i=0;i<n;i++) {
00451   
00452     /* if (*p1++!=*p2++) break; */
00453     if (value_ne(*p1,*p2))
00454       break;
00455     p1++; p2++;
00456   }
00457   return (i==n);
00458 } /* Vector_Equal */
00459 
00460 /* 
00461  * Return the component of 'p' with minimum non-zero absolute value. 'index'
00462  * points to the component index that has the minimum value. If no such value
00463  * and index is found, Value 1 is returned.
00464  */
00465 void Vector_Min_Not_Zero(Value *p,unsigned length,int *index,Value *min) {
00466   
00467   Value *cp, aux;
00468   int i,j;
00469   
00470   value_init(aux);
00471   
00472   cp=p;
00473   for(i=0;i<length;i++) {
00474     if (value_notzero_p(*cp)) {
00475       value_absolute(*min,*cp);
00476       *index = i;
00477       break;
00478     }
00479     ++cp;
00480   }
00481   if (i == length) {
00482     value_set_si(*min,1);
00483     value_clear(aux);
00484     cp = NULL;
00485     return;
00486   }
00487   ++cp;
00488   for(j=i+1;j<length;j++) {
00489     value_absolute(aux,*cp);
00490     if (value_lt(aux,*min) && value_notzero_p(aux)) {
00491       value_assign(*min,aux);
00492       *index = j;
00493     }  
00494     cp++;
00495   }
00496   value_clear(aux);
00497   cp = NULL;
00498 } /* Vector_Min_Not_Zero */
00499 
00500 /* 
00501  * Return the GCD of components of Vector 'p' 
00502  */
00503 void Vector_Gcd(Value *p,unsigned length,Value *min) {
00504   
00505   Value *q,*cq, *cp;
00506   int i, Not_Zero, Index_Min=0;
00507   
00508   q  = (Value *)malloc(length*sizeof(Value));
00509 
00510   /* Initialize all the 'Value' variables */
00511   for(i=0;i<length;i++)
00512     value_init(q[i]);
00513   
00514   /* 'cp' points to vector 'p' and cq points to vector 'q' that holds the */
00515   /* absolute value of elements of vector 'p'.                            */
00516   cp=p;
00517   for (cq = q,i=0;i<length;i++) {
00518     value_absolute(*cq,*cp);    
00519     cq++;
00520     cp++;
00521   }
00522   do {   
00523     Vector_Min_Not_Zero(q,length,&Index_Min,min);
00524     
00525     /* if (*min != 1) */
00526     if (value_notone_p(*min)) {
00527       
00528       cq=q;
00529       Not_Zero=0;
00530       for (i=0;i<length;i++,cq++)
00531         if (i!=Index_Min) {
00532           
00533           /* Not_Zero |= (*cq %= *min) */
00534           value_modulus(*cq,*cq,*min);
00535           Not_Zero |= value_notzero_p(*cq);
00536         }
00537     } 
00538     else 
00539       break;
00540   } while (Not_Zero);
00541   
00542   /* Clear all the 'Value' variables */
00543   for(i=0;i<length;i++)
00544     value_clear(q[i]);
00545   free(q);
00546 } /* Vector_Gcd */
00547 
00548 /* 
00549  * Given vectors 'p1', 'p2', and a pointer to a function returning 'Value type,
00550  * compute p3[i] = f(p1[i],p2[i]).  
00551  */ 
00552 void Vector_Map(Value *p1,Value *p2,Value *p3,unsigned length,Value *(*f)()) {
00553   
00554   Value *cp1, *cp2, *cp3;
00555   int i;
00556   
00557   cp1=p1;
00558   cp2=p2;
00559   cp3=p3;
00560   for(i=0;i<length;i++) {
00561     value_assign(*cp3,*(*f)(*cp1, *cp2));
00562     cp1++; cp2++; cp3++;
00563   }
00564   return;
00565 } /* Vector_Map */
00566 
00567 /* 
00568  * Reduce a vector by dividing it by GCD. There is no restriction on 
00569  * components of Vector 'p'. Making the last element positive is *not* OK
00570  * for equalities. 
00571  */
00572 void Vector_Normalize(Value *p,unsigned length) {
00573   
00574   Value *cp, gcd,tmp;
00575   int i;
00576   
00577   value_init(tmp);value_init(gcd);
00578 
00579   Vector_Gcd(p,length,&gcd);
00580   value_set_si(tmp,1);
00581   
00582   if (value_gt(gcd,tmp)) {
00583     cp = p;    
00584     for (i=0; i<length; i++) { 
00585       
00586       /* *cp /= gcd */
00587       value_division(*cp,*cp,gcd);
00588       cp++;
00589     }
00590   }
00591   value_clear(tmp);
00592   value_clear(gcd);
00593   return;
00594 } /* Vector_Normalize */
00595 
00596 /* 
00597  * Reduce a vector by dividing it by GCD and making sure its pos-th 
00598  * element is positive.    
00599  */
00600 void Vector_Normalize_Positive(Value *p,int length,int pos) {
00601   
00602   Value gcd;
00603   int i;
00604   
00605   value_init(gcd);
00606   Vector_Gcd(p,length,&gcd);
00607   if (value_neg_p(p[pos]))
00608     value_oppose(gcd,gcd);
00609   if(value_notone_p(gcd))
00610     for(i=0; i<length; i++)
00611       value_division(p[i],p[i],gcd);
00612   value_clear(gcd);
00613 
00614   return;
00615 } /* Vector_Normalize_Positive */
00616 
00617 /* 
00618  * Reduce 'p' by operating binary function on its components successively 
00619  */
00620 void Vector_Reduce(Value *p,unsigned length,void(*f)(Value,Value *),Value *r) {
00621   
00622   Value *cp;
00623   int i;
00624   
00625   cp = p;
00626   value_assign(*r,*cp);
00627   for(i=1;i<length;i++) {
00628     cp++;
00629     (*f)(*cp,r);
00630   }
00631 } /* Vector_Reduce */
00632 
00633 /* 
00634  * Sort the components of a Vector 'vector' using Heap Sort. 
00635  */
00636 void Vector_Sort(Value *vector,unsigned n) {
00637   
00638   int i, j;
00639   Value temp;
00640   Value *current_node=(Value *)0;
00641   Value *left_son,*right_son;
00642 
00643   value_init(temp);
00644 
00645   for (i=(n-1)/2;i>=0;i--) { 
00646     
00647     /* Phase 1 : build the heap */
00648     j=i;
00649     value_assign(temp,*(vector+i));
00650     
00651     /* While not a leaf */
00652     while (j<=(n-1)/2) {
00653       current_node = vector+j;
00654       left_son = vector+(j<<1)+1;
00655 
00656       /* If only one son */
00657       if ((j<<1)+2>=n) {
00658         if (value_lt(temp,*left_son)) {
00659           value_assign(*current_node,*left_son);
00660           j=(j<<1)+1;
00661         }
00662         else
00663           break;
00664       }
00665       else {  
00666         
00667         /* If two sons */
00668         right_son=left_son+1;
00669         if (value_lt(*right_son,*left_son)) {
00670           if (value_lt(temp,*left_son)) {
00671             value_assign(*current_node,*left_son);
00672             j=(j<<1)+1;
00673           }
00674           else
00675             break;
00676         }
00677         else {
00678           if (value_lt(temp,*right_son)) {
00679             value_assign(*current_node,*right_son );
00680             j=(j<<1)+2;
00681           }
00682           else
00683             break;
00684         }
00685       }
00686     }
00687     value_assign(*current_node,temp);
00688   }
00689   for(i=n-1;i>0;i--) { 
00690     
00691     /* Phase 2 : sort the heap */
00692     value_assign(temp, *(vector+i));
00693     value_assign(*(vector+i),*vector);
00694     j=0;
00695     
00696     /* While not a leaf */
00697     while (j<i/2) {     
00698       current_node=vector+j;
00699       left_son=vector+(j<<1)+1;
00700       
00701       /* If only one son */
00702       if ((j<<1)+2>=i) {                
00703         if (value_lt(temp,*left_son)) {
00704           value_assign(*current_node,*left_son);
00705           j=(j<<1)+1;
00706         }
00707         else
00708           break;
00709       }
00710       else {
00711         
00712         /* If two sons */
00713         right_son=left_son+1;
00714         if (value_lt(*right_son,*left_son)) {
00715           if (value_lt(temp,*left_son)) {
00716             value_assign(*current_node,*left_son);
00717             j=(j<<1)+1;
00718           }
00719           else
00720             break;
00721         }
00722         else {
00723           if (value_lt(temp,*right_son)) {
00724             value_assign(*current_node,*right_son );
00725             j=(j<<1)+2;
00726           }
00727           else
00728             break;
00729         }
00730       }
00731     }
00732     value_assign(*current_node,temp);
00733   }
00734   value_clear(temp);
00735   return;
00736 } /* Vector_Sort */
00737 
00738 /*
00739  * Replaces constraint a x >= c by x >= ceil(c/a)
00740  * where "a" is a common factor in the coefficients
00741  * old is the constraint; v points to an initialized
00742  * value that this procedure can use.
00743  * Return non-zero if something changed.
00744  * Result is placed in new.
00745  */
00746 int ConstraintSimplify(Value *old, Value *new, int len, Value* v)
00747 {
00748     Vector_Gcd(old+1, len - 2, v);
00749 
00750     if (value_one_p(*v))
00751         return 0;
00752 
00753     Vector_AntiScale(old+1, new+1, *v, len-2);
00754     value_pdivision(new[len-1], old[len-1], *v);
00755     return 1;
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 }

Generated on Mon Sep 12 15:15:11 2005 for polylib by doxygen 1.3.5