void ppl_min_for_le_pointset (ppl_Pointset_Powerset_C_Polyhedron_t ps, ppl_Linear_Expression_t le, Value res) { ppl_Coefficient_t num, denom; Value dv, nv; int minimum, err; value_init (nv); value_init (dv); ppl_new_Coefficient (&num); ppl_new_Coefficient (&denom); err = ppl_Pointset_Powerset_C_Polyhedron_minimize (ps, le, num, denom, &minimum); if (err > 0) { ppl_Coefficient_to_mpz_t (num, nv); ppl_Coefficient_to_mpz_t (denom, dv); gcc_assert (value_notzero_p (dv)); value_division (res, nv, dv); } value_clear (nv); value_clear (dv); ppl_delete_Coefficient (num); ppl_delete_Coefficient (denom); }
/* * Return the number of ways to choose 'b' items from 'a' items, that is, * return a!/(b!(a-b)!) */ void CNP(int a,int b, Value *result) { int i; Value tmp; value_init(tmp); value_set_si(*result,1); /* If number of items is less than the number to be choosen, return 1 */ if(a <= b) { value_clear(tmp); return; } for(i=a;i>b;--i) { value_set_si(tmp,i); value_multiply(*result,*result,tmp); } for(i=1;i<=(a-b);++i) { value_set_si(tmp,i); value_division(*result,*result,tmp); } value_clear(tmp); } /* CNP */
/* * Compute n!/(p!(n-p)!) */ void Binomial(int n, int p, Value *result) { int i; Value tmp; Value f; value_init(tmp);value_init(f); if (n-p<p) p=n-p; if (p!=0) { value_set_si(*result,(n-p+1)); for (i=n-p+2;i<=n;i++) { value_set_si(tmp,i); value_multiply(*result,*result,tmp); } Factorial(p,&f); value_division(*result,*result,f); } else value_set_si(*result,1); value_clear(f);value_clear(tmp); } /* Binomial */
/* * Given a rational matrix 'Mat'(k x k), compute its inverse rational matrix * 'MatInv' k x k. * The output is 1, * if 'Mat' is non-singular (invertible), otherwise the output is 0. Note:: * (1) Matrix 'Mat' is modified during the inverse operation. * (2) Matrix 'MatInv' must be preallocated before passing into this function. */ int Matrix_Inverse(Matrix *Mat,Matrix *MatInv ) { int i, k, j, c; Value x, gcd, piv; Value m1,m2; Value *den; if(Mat->NbRows != Mat->NbColumns) { fprintf(stderr,"Trying to invert a non-square matrix !\n"); return 0; } /* Initialize all the 'Value' variables */ value_init(x); value_init(gcd); value_init(piv); value_init(m1); value_init(m2); k = Mat->NbRows; /* Initialise MatInv */ Vector_Set(MatInv->p[0],0,k*k); /* Initialize 'MatInv' to Identity matrix form. Each diagonal entry is set*/ /* to 1. Last column of each row (denominator of each entry in a row) is */ /* also set to 1. */ for(i=0;i<k;++i) { value_set_si(MatInv->p[i][i],1); /* value_set_si(MatInv->p[i][k],1); /* denum */ } /* Apply Gauss-Jordan elimination method on the two matrices 'Mat' and */ /* 'MatInv' in parallel. */ for(i=0;i<k;++i) { /* Check if the diagonal entry (new pivot) is non-zero or not */ if(value_zero_p(Mat->p[i][i])) { /* Search for a non-zero pivot down the column(i) */ for(j=i;j<k;++j) if(value_notzero_p(Mat->p[j][i])) break; /* If no non-zero pivot is found, the matrix 'Mat' is non-invertible */ /* Return 0. */ if(j==k) { /* Clear all the 'Value' variables */ value_clear(x); value_clear(gcd); value_clear(piv); value_clear(m1); value_clear(m2); return 0; } /* Exchange the rows, row(i) and row(j) so that the diagonal element */ /* Mat->p[i][i] (pivot) is non-zero. Repeat the same operations on */ /* matrix 'MatInv'. */ for(c=0;c<k;++c) { /* Interchange rows, row(i) and row(j) of matrix 'Mat' */ value_assign(x,Mat->p[j][c]); value_assign(Mat->p[j][c],Mat->p[i][c]); value_assign(Mat->p[i][c],x); /* Interchange rows, row(i) and row(j) of matrix 'MatInv' */ value_assign(x,MatInv->p[j][c]); value_assign(MatInv->p[j][c],MatInv->p[i][c]); value_assign(MatInv->p[i][c],x); } } /* Make all the entries in column(i) of matrix 'Mat' zero except the */ /* diagonal entry. Repeat the same sequence of operations on matrix */ /* 'MatInv'. */ for(j=0;j<k;++j) { if (j==i) continue; /* Skip the pivot */ value_assign(x,Mat->p[j][i]); if(value_notzero_p(x)) { value_assign(piv,Mat->p[i][i]); value_gcd(gcd, x, piv); if (value_notone_p(gcd) ) { value_divexact(x, x, gcd); value_divexact(piv, piv, gcd); } for(c=((j>i)?i:0);c<k;++c) { value_multiply(m1,piv,Mat->p[j][c]); value_multiply(m2,x,Mat->p[i][c]); value_subtract(Mat->p[j][c],m1,m2); } for(c=0;c<k;++c) { value_multiply(m1,piv,MatInv->p[j][c]); value_multiply(m2,x,MatInv->p[i][c]); value_subtract(MatInv->p[j][c],m1,m2); } /* Simplify row(j) of the two matrices 'Mat' and 'MatInv' by */ /* dividing the rows with the common GCD. */ Vector_Gcd(&MatInv->p[j][0],k,&m1); Vector_Gcd(&Mat->p[j][0],k,&m2); value_gcd(gcd, m1, m2); if(value_notone_p(gcd)) { for(c=0;c<k;++c) { value_divexact(Mat->p[j][c], Mat->p[j][c], gcd); value_divexact(MatInv->p[j][c], MatInv->p[j][c], gcd); } } } } } /* Find common denom for each row */ den = (Value *)malloc(k*sizeof(Value)); value_set_si(x,1); for(j=0 ; j<k ; ++j) { value_init(den[j]); value_assign(den[j],Mat->p[j][j]); /* gcd is always positive */ Vector_Gcd(&MatInv->p[j][0],k,&gcd); value_gcd(gcd, gcd, den[j]); if (value_neg_p(den[j])) value_oppose(gcd,gcd); /* make denominator positive */ if (value_notone_p(gcd)) { for (c=0; c<k; c++) value_divexact(MatInv->p[j][c], MatInv->p[j][c], gcd); /* normalize */ value_divexact(den[j], den[j], gcd); } value_gcd(gcd, x, den[j]); value_divexact(m1, den[j], gcd); value_multiply(x,x,m1); } if (value_notone_p(x)) for(j=0 ; j<k ; ++j) { for (c=0; c<k; c++) { value_division(m1,x,den[j]); value_multiply(MatInv->p[j][c],MatInv->p[j][c],m1); /* normalize */ } } /* Clear all the 'Value' variables */ for(j=0 ; j<k ; ++j) { value_clear(den[j]); } value_clear(x); value_clear(gcd); value_clear(piv); value_clear(m1); value_clear(m2); free(den); return 1; } /* Matrix_Inverse */
/* * Given (m x n) integer matrix 'X' and n x (k+1) rational matrix 'P', compute * the rational m x (k+1) rational matrix 'S'. The last column in each row of * the rational matrices is used to store the common denominator of elements * in a row. */ void rat_prodmat(Matrix *S,Matrix *X,Matrix *P) { int i,j,k; int last_column_index = P->NbColumns - 1; Value lcm, old_lcm,gcd,last_column_entry,s1; Value m1,m2; /* Initialize all the 'Value' variables */ value_init(lcm); value_init(old_lcm); value_init(gcd); value_init(last_column_entry); value_init(s1); value_init(m1); value_init(m2); /* Compute the LCM of last column entries (denominators) of rows */ value_assign(lcm,P->p[0][last_column_index]); for(k=1;k<P->NbRows;++k) { value_assign(old_lcm,lcm); value_assign(last_column_entry,P->p[k][last_column_index]); value_gcd(gcd, lcm, last_column_entry); value_divexact(m1, last_column_entry, gcd); value_multiply(lcm,lcm,m1); } /* S[i][j] = Sum(X[i][k] * P[k][j] where Sum is extended over k = 1..nbrows*/ for(i=0;i<X->NbRows;++i) for(j=0;j<P->NbColumns-1;++j) { /* Initialize s1 to zero. */ value_set_si(s1,0); for(k=0;k<P->NbRows;++k) { /* If the LCM of last column entries is one, simply add the products */ if(value_one_p(lcm)) { value_addmul(s1, X->p[i][k], P->p[k][j]); } /* Numerator (num) and denominator (denom) of S[i][j] is given by :- */ /* numerator = Sum(X[i][k]*P[k][j]*lcm/P[k][last_column_index]) and */ /* denominator= lcm where Sum is extended over k = 1..nbrows. */ else { value_multiply(m1,X->p[i][k],P->p[k][j]); value_division(m2,lcm,P->p[k][last_column_index]); value_addmul(s1, m1, m2); } } value_assign(S->p[i][j],s1); } for(i=0;i<S->NbRows;++i) { value_assign(S->p[i][last_column_index],lcm); /* Normalize the rows so that last element >=0 */ Vector_Normalize_Positive(&S->p[i][0],S->NbColumns,S->NbColumns-1); } /* Clear all the 'Value' variables */ value_clear(lcm); value_clear(old_lcm); value_clear(gcd); value_clear(last_column_entry); value_clear(s1); value_clear(m1); value_clear(m2); return; } /* rat_prodmat */
/* * Basic hermite engine */ static int hermite(Matrix *H,Matrix *U,Matrix *Q) { int nc, nr, i, j, k, rank, reduced, pivotrow; Value pivot,x,aux; Value *temp1, *temp2; /* T -1 T */ /* Computes form: A = Q H and U A = H and U = Q */ if (!H) { errormsg1("Domlib", "nullH", "hermite: ? Null H"); return -1; } nc = H->NbColumns; nr = H->NbRows; temp1 = (Value *) malloc(nc * sizeof(Value)); temp2 = (Value *) malloc(nr * sizeof(Value)); if (!temp1 ||!temp2) { errormsg1("Domlib", "outofmem", "out of memory space"); return -1; } /* Initialize all the 'Value' variables */ value_init(pivot); value_init(x); value_init(aux); for(i=0;i<nc;i++) value_init(temp1[i]); for(i=0;i<nr;i++) value_init(temp2[i]); #ifdef DEBUG fprintf(stderr,"Start -----------\n"); Matrix_Print(stderr,0,H); #endif for (k=0, rank=0; k<nc && rank<nr; k=k+1) { reduced = 1; /* go through loop the first time */ #ifdef DEBUG fprintf(stderr, "Working on col %d. Rank=%d ----------\n", k+1, rank+1); #endif while (reduced) { reduced=0; /* 1. find pivot row */ value_absolute(pivot,H->p[rank][k]); /* the kth-diagonal element */ pivotrow = rank; /* find the row i>rank with smallest nonzero element in col k */ for (i=rank+1; i<nr; i++) { value_absolute(x,H->p[i][k]); if (value_notzero_p(x) && (value_lt(x,pivot) || value_zero_p(pivot))) { value_assign(pivot,x); pivotrow = i; } } /* 2. Bring pivot to diagonal (exchange rows pivotrow and rank) */ if (pivotrow != rank) { Vector_Exchange(H->p[pivotrow],H->p[rank],nc); if (U) Vector_Exchange(U->p[pivotrow],U->p[rank],nr); if (Q) Vector_Exchange(Q->p[pivotrow],Q->p[rank],nr); #ifdef DEBUG fprintf(stderr,"Exchange rows %d and %d -----------\n", rank+1, pivotrow+1); Matrix_Print(stderr,0,H); #endif } value_assign(pivot,H->p[rank][k]); /* actual ( no abs() ) pivot */ /* 3. Invert the row 'rank' if pivot is negative */ if (value_neg_p(pivot)) { value_oppose(pivot,pivot); /* pivot = -pivot */ for (j=0; j<nc; j++) value_oppose(H->p[rank][j],H->p[rank][j]); /* H->p[rank][j] = -(H->p[rank][j]); */ if (U) for (j=0; j<nr; j++) value_oppose(U->p[rank][j],U->p[rank][j]); /* U->p[rank][j] = -(U->p[rank][j]); */ if (Q) for (j=0; j<nr; j++) value_oppose(Q->p[rank][j],Q->p[rank][j]); /* Q->p[rank][j] = -(Q->p[rank][j]); */ #ifdef DEBUG fprintf(stderr,"Negate row %d -----------\n", rank+1); Matrix_Print(stderr,0,H); #endif } if (value_notzero_p(pivot)) { /* 4. Reduce the column modulo the pivot */ /* This eventually zeros out everything below the */ /* diagonal and produces an upper triangular matrix */ for (i=rank+1;i<nr;i++) { value_assign(x,H->p[i][k]); if (value_notzero_p(x)) { value_modulus(aux,x,pivot); /* floor[integer division] (corrected for neg x) */ if (value_neg_p(x) && value_notzero_p(aux)) { /* x=(x/pivot)-1; */ value_division(x,x,pivot); value_decrement(x,x); } else value_division(x,x,pivot); for (j=0; j<nc; j++) { value_multiply(aux,x,H->p[rank][j]); value_subtract(H->p[i][j],H->p[i][j],aux); } /* U->p[i][j] -= (x * U->p[rank][j]); */ if (U) for (j=0; j<nr; j++) { value_multiply(aux,x,U->p[rank][j]); value_subtract(U->p[i][j],U->p[i][j],aux); } /* Q->p[rank][j] += (x * Q->p[i][j]); */ if (Q) for(j=0;j<nr;j++) { value_addmul(Q->p[rank][j], x, Q->p[i][j]); } reduced = 1; #ifdef DEBUG fprintf(stderr, "row %d = row %d - %d row %d -----------\n", i+1, i+1, x, rank+1); Matrix_Print(stderr,0,H); #endif } /* if (x) */ } /* for (i) */ } /* if (pivot != 0) */ } /* while (reduced) */ /* Last finish up this column */ /* 5. Make pivot column positive (above pivot row) */ /* x should be zero for i>k */ if (value_notzero_p(pivot)) { for (i=0; i<rank; i++) { value_assign(x,H->p[i][k]); if (value_notzero_p(x)) { value_modulus(aux,x,pivot); /* floor[integer division] (corrected for neg x) */ if (value_neg_p(x) && value_notzero_p(aux)) { value_division(x,x,pivot); value_decrement(x,x); /* x=(x/pivot)-1; */ } else value_division(x,x,pivot); /* H->p[i][j] -= x * H->p[rank][j]; */ for (j=0; j<nc; j++) { value_multiply(aux,x,H->p[rank][j]); value_subtract(H->p[i][j],H->p[i][j],aux); } /* U->p[i][j] -= x * U->p[rank][j]; */ if (U) for (j=0; j<nr; j++) { value_multiply(aux,x,U->p[rank][j]); value_subtract(U->p[i][j],U->p[i][j],aux); } /* Q->p[rank][j] += x * Q->p[i][j]; */ if (Q) for (j=0; j<nr; j++) { value_addmul(Q->p[rank][j], x, Q->p[i][j]); } #ifdef DEBUG fprintf(stderr, "row %d = row %d - %d row %d -----------\n", i+1, i+1, x, rank+1); Matrix_Print(stderr,0,H); #endif } /* if (x) */ } /* for (i) */ rank++; } /* if (pivot!=0) */ } /* for (k) */ /* Clear all the 'Value' variables */ value_clear(pivot); value_clear(x); value_clear(aux); for(i=0;i<nc;i++) value_clear(temp1[i]); for(i=0;i<nr;i++) value_clear(temp2[i]); free(temp2); free(temp1); return rank; } /* Hermite */
/* GaussSimplify -- Given Mat1, a matrix of equalities, performs Gaussian elimination. Find a minimum basis, Returns the rank. Mat1 is context, Mat2 is reduced in context of Mat1 */ int GaussSimplify(Matrix *Mat1,Matrix *Mat2) { int NbRows = Mat1->NbRows; int NbCols = Mat1->NbColumns; int *column_index; int i, j, k, n, t, pivot, Rank; Value gcd, tmp, *cp; column_index=(int *)malloc(NbCols * sizeof(int)); if (!column_index) { errormsg1("GaussSimplify", "outofmem", "out of memory space\n"); Pol_status = 1; return 0; } /* Initialize all the 'Value' variables */ value_init(gcd); value_init(tmp); Rank=0; for (j=0; j<NbCols; j++) { /* for each column starting at */ for (i=Rank; i<NbRows; i++) /* diagonal, look down to find */ if (value_notzero_p(Mat1->p[i][j])) /* the first non-zero entry */ break; if (i!=NbRows) { /* was one found ? */ if (i!=Rank) /* was it found below the diagonal?*/ Vector_Exchange(Mat1->p[Rank],Mat1->p[i],NbCols); /* Normalize the pivot row */ Vector_Gcd(Mat1->p[Rank],NbCols,&gcd); /* If (gcd >= 2) */ value_set_si(tmp,2); if (value_ge(gcd,tmp)) { cp = Mat1->p[Rank]; for (k=0; k<NbCols; k++,cp++) value_division(*cp,*cp,gcd); } if (value_neg_p(Mat1->p[Rank][j])) { cp = Mat1->p[Rank]; for (k=0; k<NbCols; k++,cp++) value_oppose(*cp,*cp); } /* End of normalize */ pivot=i; for (i=0;i<NbRows;i++) /* Zero out the rest of the column */ if (i!=Rank) { if (value_notzero_p(Mat1->p[i][j])) { Value a, a1, a2, a1abs, a2abs; value_init(a); value_init(a1); value_init(a2); value_init(a1abs); value_init(a2abs); value_assign(a1,Mat1->p[i][j]); value_absolute(a1abs,a1); value_assign(a2,Mat1->p[Rank][j]); value_absolute(a2abs,a2); value_gcd(a, a1abs, a2abs); value_divexact(a1, a1, a); value_divexact(a2, a2, a); value_oppose(a1,a1); Vector_Combine(Mat1->p[i],Mat1->p[Rank],Mat1->p[i],a2, a1,NbCols); Vector_Normalize(Mat1->p[i],NbCols); value_clear(a); value_clear(a1); value_clear(a2); value_clear(a1abs); value_clear(a2abs); } } column_index[Rank]=j; Rank++; } } /* end of Gauss elimination */ if (Mat2) { /* Mat2 is a transformation matrix (i,j->f(i,j)).... can't scale it because can't scale both sides of -> */ /* normalizes an affine transformation */ /* priority of forms */ /* 1. i' -> i (identity) */ /* 2. i' -> i + constant (uniform) */ /* 3. i' -> constant (broadcast) */ /* 4. i' -> j (permutation) */ /* 5. i' -> j + constant ( ) */ /* 6. i' -> i + j + constant (non-uniform) */ for (k=0; k<Rank; k++) { j = column_index[k]; for (i=0; i<(Mat2->NbRows-1);i++) { /* all but the last row 0...0 1 */ if ((i!=j) && value_notzero_p(Mat2->p[i][j])) { /* Remove dependency of i' on j */ Value a, a1, a1abs, a2, a2abs; value_init(a); value_init(a1); value_init(a2); value_init(a1abs); value_init(a2abs); value_assign(a1,Mat2->p[i][j]); value_absolute(a1abs,a1); value_assign(a2,Mat1->p[k][j]); value_absolute(a2abs,a2); value_gcd(a, a1abs, a2abs); value_divexact(a1, a1, a); value_divexact(a2, a2, a); value_oppose(a1,a1); if (value_one_p(a2)) { Vector_Combine(Mat2->p[i],Mat1->p[k],Mat2->p[i],a2, a1,NbCols); /* Vector_Normalize(Mat2->p[i],NbCols); -- can't do T */ } /* otherwise, can't do it without mult lhs prod (2i,3j->...) */ value_clear(a); value_clear(a1); value_clear(a2); value_clear(a1abs); value_clear(a2abs); } else if ((i==j) && value_zero_p(Mat2->p[i][j])) { /* 'i' does not depend on j */ for (n=j+1; n < (NbCols-1); n++) { if (value_notzero_p(Mat2->p[i][n])) { /* i' depends on some n */ value_set_si(tmp,1); Vector_Combine(Mat2->p[i],Mat1->p[k],Mat2->p[i],tmp, tmp,NbCols); break; } /* if 'i' depends on just a constant, then leave it alone.*/ } } } } /* Check last row of transformation Mat2 */ for (j=0; j<(NbCols-1); j++) if (value_notzero_p(Mat2->p[Mat2->NbRows-1][j])) { errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n"); break; } if (value_notone_p(Mat2->p[Mat2->NbRows-1][NbCols-1])) { errormsg1("GaussSimplify", "corrtrans", "Corrupted transformation\n"); } } value_clear(gcd); value_clear(tmp); free(column_index); return Rank; } /* GaussSimplify */