2 This file is part of PolyLib.
4 PolyLib is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 PolyLib is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with PolyLib. If not, see <http://www.gnu.org/licenses/>.
20 Both this software and its documentation are
22 Copyrighted 1993 by IRISA /Universite de Rennes I - France,
23 Copyright 1995,1996 by BYU, Provo, Utah
30 #include <polylib/polylib.h>
32 //#define THREAD_SAFE_POLYLIB
41 void Factorial(int n
, Value
*fact
) {
48 value_set_si(*fact
,1);
51 value_multiply(*fact
,*fact
,tmp
);
57 * Compute n!/(p!(n-p)!)
59 void Binomial(int n
, int p
, Value
*result
) {
65 value_init(tmp
);value_init(f
);
70 value_set_si(*result
,(n
-p
+1));
71 for (i
=n
-p
+2;i
<=n
;i
++) {
73 value_multiply(*result
,*result
,tmp
);
76 value_division(*result
,*result
,f
);
79 value_set_si(*result
,1);
80 value_clear(f
);value_clear(tmp
);
84 * Return the number of ways to choose 'b' items from 'a' items, that is,
85 * return a!/(b!(a-b)!)
87 void CNP(int a
,int b
, Value
*result
) {
93 value_set_si(*result
,1);
95 /* If number of items is less than the number to be choosen, return 1 */
102 value_multiply(*result
,*result
,tmp
);
104 for(i
=1;i
<=(a
-b
);++i
) {
106 value_division(*result
,*result
,tmp
);
112 * Compute GCD of 'a' and 'b'
114 void Gcd(Value a
,Value b
,Value
*result
) {
120 value_assign(acopy
,a
);
121 value_assign(bcopy
,b
);
122 while(value_notzero_p(acopy
)) {
123 value_modulus(*result
,bcopy
,acopy
);
124 value_assign(bcopy
,acopy
);
125 value_assign(acopy
,*result
);
127 value_absolute(*result
,bcopy
);
133 * Return the smallest component index in 'p' whose value is non-zero
135 int First_Non_Zero(Value
*p
,unsigned length
) {
141 for (i
=0;i
<length
;i
++) {
142 if (value_notzero_p(*cp
))
146 return((i
==length
) ? -1 : i
);
147 } /* First_Non_Zero */
150 * Allocate memory space for Vector
152 Vector
*Vector_Alloc(unsigned length
) {
157 vector
= (Vector
*)malloc(sizeof(Vector
));
159 errormsg1("Vector_Alloc", "outofmem", "out of memory space");
163 vector
->p
=(Value
*)malloc(length
* sizeof(Value
));
165 errormsg1("Vector_Alloc", "outofmem", "out of memory space");
169 for(i
=0;i
<length
;i
++)
170 value_init(vector
->p
[i
]);
175 * Free the memory space occupied by Vector
177 void Vector_Free(Vector
*vector
) {
182 for(i
=0;i
<vector
->Size
;i
++)
183 value_clear(vector
->p
[i
]);
189 * Print the contents of a Vector
191 void Vector_Print(FILE *Dst
, const char *Format
, Vector
*vector
)
197 fprintf(Dst
, "%d\n", length
=vector
->Size
);
199 for (i
=0;i
<length
;i
++) {
201 value_print(Dst
,Format
,*p
++);
204 value_print(Dst
,P_VALUE_FMT
,*p
++);
211 * Read the contents of a Vector
213 Vector
*Vector_Read() {
221 scanf("%d", &length
);
222 vector
= Vector_Alloc(length
);
224 errormsg1("Vector_Read", "outofmem", "out of memory space");
228 for (i
=0;i
<length
;i
++)
230 int r
=scanf("%ms",&s
);
233 errormsg1("Vector_Read", "hi, Mathematica", "scanf at line 231 failed");
236 value_read(*(p
++),s
);
243 * Assign 'n' to each component of Vector 'p'
245 void Vector_Set(Value
*p
,int n
,unsigned length
) {
251 for (i
=0;i
<length
;i
++) {
259 * Exchange the components of the vectors 'p1' and 'p2' of length 'length'
261 void Vector_Exchange(Value
*p1
, Value
*p2
, unsigned length
) {
265 for(i
=0;i
<length
;i
++) {
266 value_swap(p1
[i
],p2
[i
]);
272 * Copy Vector 'p1' to Vector 'p2'
274 void Vector_Copy(Value
*p1
,Value
*p2
,unsigned length
) {
282 for(i
=0;i
<length
;i
++)
283 value_assign(*cp2
++,*cp1
++);
289 * Add two vectors 'p1' and 'p2' and store the result in 'p3'
291 void Vector_Add(Value
*p1
,Value
*p2
,Value
*p3
,unsigned length
) {
293 Value
*cp1
, *cp2
, *cp3
;
299 for (i
=0;i
<length
;i
++) {
301 /* *cp3++ = *cp1++ + *cp2++ */
302 value_addto(*cp3
,*cp1
,*cp2
);
308 * Subtract two vectors 'p1' and 'p2' and store the result in 'p3'
310 void Vector_Sub(Value
*p1
,Value
*p2
,Value
*p3
,unsigned length
) {
312 Value
*cp1
, *cp2
, *cp3
;
318 for (i
=0;i
<length
;i
++) {
320 /* *cp3++= *cp1++ - *cp2++ */
321 value_subtract(*cp3
,*cp1
,*cp2
);
327 * Compute Bitwise OR of Vectors 'p1' and 'p2' and store in 'p3'
329 void Vector_Or(Value
*p1
,Value
*p2
,Value
*p3
,unsigned length
) {
331 Value
*cp1
, *cp2
, *cp3
;
337 for (i
=0;i
<length
;i
++) {
339 /* *cp3++=*cp1++ | *cp2++ */
340 value_orto(*cp3
,*cp1
,*cp2
);
346 * Scale Vector 'p1' lambda times and store in 'p2'
348 void Vector_Scale(Value
*p1
,Value
*p2
,Value lambda
,unsigned length
) {
355 for (i
=0;i
<length
;i
++) {
357 /* *cp2++=*cp1++ * lambda */
358 value_multiply(*cp2
,*cp1
,lambda
);
364 * Antiscale Vector 'p1' by lambda and store in 'p2'
365 * Assumes all elements of 'p1' are divisble by lambda.
367 void Vector_AntiScale(Value
*p1
, Value
*p2
, Value lambda
, unsigned length
)
371 for (i
= 0; i
< length
; i
++)
372 value_divexact(p2
[i
], p1
[i
], lambda
);
373 } /* Vector_AntiScale */
376 * Puts negative of 'p1' in 'p2'
378 void Vector_Oppose(Value
*p1
, Value
*p2
, unsigned len
)
382 for (i
= 0; i
< len
; ++i
)
383 value_oppose(p2
[i
], p1
[i
]);
387 * Return the inner product of the two Vectors 'p1' and 'p2'
389 void Inner_Product(Value
*p1
, Value
*p2
, unsigned length
, Value
*ip
)
394 value_multiply(*ip
, p1
[0], p2
[0]);
396 value_set_si(*ip
, 0);
397 for(i
= 1; i
< length
; i
++)
398 value_addmul(*ip
, p1
[i
], p2
[i
]);
399 } /* Inner_Product */
402 * Return the maximum of the components of 'p'
404 void Vector_Max(Value
*p
,unsigned length
, Value
*max
) {
410 value_assign(*max
,*cp
);
412 for (i
=1;i
<length
;i
++) {
413 value_maximum(*max
,*max
,*cp
);
419 * Return the minimum of the components of Vector 'p'
421 void Vector_Min(Value
*p
,unsigned length
,Value
*min
) {
427 value_assign(*min
,*cp
);
429 for (i
=1;i
<length
;i
++) {
430 value_minimum(*min
,*min
,*cp
);
437 * Given Vectors 'p1' and 'p2', return Vector 'p3' = lambda * p1 + mu * p2.
439 void Vector_Combine(Value
*p1
, Value
*p2
, Value
*p3
, Value lambda
, Value mu
,
446 for (i
= 0; i
< length
; i
++) {
447 value_multiply(tmp
, lambda
, p1
[i
]);
448 value_addmul(tmp
, mu
, p2
[i
]);
449 value_assign(p3
[i
], tmp
);
453 } /* Vector_Combine */
456 * Return 1 if 'Vec1' equals 'Vec2', otherwise return 0
458 int Vector_Equal(Value
*Vec1
, Value
*Vec2
, unsigned n
)
462 for (i
= 0; i
< n
; ++i
)
463 if (value_ne(Vec1
[i
], Vec2
[i
]))
470 * Return the component of 'p' with minimum non-zero absolute value. 'index'
471 * points to the component index that has the minimum value. If no such value
472 * and index is found, Value 1 is returned.
474 void Vector_Min_Not_Zero(Value
*p
,unsigned length
,int *index
,Value
*min
)
480 i
= First_Non_Zero(p
, length
);
482 value_set_si(*min
,1);
486 value_absolute(*min
, p
[i
]);
488 for (i
= i
+1; i
< length
; i
++) {
489 if (value_zero_p(p
[i
]))
491 value_absolute(aux
, p
[i
]);
492 if (value_lt(aux
,*min
)) {
493 value_assign(*min
,aux
);
498 } /* Vector_Min_Not_Zero */
501 * Return the GCD of components of Vector 'p'
503 void Vector_Gcd(Value
*p
,unsigned length
,Value
*min
) {
506 int i
, Not_Zero
, Index_Min
=0;
508 q
= (Value
*)malloc(length
*sizeof(Value
));
510 /* Initialize all the 'Value' variables */
511 for(i
=0;i
<length
;i
++)
514 /* 'cp' points to vector 'p' and cq points to vector 'q' that holds the */
515 /* absolute value of elements of vector 'p'. */
517 for (cq
= q
,i
=0;i
<length
;i
++) {
518 value_absolute(*cq
,*cp
);
523 Vector_Min_Not_Zero(q
,length
,&Index_Min
,min
);
526 if (value_notone_p(*min
)) {
530 for (i
=0;i
<length
;i
++,cq
++)
533 /* Not_Zero |= (*cq %= *min) */
534 value_modulus(*cq
,*cq
,*min
);
535 Not_Zero
|= value_notzero_p(*cq
);
542 /* Clear all the 'Value' variables */
543 for(i
=0;i
<length
;i
++)
549 * Given vectors 'p1', 'p2', and a pointer to a function returning 'Value type,
550 * compute p3[i] = f(p1[i],p2[i]).
552 void Vector_Map(Value
*p1
,Value
*p2
,Value
*p3
,unsigned length
,
553 Value
*(*f
)(Value
,Value
))
555 Value
*cp1
, *cp2
, *cp3
;
561 for(i
=0;i
<length
;i
++) {
562 value_assign(*cp3
,*(*f
)(*cp1
, *cp2
));
569 * Reduce a vector by dividing it by GCD. There is no restriction on
570 * components of Vector 'p'. Making the last element positive is *not* OK
573 void Vector_Normalize(Value
*p
,unsigned length
) {
580 Vector_Gcd(p
,length
,&gcd
);
582 if (value_notone_p(gcd
))
583 Vector_AntiScale(p
, p
, gcd
, length
);
586 } /* Vector_Normalize */
589 * Reduce a vector by dividing it by GCD and making sure its pos-th
590 * element is positive.
592 void Vector_Normalize_Positive(Value
*p
,int length
,int pos
) {
598 Vector_Gcd(p
,length
,&gcd
);
599 if (value_neg_p(p
[pos
]))
600 value_oppose(gcd
,gcd
);
601 if(value_notone_p(gcd
))
602 Vector_AntiScale(p
, p
, gcd
, length
);
604 } /* Vector_Normalize_Positive */
607 * Reduce 'p' by operating binary function on its components successively
609 void Vector_Reduce(Value
*p
,unsigned length
,void(*f
)(Value
,Value
*),Value
*r
) {
615 value_assign(*r
,*cp
);
616 for(i
=1;i
<length
;i
++) {
620 } /* Vector_Reduce */
623 * Sort the components of a Vector 'vector' using Heap Sort.
625 void Vector_Sort(Value
*vector
,unsigned n
) {
629 Value
*current_node
=(Value
*)0;
630 Value
*left_son
,*right_son
;
634 for (i
=(n
-1)/2;i
>=0;i
--) {
636 /* Phase 1 : build the heap */
638 value_assign(temp
,*(vector
+i
));
640 /* While not a leaf */
642 current_node
= vector
+j
;
643 left_son
= vector
+(j
<<1)+1;
645 /* If only one son */
647 if (value_lt(temp
,*left_son
)) {
648 value_assign(*current_node
,*left_son
);
657 right_son
=left_son
+1;
658 if (value_lt(*right_son
,*left_son
)) {
659 if (value_lt(temp
,*left_son
)) {
660 value_assign(*current_node
,*left_son
);
667 if (value_lt(temp
,*right_son
)) {
668 value_assign(*current_node
,*right_son
);
676 value_assign(*current_node
,temp
);
680 /* Phase 2 : sort the heap */
681 value_assign(temp
, *(vector
+i
));
682 value_assign(*(vector
+i
),*vector
);
685 /* While not a leaf */
687 current_node
=vector
+j
;
688 left_son
=vector
+(j
<<1)+1;
690 /* If only one son */
692 if (value_lt(temp
,*left_son
)) {
693 value_assign(*current_node
,*left_son
);
702 right_son
=left_son
+1;
703 if (value_lt(*right_son
,*left_son
)) {
704 if (value_lt(temp
,*left_son
)) {
705 value_assign(*current_node
,*left_son
);
712 if (value_lt(temp
,*right_son
)) {
713 value_assign(*current_node
,*right_son
);
721 value_assign(*current_node
,temp
);
728 * Replaces constraint a x >= c by x >= ceil(c/a)
729 * where "a" is a common factor in the coefficients
730 * old is the constraint; v points to an initialized
731 * value that this procedure can use.
732 * Return non-zero if something changed.
733 * Result is placed in newp.
735 int ConstraintSimplify(Value
*old
, Value
*newp
, int len
, Value
* v
)
737 /* first remove common factor of all coefficients (including "c") */
738 Vector_Gcd(old
+1, len
- 1, v
);
739 if (value_notone_p(*v
))
740 Vector_AntiScale(old
+1, newp
+1, *v
, len
-1);
742 Vector_Gcd(old
+1, len
- 2, v
);
747 Vector_AntiScale(old
+1, newp
+1, *v
, len
-2);
748 value_pdivision(newp
[len
-1], old
[len
-1], *v
);
752 int Vector_IsZero(Value
* v
, unsigned length
) {
754 if (value_notzero_p(v
[0])) return 0;
756 value_set_si(v
[0], 1);
757 for (i
=length
-1; value_zero_p(v
[i
]); i
--);
758 value_set_si(v
[0], 0);
767 #define MAX_CACHE_SIZE 20
770 /************************************************/
771 /** Vincent's patch for thread safe value cache */
772 /** each thread has it's own cache and size. */
774 /************************************************/
776 #ifdef THREAD_SAFE_POLYLIB
781 static pthread_once_t once_cache
= PTHREAD_ONCE_INIT
;
782 static pthread_key_t cache_key
;
783 /* cache_size is stored in the last+1 cache position */
784 #define cache_size (cache[MAX_CACHE_SIZE].size)
786 static cache_holder
*allocate_local_cache(void)
789 cache
= malloc( sizeof(cache_holder
)*(MAX_CACHE_SIZE
+1) );
790 assert( cache
!=NULL
);
792 assert( pthread_setspecific( cache_key
, cache
) == 0 );
795 static void free_local_cache(void *c
)
798 assert( pthread_setspecific(cache_key
, NULL
) == 0 );
800 static void init_value_caches(void)
802 pthread_key_create(&cache_key
, free_local_cache
);
806 cache_holder cache
[MAX_CACHE_SIZE
];
807 static int cache_size
= 0;
808 #endif // THREAD_SAFE_POLYLIB
811 Value
* value_alloc(int want
, int *got
)
816 #ifdef THREAD_SAFE_POLYLIB
817 assert(pthread_once(&once_cache
, init_value_caches
) == 0);
819 if( (cache
= pthread_getspecific( cache_key
)) == NULL
)
820 cache
= allocate_local_cache();
821 #endif // THREAD_SAFE_POLYLIB
825 for (i
= 0; i
< cache_size
; ++i
) {
826 if (cache
[i
].size
>= want
) {
827 Value
*p
= cache
[i
].p
;
828 *got
= cache
[i
].size
;
829 if (--cache_size
!= i
)
830 cache
[i
] = cache
[cache_size
];
831 Vector_Set(p
, 0, want
);
834 if (cache
[i
].size
> cache
[best
].size
)
838 p
= (Value
*)realloc(cache
[best
].p
, want
* sizeof(Value
));
839 *got
= cache
[best
].size
;
840 if (--cache_size
!= best
)
841 cache
[best
] = cache
[cache_size
];
842 Vector_Set(p
, 0, *got
);
845 p
= (Value
*)malloc(want
* sizeof(Value
));
852 for (i
= *got
; i
< want
; ++i
)
859 void value_free(Value
*p
, int size
)
863 #ifdef THREAD_SAFE_POLYLIB
864 /* suppose alloc before free :) */
865 // assert(pthread_once(&once_cache, init_value_caches) == 0);
867 // if( (cache = pthread_getspecific( cache_key )) == NULL )
868 // cache = allocate_local_cache();
869 assert( (cache
= pthread_getspecific( cache_key
)) != NULL
);
870 #endif // THREAD_SAFE_POLYLIB
872 if (cache_size
< MAX_CACHE_SIZE
) {
873 cache
[cache_size
].p
= p
;
874 cache
[cache_size
].size
= size
;
879 for (i
=0; i
< size
; i
++)