void Matrix_Extend(Matrix *Mat, unsigned NbRows) { Value *p, **q; int i,j; q = (Value **)realloc(Mat->p, NbRows * sizeof(*q)); if(!q) { errormsg1("Matrix_Extend", "outofmem", "out of memory space"); return; } Mat->p = q; if (Mat->p_Init_size < NbRows * Mat->NbColumns) { p = (Value *)realloc(Mat->p_Init, NbRows * Mat->NbColumns * sizeof(Value)); if(!p) { errormsg1("Matrix_Extend", "outofmem", "out of memory space"); return; } Mat->p_Init = p; Vector_Set(Mat->p_Init + Mat->NbRows*Mat->NbColumns, 0, Mat->p_Init_size - Mat->NbRows*Mat->NbColumns); for (i = Mat->p_Init_size; i < Mat->NbColumns*NbRows; ++i) value_init(Mat->p_Init[i]); Mat->p_Init_size = Mat->NbColumns*NbRows; } else Vector_Set(Mat->p_Init + Mat->NbRows*Mat->NbColumns, 0, (NbRows - Mat->NbRows) * Mat->NbColumns); for (i=0;i<NbRows;i++) { Mat->p[i] = Mat->p_Init + (i * Mat->NbColumns); } Mat->NbRows = NbRows; }
void Matrix_Read_Input(Matrix *Mat) { Value *p; int i,j,n; char *c, s[1024],str[1024]; p = Mat->p_Init; for (i=0;i<Mat->NbRows;i++) { do { c = fgets(s, 1024, stdin); while(isspace(*c) && *c!='\n') ++c; } while(c && (*c =='#' || *c== '\n')); if (!c) { errormsg1( "Matrix_Read", "baddim", "not enough rows" ); break; } for (j=0;j<Mat->NbColumns;j++) { if(!c || *c=='\n' || *c=='#') { errormsg1("Matrix_Read", "baddim", "not enough columns"); break; } if (sscanf(c,"%s%n",str,&n) == 0) { errormsg1( "Matrix_Read", "baddim", "not enough columns" ); break; } value_read(*(p++),str); c += n; } } } /* Matrix_Read_Input */
/* * Allocate space for matrix dimensioned by 'NbRows X NbColumns'. */ Matrix *Matrix_Alloc(unsigned NbRows,unsigned NbColumns) { Matrix *Mat; Value *p, **q; int i,j; Mat=(Matrix *)malloc(sizeof(Matrix)); if(!Mat) { errormsg1("Matrix_Alloc", "outofmem", "out of memory space"); return 0; } Mat->NbRows=NbRows; Mat->NbColumns=NbColumns; if (NbRows==0 || NbColumns==0) { Mat->p = (Value **)0; Mat->p_Init= (Value *)0; Mat->p_Init_size = 0; } else { q = (Value **)malloc(NbRows * sizeof(*q)); if(!q) { free(Mat); errormsg1("Matrix_Alloc", "outofmem", "out of memory space"); return 0; } p = value_alloc(NbRows * NbColumns, &Mat->p_Init_size); if(!p) { free(q); free(Mat); errormsg1("Matrix_Alloc", "outofmem", "out of memory space"); return 0; } Mat->p = q; Mat->p_Init = p; for (i=0;i<NbRows;i++) { *q++ = p; p += NbColumns; } } p = NULL; q = NULL; return Mat; } /* Matrix_Alloc */
/* * Allocate memory space for Vector */ Vector *Vector_Alloc(unsigned length) { int i; Vector *vector; vector = (Vector *)malloc(sizeof(Vector)); if (!vector) { errormsg1("Vector_Alloc", "outofmem", "out of memory space"); return 0; } vector->Size=length; vector->p=(Value *)malloc(length * sizeof(Value)); if (!vector->p) { errormsg1("Vector_Alloc", "outofmem", "out of memory space"); free(vector); return 0; } for(i=0;i<length;i++) value_init(vector->p[i]); return vector; } /* Vector_Alloc */
/*---------------------------------------------------------------------*/ static int exist_points(int pos,Polyhedron *Pol,Value *context) { Value LB, UB, k,tmp; value_init(LB); value_init(UB); value_init(k); value_init(tmp); value_set_si(LB,0); value_set_si(UB,0); /* Problem if UB or LB is INFINITY */ if (lower_upper_bounds(pos,Pol,context,&LB,&UB) !=0) { errormsg1("exist_points", "infdom", "infinite domain"); value_clear(LB); value_clear(UB); value_clear(k); value_clear(tmp); return -1; } value_set_si(context[pos],0); if(value_lt(UB,LB)) { value_clear(LB); value_clear(UB); value_clear(k); value_clear(tmp); return 0; } if (!Pol->next) { value_subtract(tmp,UB,LB); value_increment(tmp,tmp); value_clear(UB); value_clear(LB); value_clear(k); return (value_pos_p(tmp)); } for (value_assign(k,LB);value_le(k,UB);value_increment(k,k)) { /* insert k in context */ value_assign(context[pos],k); if (exist_points(pos+1,Pol->next,context) > 0 ) { value_clear(LB); value_clear(UB); value_clear(k); value_clear(tmp); return 1; } } /* Reset context */ value_set_si(context[pos],0); value_clear(UB); value_clear(LB); value_clear(k); value_clear(tmp); return 0; }
/* * Read the contents of the matrix 'Mat' from standard input. * A '#' in the first column is a comment line */ Matrix *Matrix_Read(void) { Matrix *Mat; unsigned NbRows, NbColumns; char s[1024]; if (fgets(s, 1024, stdin) == NULL) return NULL; while ((*s=='#' || *s=='\n') || (sscanf(s, "%d %d", &NbRows, &NbColumns)<2)) { if (fgets(s, 1024, stdin) == NULL) return NULL; } Mat = Matrix_Alloc(NbRows,NbColumns); if(!Mat) { errormsg1("Matrix_Read", "outofmem", "out of memory space"); return(NULL); } Matrix_Read_Input(Mat); return Mat; } /* Matrix_Read */
/* * Read the contents of a Vector */ Vector *Vector_Read() { Vector *vector; unsigned length; int i; char str[1024]; Value *p; scanf("%d", &length); vector = Vector_Alloc(length); if (!vector) { errormsg1("Vector_Read", "outofmem", "out of memory space"); return 0; } p = vector->p; for (i=0;i<length;i++) { scanf("%s",str); value_read(*(p++),str); } return vector; } /* Vector_Read */
void left_hermite(Matrix *A,Matrix **Hp,Matrix **Qp,Matrix **Up) { Matrix *H, *HT, *Q, *U; int i, j, nc, nr, rank; Value tmp; /* Computes left form: A = HQ , AU = H , T T T T T T using right form A = Q H , U A = H */ nr = A->NbRows; nc = A->NbColumns; /* HT = A transpose */ HT = Matrix_Alloc(nc, nr); if (!HT) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); return; } value_init(tmp); for (i=0; i<nr; i++) for (j=0; j<nc; j++) value_assign(HT->p[j][i],A->p[i][j]); /* U = I */ if (Up) { *Up = U = Matrix_Alloc(nc,nc); if (!U) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(U->p_Init,0,nc*nc); /* zero's */ for (i=0;i<nc;i++) /* with diagonal of 1's */ value_set_si(U->p[i][i],1); } else U=(Matrix *)0; /* Q = I */ if (Qp) { *Qp = Q = Matrix_Alloc(nc, nc); if (!Q) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(Q->p_Init,0,nc*nc); /* zero's */ for (i=0;i<nc;i++) /* with diagonal of 1's */ value_set_si(Q->p[i][i],1); } else Q=(Matrix *)0; rank = hermite(HT,U,Q); /* H = HT transpose */ *Hp = H = Matrix_Alloc(nr,nc); if (!H) { errormsg1("DomLeftHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } for (i=0; i<nr; i++) for (j=0;j<nc;j++) value_assign(H->p[i][j],HT->p[j][i]); Matrix_Free(HT); /* Transpose U */ if (U) { for (i=0; i<nc; i++) { for (j=i+1; j<nc; j++) { value_assign(tmp,U->p[i][j]); value_assign(U->p[i][j],U->p[j][i] ); value_assign(U->p[j][i],tmp); } } } value_clear(tmp); } /* left_hermite */
void right_hermite(Matrix *A,Matrix **Hp,Matrix **Up,Matrix **Qp) { Matrix *H, *Q, *U; int i, j, nr, nc, rank; Value tmp; /* Computes form: A = QH , UA = H */ nc = A->NbColumns; nr = A->NbRows; /* H = A */ *Hp = H = Matrix_Alloc(nr,nc); if (!H) { errormsg1("DomRightHermite", "outofmem", "out of memory space"); return; } /* Initialize all the 'Value' variables */ value_init(tmp); Vector_Copy(A->p_Init,H->p_Init,nr*nc); /* U = I */ if (Up) { *Up = U = Matrix_Alloc(nr, nr); if (!U) { errormsg1("DomRightHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(U->p_Init,0,nr*nr); /* zero's */ for(i=0;i<nr;i++) /* with diagonal of 1's */ value_set_si(U->p[i][i],1); } else U = (Matrix *)0; /* Q = I */ /* Actually I compute Q transpose... its easier */ if (Qp) { *Qp = Q = Matrix_Alloc(nr,nr); if (!Q) { errormsg1("DomRightHermite", "outofmem", "out of memory space"); value_clear(tmp); return; } Vector_Set(Q->p_Init,0,nr*nr); /* zero's */ for (i=0;i<nr;i++) /* with diagonal of 1's */ value_set_si(Q->p[i][i],1); } else Q = (Matrix *)0; rank = hermite(H,U,Q); /* Q is returned transposed */ /* Transpose Q */ if (Q) { for (i=0; i<nr; i++) { for (j=i+1; j<nr; j++) { value_assign(tmp,Q->p[i][j]); value_assign(Q->p[i][j],Q->p[j][i] ); value_assign(Q->p[j][i],tmp); } } } value_clear(tmp); return; } /* right_hermite */
/* * 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 */