static enum order_sign interval_minmax(Polyhedron *I) { int i; int min = 1; int max = -1; assert(I->Dimension == 1); POL_ENSURE_VERTICES(I); for (i = 0; i < I->NbRays; ++i) { if (value_pos_p(I->Ray[i][1])) max = 1; else if (value_neg_p(I->Ray[i][1])) min = -1; else { if (max < 0) max = 0; if (min > 0) min = 0; } } if (min > 0) return order_gt; if (max < 0) return order_lt; if (min == max) return order_eq; if (max == 0) return order_le; if (min == 0) return order_ge; return order_unknown; }
/* * Reduce a vector by dividing it by GCD and making sure its pos-th * element is positive. */ void Vector_Normalize_Positive(Value *p,int length,int pos) { Value gcd; int i; value_init(gcd); Vector_Gcd(p,length,&gcd); if (value_neg_p(p[pos])) value_oppose(gcd,gcd); if(value_notone_p(gcd)) Vector_AntiScale(p, p, gcd, length); value_clear(gcd); } /* Vector_Normalize_Positive */
enum lp_result PL_polyhedron_opt(Polyhedron *P, Value *obj, Value denom, enum lp_dir dir, Value *opt) { int i; int first = 1; Value val, d; enum lp_result res = lp_empty; POL_ENSURE_VERTICES(P); if (emptyQ(P)) return res; value_init(val); value_init(d); for (i = 0; i < P->NbRays; ++ i) { Inner_Product(P->Ray[i]+1, obj, P->Dimension+1, &val); if (value_zero_p(P->Ray[i][0]) && value_notzero_p(val)) { res = lp_unbounded; break; } if (value_zero_p(P->Ray[i][1+P->Dimension])) { if ((dir == lp_min && value_neg_p(val)) || (dir == lp_max && value_pos_p(val))) { res = lp_unbounded; break; } } else { res = lp_ok; value_multiply(d, denom, P->Ray[i][1+P->Dimension]); if (dir == lp_min) mpz_cdiv_q(val, val, d); else mpz_fdiv_q(val, val, d); if (first || (dir == lp_min ? value_lt(val, *opt) : value_gt(val, *opt))) value_assign(*opt, val); first = 0; } } value_clear(d); value_clear(val); return res; }
int in_domain(Polyhedron *P, Value *list_args) { int col,row; Value v; /* value of the constraint of a row when parameters are instanciated*/ if( !P ) return( 0 ); POL_ENSURE_INEQUALITIES(P); value_init(v); /* P->Constraint constraint matrice of polyhedron P */ for(row=0;row<P->NbConstraints;row++) { value_assign(v,P->Constraint[row][P->Dimension+1]); /*constant part*/ for(col=1;col<P->Dimension+1;col++) { value_addmul(v, P->Constraint[row][col], list_args[col-1]); } if (value_notzero_p(P->Constraint[row][0])) { /*if v is not >=0 then this constraint is not respected */ if (value_neg_p(v)) { value_clear(v); return( in_domain(P->next, list_args) ); } } else { /*if v is not = 0 then this constraint is not respected */ if (value_notzero_p(v)) { value_clear(v); return( in_domain(P->next, list_args) ); } } } /* if not return before this point => all the constraints are respected */ value_clear(v); return 1; } /* in_domain */
/* * 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 */
/* * 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 */
/* INDEX = 1 .... Dimension */ int PolyhedronLTQ (Polyhedron *Pol1,Polyhedron *Pol2,int INDEX, int PDIM, int NbMaxConstrs) { int res, dim, i, j, k; Polyhedron *Q1, *Q2, *Q3, *Q4, *Q; Matrix *Mat; if (Pol1->next || Pol2->next) { errormsg1("PolyhedronLTQ", "compoly", "Can only compare polyhedra"); return 0; } if (Pol1->Dimension != Pol2->Dimension) { errormsg1("PolyhedronLTQ","diffdim","Polyhedra are not same dimension"); return 0; } dim = Pol1->Dimension+2; POL_ENSURE_FACETS(Pol1); POL_ENSURE_VERTICES(Pol1); POL_ENSURE_FACETS(Pol2); POL_ENSURE_VERTICES(Pol2); #ifdef DEBUG fprintf(stdout, "P1\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Pol1); fprintf(stdout, "P2\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Pol2); #endif /* Create the Line to add */ k = Pol1->Dimension-INDEX+1-PDIM; Mat = Matrix_Alloc(k,dim); Vector_Set(Mat->p_Init,0,dim*k); for(j=0,i=INDEX;j<k;i++,j++) value_set_si(Mat->p[j][i],1); Q1 = AddRays(Mat->p[0],k,Pol1,NbMaxConstrs); Q2 = AddRays(Mat->p[0],k,Pol2,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q1\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q1); fprintf(stdout, "Q2\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q2); #endif Matrix_Free(Mat); Q = DomainIntersection(Q1,Q2,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q); #endif Domain_Free(Q1); Domain_Free(Q2); if (emptyQ(Q)) res = 0; /* not comparable */ else { Q1 = DomainIntersection(Pol1,Q,NbMaxConstrs); Q2 = DomainIntersection(Pol2,Q,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q1\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q1); fprintf(stdout, "Q2\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q2); #endif k = Q1->NbConstraints + Q2->NbConstraints; Mat = Matrix_Alloc(k, dim); Vector_Set(Mat->p_Init,0,k*dim); /* First compute surrounding polyhedron */ j=0; for (i=0; i<Q1->NbConstraints; i++) { if ((value_one_p(Q1->Constraint[i][0])) && (value_pos_p(Q1->Constraint[i][INDEX]))) { /* keep Q1's lower bounds */ for (k=0; k<dim; k++) value_assign(Mat->p[j][k],Q1->Constraint[i][k]); j++; } } for (i=0; i<Q2->NbConstraints; i++) { if ((value_one_p(Q2->Constraint[i][0])) && (value_neg_p(Q2->Constraint[i][INDEX]))) { /* and keep Q2's upper bounds */ for (k=0; k<dim; k++) value_assign(Mat->p[j][k],Q2->Constraint[i][k]); j++; } } Q4 = AddConstraints(Mat->p[0], j, Q, NbMaxConstrs); Matrix_Free(Mat); #ifdef debug fprintf(stderr, "Q4 surrounding polyhedron\n"); Polyhderon_Print(stderr,P_VALUE_FMT, Q4); #endif /* if surrounding polyhedron is empty, D1>D2 */ if (emptyQ(Q4)) { res = 1; #ifdef debug fprintf(stderr, "Surrounding polyhedron is empty\n"); #endif goto LTQdone2; } /* Test if Q1 < Q2 */ /* Build a constraint array for >= Q1 and <= Q2 */ Mat = Matrix_Alloc(2,dim); Vector_Set(Mat->p_Init,0,2*dim); /* Choose a contraint from Q1 */ for (i=0; i<Q1->NbConstraints; i++) { if (value_zero_p(Q1->Constraint[i][0])) { /* Equality */ if (value_zero_p(Q1->Constraint[i][INDEX])) { /* Ignore side constraint (they are in Q) */ continue; } else if (value_neg_p(Q1->Constraint[i][INDEX])) { /* copy -constraint to Mat */ value_set_si(Mat->p[0][0],1); for (k=1; k<dim; k++) value_oppose(Mat->p[0][k],Q1->Constraint[i][k]); } else { /* Copy constraint to Mat */ value_set_si(Mat->p[0][0],1); for (k=1; k<dim; k++) value_assign(Mat->p[0][k],Q1->Constraint[i][k]); } } else if(value_neg_p(Q1->Constraint[i][INDEX])) { /* Upper bound -- make a lower bound from it */ value_set_si(Mat->p[0][0],1); for (k=1; k<dim; k++) value_oppose(Mat->p[0][k],Q1->Constraint[i][k]); } else { /* Lower or side bound -- ignore it */ continue; } /* Choose a constraint from Q2 */ for (j=0; j<Q2->NbConstraints; j++) { if (value_zero_p(Q2->Constraint[j][0])) { /* equality */ if (value_zero_p(Q2->Constraint[j][INDEX])) { /* Ignore side constraint (they are in Q) */ continue; } else if (value_pos_p(Q2->Constraint[j][INDEX])) { /* Copy -constraint to Mat */ value_set_si(Mat->p[1][0],1); for (k=1; k<dim; k++) value_oppose(Mat->p[1][k],Q2->Constraint[j][k]); } else { /* Copy constraint to Mat */ value_set_si(Mat->p[1][0],1); for (k=1; k<dim; k++) value_assign(Mat->p[1][k],Q2->Constraint[j][k]); }; } else if (value_pos_p(Q2->Constraint[j][INDEX])) { /* Lower bound -- make an upper bound from it */ value_set_si(Mat->p[1][0],1); for(k=1;k<dim;k++) value_oppose(Mat->p[1][k],Q2->Constraint[j][k]); } else { /* Upper or side bound -- ignore it */ continue; }; #ifdef DEBUG fprintf(stdout, "i=%d j=%d M=\n", i+1, j+1); Matrix_Print(stdout,P_VALUE_FMT,Mat); #endif /* Add Mat to Q and see if anything is made */ Q3 = AddConstraints(Mat->p[0],2,Q,NbMaxConstrs); #ifdef DEBUG fprintf(stdout, "Q3\n"); Polyhedron_Print(stdout,P_VALUE_FMT,Q3); #endif if (!emptyQ(Q3)) { Domain_Free(Q3); #ifdef DEBUG fprintf(stdout, "not empty\n"); #endif res = -1; goto LTQdone; } #ifdef DEBUG fprintf(stdout,"empty\n"); #endif Domain_Free(Q3); } /* end for j */ } /* end for i */ res = 1; LTQdone: Matrix_Free(Mat); LTQdone2: Domain_Free(Q4); Domain_Free(Q1); Domain_Free(Q2); } Domain_Free(Q); #ifdef DEBUG fprintf(stdout, "res = %d\n", res); #endif return res; } /* PolyhedronLTQ */