/* * Given matrices 'Mat1' and 'Mat2', compute the matrix product and store in * matrix 'Mat3' */ void Matrix_Product(Matrix *Mat1,Matrix *Mat2,Matrix *Mat3) { int Size, i, j, k; unsigned NbRows, NbColumns; Value **q1, **q2, *p1, *p3,sum; NbRows = Mat1->NbRows; NbColumns = Mat2->NbColumns; Size = Mat1->NbColumns; if(Mat2->NbRows!=Size||Mat3->NbRows!=NbRows||Mat3->NbColumns!=NbColumns) { fprintf(stderr, "? Matrix_Product : incompatable matrix dimension\n"); return; } value_init(sum); p3 = Mat3->p_Init; q1 = Mat1->p; q2 = Mat2->p; /* Mat3[i][j] = Sum(Mat1[i][k]*Mat2[k][j] where sum is over k = 1..nbrows */ for (i=0;i<NbRows;i++) { for (j=0;j<NbColumns;j++) { p1 = *(q1+i); value_set_si(sum,0); for (k=0;k<Size;k++) { value_addmul(sum, *p1, *(*(q2+k)+j)); p1++; } value_assign(*p3,sum); p3++; } } value_clear(sum); return; } /* Matrix_Product */
/* * Given a matrix 'Mat' and vector 'p1', compute the matrix-vector product * and store the result in vector 'p2'. */ void Matrix_Vector_Product(Matrix *Mat,Value *p1,Value *p2) { int NbRows, NbColumns, i, j; Value **cm, *q, *cp1, *cp2; NbRows=Mat->NbRows; NbColumns=Mat->NbColumns; cm = Mat->p; cp2 = p2; for(i=0;i<NbRows;i++) { q = *cm++; cp1 = p1; value_multiply(*cp2,*q,*cp1); q++; cp1++; /* *cp2 = *q++ * *cp1++ */ for(j=1;j<NbColumns;j++) { value_addmul(*cp2, *q, *cp1); q++; cp1++; } cp2++; } return; } /* Matrix_Vector_Product */
/* * Return the inner product of the two Vectors 'p1' and 'p2' */ void Inner_Product(Value *p1, Value *p2, unsigned length, Value *ip) { int i; if (length != 0) value_multiply(*ip, p1[0], p2[0]); else value_set_si(*ip, 0); for(i = 1; i < length; i++) value_addmul(*ip, p1[i], p2[i]); } /* Inner_Product */
/* * Given Vectors 'p1' and 'p2', return Vector 'p3' = lambda * p1 + mu * p2. */ void Vector_Combine(Value *p1, Value *p2, Value *p3, Value lambda, Value mu, unsigned length) { Value tmp; int i; value_init(tmp); for (i = 0; i < length; i++) { value_multiply(tmp, lambda, p1[i]); value_addmul(tmp, mu, p2[i]); value_assign(p3[i], tmp); } value_clear(tmp); return; } /* Vector_Combine */
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 vector 'p1' and a matrix 'Mat', compute the vector-matrix product * and store the result in vector 'p2' */ void Vector_Matrix_Product(Value *p1,Matrix *Mat,Value *p2) { int NbRows, NbColumns, i, j; Value **cm, *cp1, *cp2; NbRows=Mat->NbRows; NbColumns=Mat->NbColumns; cp2 = p2; cm = Mat->p; for (j=0;j<NbColumns;j++) { cp1 = p1; value_multiply(*cp2,*(*cm+j),*cp1); cp1++; /* *cp2= *(*cm+j) * *cp1++; */ for (i=1;i<NbRows;i++) { value_addmul(*cp2, *(*(cm+i)+j), *cp1); cp1++; } cp2++; } return; } /* Vector_Matrix_Product */
/* * 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 */