/** * Eliminate the columns corresponding to a list of eliminated parameters. * @param M the constraints matrix whose columns are to be removed * @param nbVars an offset to be added to the ranks of the variables to be * removed * @param elimParms the list of ranks of the variables to be removed * @param newM (output) the matrix without the removed columns */ void Constraints_removeElimCols(Matrix * M, unsigned int nbVars, unsigned int *elimParms, Matrix ** newM) { unsigned int i, j, k; if (elimParms[0]==0) { Matrix_clone(M, newM); return; } if ((*newM)==NULL) { (*newM) = Matrix_Alloc(M->NbRows, M->NbColumns - elimParms[0]); } else { assert ((*newM)->NbColumns==M->NbColumns - elimParms[0]); } for (i=0; i< M->NbRows; i++) { value_assign((*newM)->p[i][0], M->p[i][0]); /* kind of cstr */ k=0; Vector_Copy(&(M->p[i][1]), &((*newM)->p[i][1]), nbVars); for (j=0; j< M->NbColumns-2-nbVars; j++) { if (j!=elimParms[k+1]) { value_assign((*newM)->p[i][j-k+nbVars+1], M->p[i][j+nbVars+1]); } else { k++; } } value_assign((*newM)->p[i][(*newM)->NbColumns-1], M->p[i][M->NbColumns-1]); /* cst part */ } } /* Constraints_removeElimCols */
static double compute_enode(enode *p, Value *list_args) { int i; Value m, param; double res=0.0; if (!p) return(0.); value_init(m); value_init(param); if (p->type == polynomial) { if (p->size > 1) value_assign(param,list_args[p->pos-1]); /* Compute the polynomial using Horner's rule */ for (i=p->size-1;i>0;i--) { res +=compute_evalue(&p->arr[i],list_args); res *=VALUE_TO_DOUBLE(param); } res +=compute_evalue(&p->arr[0],list_args); } else if (p->type == periodic) { value_assign(m,list_args[p->pos-1]); /* Choose the right element of the periodic */ value_set_si(param,p->size); value_pmodulus(m,m,param); res = compute_evalue(&p->arr[VALUE_TO_INT(m)],list_args); } value_clear(m); value_clear(param); return res; } /* compute_enode */
/*---------------------------------------------------------------------*/ 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; }
/* * Return the component of 'p' with minimum non-zero absolute value. 'index' * points to the component index that has the minimum value. If no such value * and index is found, Value 1 is returned. */ void Vector_Min_Not_Zero(Value *p,unsigned length,int *index,Value *min) { Value aux; int i; i = First_Non_Zero(p, length); if (i == -1) { value_set_si(*min,1); return; } *index = i; value_absolute(*min, p[i]); value_init(aux); for (i = i+1; i < length; i++) { if (value_zero_p(p[i])) continue; value_absolute(aux, p[i]); if (value_lt(aux,*min)) { value_assign(*min,aux); *index = i; } } value_clear(aux); } /* Vector_Min_Not_Zero */
/* * 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 */
/** * Computes the overall period of the variables I for (MI) mod |d|, where M is * a matrix and |d| a vector. Produce a diagonal matrix S = (s_k) where s_k is * the overall period of i_k * @param M the set of affine functions of I (row-vectors) * @param d the column-vector representing the modulos */ Matrix * affine_periods(Matrix * M, Matrix * d) { Matrix * S; unsigned int i,j; Value tmp; Value * periods = (Value *)malloc(sizeof(Value) * M->NbColumns); value_init(tmp); for(i=0; i< M->NbColumns; i++) { value_init(periods[i]); value_set_si(periods[i], 1); } for (i=0; i<M->NbRows; i++) { for (j=0; j< M->NbColumns; j++) { value_gcd(tmp, d->p[i][0], M->p[i][j]); value_divexact(tmp, d->p[i][0], tmp); value_lcm(periods[j], periods[j], tmp); } } value_clear(tmp); /* 2- build S */ S = Matrix_Alloc(M->NbColumns, M->NbColumns); for (i=0; i< M->NbColumns; i++) for (j=0; j< M->NbColumns; j++) if (i==j) value_assign(S->p[i][j],periods[j]); else value_set_si(S->p[i][j], 0); /* 3- clean up */ for(i=0; i< M->NbColumns; i++) value_clear(periods[i]); free(periods); return S; } /* affine_periods */
/* * Compute GCD of 'a' and 'b' */ void Gcd(Value a,Value b,Value *result) { Value acopy, bcopy; value_init(acopy); value_init(bcopy); value_assign(acopy,a); value_assign(bcopy,b); while(value_notzero_p(acopy)) { value_modulus(*result,bcopy,acopy); value_assign(bcopy,acopy); value_assign(acopy,*result); } value_absolute(*result,bcopy); value_clear(acopy); value_clear(bcopy); } /* Gcd */
/** * Eliminates certain parameters from a vector of values for parameters * @param origParms the initial vector of values of parameters * @param elimParms the list of parameters to be eliminated in the vector * @param newParms the vector of values without the eliminated ones. */ void valuesWithoutElim(Matrix * origParms, unsigned int * elimParms, Matrix ** newParms) { unsigned int i, j=0; if (*newParms==NULL) { *newParms = Matrix_Alloc(1, origParms->NbColumns-elimParms[0]); } /* else assume enough space is allocated */ if (elimParms[0] ==0) { for (i=0; i< origParms->NbColumns; i++) { value_assign((*newParms)->p[0][i], origParms->p[0][i]); } } for (i=0; i< origParms->NbColumns; i++) { if (i!=elimParms[j+1]) { value_assign((*newParms)->p[0][i-j], origParms->p[0][i]); } else { j++; } } }/* valuesWithoutElim */
/** * Computes the validity lattice of a set of equalities. I.e., the lattice * induced on the last <tt>b</tt> variables by the equalities involving the * first <tt>a</tt> integer existential variables. The submatrix of Eqs that * concerns only the existential variables (so the first a columns) is assumed * to be full-row rank. * @param Eqs the equalities * @param a the number of existential integer variables, placed as first * variables * @param vl the (returned) validity lattice, in homogeneous form. It is * allocated if initially set to null, or reused if already allocated. */ void Equalities_validityLattice(Matrix * Eqs, int a, Matrix** vl) { unsigned int b = Eqs->NbColumns-2-a; unsigned int r = Eqs->NbRows; Matrix * A=NULL, * B=NULL, *I = NULL, *Lb=NULL, *sol=NULL; Matrix *H, *U, *Q; unsigned int i; if (dbgCompParm) { printf("Computing validity lattice induced by the %d first variables of:" ,a); show_matrix(Eqs); } if (b==0) { ensureMatrix((*vl), 1, 1); value_set_si((*vl)->p[0][0], 1); return; } /* 1- check that there is an integer solution to the equalities */ /* OPT: could change integerSolution's profile to allocate or not*/ Equalities_integerSolution(Eqs, &sol); /* if there is no integer solution, there is no validity lattice */ if (sol==NULL) { if ((*vl)!=NULL) Matrix_Free(*vl); return; } Matrix_subMatrix(Eqs, 0, 1, r, 1+a, &A); Matrix_subMatrix(Eqs, 0, 1+a, r, 1+a+b, &B); linearInter(A, B, &I, &Lb); Matrix_Free(A); Matrix_Free(B); Matrix_Free(I); if (dbgCompParm) { show_matrix(Lb); } /* 2- The linear part of the validity lattice is the left HNF of Lb */ left_hermite(Lb, &H, &Q, &U); Matrix_Free(Lb); Matrix_Free(Q); Matrix_Free(U); /* 3- build the validity lattice */ ensureMatrix((*vl), b+1, b+1); Matrix_copySubMatrix(H, 0, 0, b, b, (*vl), 0,0); Matrix_Free(H); for (i=0; i< b; i++) { value_assign((*vl)->p[i][b], sol->p[0][a+i]); } Matrix_Free(sol); Vector_Set((*vl)->p[b],0, b); value_set_si((*vl)->p[b][b], 1); } /* validityLattice */
static int wrap_value_assign (char *a) { struct gdb_wrapper_arguments *args = (struct gdb_wrapper_arguments *) a; value_ptr val1, val2; val1 = (value_ptr) (args)->args[0].pointer; val2 = (value_ptr) (args)->args[1].pointer; (args)->result.pointer = value_assign (val1, val2); return 1; }
/* * Reduce 'p' by operating binary function on its components successively */ void Vector_Reduce(Value *p,unsigned length,void(*f)(Value,Value *),Value *r) { Value *cp; int i; cp = p; value_assign(*r,*cp); for(i=1;i<length;i++) { cp++; (*f)(*cp,r); } } /* Vector_Reduce */
/* * Return the maximum of the components of 'p' */ void Vector_Max(Value *p,unsigned length, Value *max) { Value *cp; int i; cp=p; value_assign(*max,*cp); cp++; for (i=1;i<length;i++) { value_maximum(*max,*max,*cp); cp++; } } /* Vector_Max */
/* * Copy Vector 'p1' to Vector 'p2' */ void Vector_Copy(Value *p1,Value *p2,unsigned length) { int i; Value *cp1, *cp2; cp1 = p1; cp2 = p2; for(i=0;i<length;i++) value_assign(*cp2++,*cp1++); return; }
/* * Return the minimum of the components of Vector 'p' */ void Vector_Min(Value *p,unsigned length,Value *min) { Value *cp; int i; cp=p; value_assign(*min,*cp); cp++; for (i=1;i<length;i++) { value_minimum(*min,*min,*cp); cp++; } return; } /* Vector_Min */
/* * Given vectors 'p1', 'p2', and a pointer to a function returning 'Value type, * compute p3[i] = f(p1[i],p2[i]). */ void Vector_Map(Value *p1,Value *p2,Value *p3,unsigned length, Value *(*f)(Value,Value)) { Value *cp1, *cp2, *cp3; int i; cp1=p1; cp2=p2; cp3=p3; for(i=0;i<length;i++) { value_assign(*cp3,*(*f)(*cp1, *cp2)); cp1++; cp2++; cp3++; } return; } /* Vector_Map */
/* * 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 */
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; }
/** * Given an integer matrix B with m rows and integer m-vectors C and d, * computes the basis of the integer solutions to (BN+C) mod d = 0 (1). * This is an affine lattice (G): (N 1)^T= G(N' 1)^T, forall N' in Z^b. * If there is no solution, returns NULL. * @param B B, a (m x b) matrix * @param C C, a (m x 1) integer matrix * @param d d, a (1 x m) integer matrix * @param imb the affine (b+1)x(b+1) basis of solutions, in the homogeneous * form. Allocated if initially set to NULL, reused if not. */ void Equalities_intModBasis(Matrix * B, Matrix * C, Matrix * d, Matrix ** imb) { int b = B->NbColumns; /* FIXME: treat the case d=0 as a regular equality B_kN+C_k = 0: */ /* OPT: could keep only equalities for which d>1 */ int nbEqs = B->NbRows; unsigned int i; /* 1- buid the problem DI+BN+C = 0 */ Matrix * eqs = Matrix_Alloc(nbEqs, nbEqs+b+1); for (i=0; i< nbEqs; i++) { value_assign(eqs->p[i][i], d->p[0][i]); } Matrix_copySubMatrix(B, 0, 0, nbEqs, b, eqs, 0, nbEqs); Matrix_copySubMatrix(C, 0, 0, nbEqs, 1, eqs, 0, nbEqs+b); /* 2- the solution is the validity lattice of the equalities */ Equalities_validityLattice(eqs, nbEqs, imb); Matrix_Free(eqs); } /* Equalities_intModBasis */
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 */
void ppl_set_coef_gmp (ppl_Linear_Expression_t e, ppl_dimension_type i, Value x) { Value v0, v1; ppl_Coefficient_t c; value_init (v0); value_init (v1); ppl_new_Coefficient (&c); ppl_Linear_Expression_coefficient (e, i, c); ppl_Coefficient_to_mpz_t (c, v1); value_oppose (v1, v1); value_assign (v0, x); value_addto (v0, v0, v1); ppl_assign_Coefficient_from_mpz_t (c, v0); ppl_Linear_Expression_add_to_coefficient (e, i, c); value_clear (v0); value_clear (v1); ppl_delete_Coefficient (c); }
void ppl_set_inhomogeneous_gmp (ppl_Linear_Expression_t e, Value x) { Value v0, v1; ppl_Coefficient_t c; value_init (v0); value_init (v1); ppl_new_Coefficient (&c); ppl_Linear_Expression_inhomogeneous_term (e, c); ppl_Coefficient_to_mpz_t (c, v1); value_oppose (v1, v1); value_assign (v0, x); value_addto (v0, v0, v1); ppl_assign_Coefficient_from_mpz_t (c, v0); ppl_Linear_Expression_add_to_inhomogeneous (e, c); value_clear (v0); value_clear (v1); ppl_delete_Coefficient (c); }
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 */
/* Compute integer hull of truncated linear cone C, i.e., of C with * the origin removed. * Here, we do this by first computing the Hilbert basis of C * and then discarding elements from this basis that are rational * overconvex combinations of other elements in the basis. */ Matrix *Cone_Hilbert_Integer_Hull(Polyhedron *C, struct barvinok_options *options) { int i, j, k; Matrix *hilbert = Cone_Hilbert_Basis(C, options->MaxRays); Matrix *rays, *hull; unsigned dim = C->Dimension; Value tmp; unsigned MaxRays = options->MaxRays; /* When checking for redundant points below, we want to * check if there are any _rational_ solutions. */ POL_UNSET(options->MaxRays, POL_INTEGER); POL_ENSURE_VERTICES(C); rays = Matrix_Alloc(C->NbRays-1, C->Dimension); for (i = 0, j = 0; i < C->NbRays; ++i) { if (value_notzero_p(C->Ray[i][1+C->Dimension])) continue; Vector_Copy(C->Ray[i]+1, rays->p[j++], C->Dimension); } /* We only sort the pointers into the big Value array */ qsort(rays->p, rays->NbRows, sizeof(Value *), lex_cmp); qsort(hilbert->p, hilbert->NbRows, sizeof(Value *), lex_cmp); /* Remove rays from Hilbert basis */ for (i = 0, j = 0, k = 0; i < hilbert->NbRows && j < rays->NbRows; ++i) { if (Vector_Equal(hilbert->p[i], rays->p[j], C->Dimension)) ++j; else hilbert->p[k++] = hilbert->p[i]; } hilbert->NbRows = k; /* Now remove points that are overconvex combinations of other points */ value_init(tmp); for (i = 0; hilbert->NbRows > 1 && i < hilbert->NbRows; ++i) { Matrix *LP; Vector *obj; int nray = rays->NbRows; int npoint = hilbert->NbRows; enum lp_result result; LP = Matrix_Alloc(dim + 1 + nray + (npoint-1), 2 + nray + (npoint-1)); for (j = 0; j < dim; ++j) { for (k = 0; k < nray; ++k) value_assign(LP->p[j][k+1], rays->p[k][j]); for (k = 0; k < npoint; ++k) { if (k == i) value_oppose(LP->p[j][1+nray+npoint-1], hilbert->p[k][j]); else value_assign(LP->p[j][1+nray+k-(k>i)], hilbert->p[k][j]); } } value_set_si(LP->p[dim][0], 1); for (k = 0; k < nray+npoint-1; ++k) value_set_si(LP->p[dim][1+k], 1); value_set_si(LP->p[dim][LP->NbColumns-1], -1); for (k = 0; k < LP->NbColumns-2; ++k) { value_set_si(LP->p[dim+1+k][0], 1); value_set_si(LP->p[dim+1+k][1+k], 1); } /* Somewhat arbitrary objective function. */ obj = Vector_Alloc(LP->NbColumns-1); value_set_si(obj->p[0], 1); value_set_si(obj->p[obj->Size-1], 1); result = constraints_opt(LP, obj->p, obj->p[0], lp_min, &tmp, options); /* If the LP is not empty, the point can be discarded */ if (result != lp_empty) { hilbert->NbRows--; if (i < hilbert->NbRows) hilbert->p[i] = hilbert->p[hilbert->NbRows]; --i; } Matrix_Free(LP); Vector_Free(obj); } value_clear(tmp); hull = Matrix_Alloc(rays->NbRows + hilbert->NbRows, dim+1); for (i = 0; i < rays->NbRows; ++i) { Vector_Copy(rays->p[i], hull->p[i], dim); value_set_si(hull->p[i][dim], 1); } for (i = 0; i < hilbert->NbRows; ++i) { Vector_Copy(hilbert->p[i], hull->p[rays->NbRows+i], dim); value_set_si(hull->p[rays->NbRows+i][dim], 1); } Matrix_Free(rays); Matrix_Free(hilbert); options->MaxRays = MaxRays; return hull; }
/* * Return the Z-polyhderon 'Zpol' in canonical form: 'Result' (for the Z-poly- * hedron in canonical form) and Basis 'Basis' (for the basis with respect to * which 'Result' is in canonical form. */ void CanonicalForm(ZPolyhedron *Zpol,ZPolyhedron **Result,Matrix **Basis) { Matrix *B1 = NULL, *B2=NULL, *T1 , *B2inv; int i, l1, l2; Value tmp; Polyhedron *Image, *ImageP; Matrix *H, *U, *temp, *Hprime, *Uprime, *T2; #ifdef DOMDEBUG FILE *fp; fp = fopen("_debug", "a"); fprintf(fp,"\nEntered CANONICALFORM\n"); fclose(fp); #endif if(isEmptyZPolyhedron (Zpol)) { Basis[0] = Identity(Zpol->Lat->NbRows); Result[0] = ZDomain_Copy (Zpol); return ; } value_init(tmp); l1 = FindHermiteBasisofDomain(Zpol->P,&B1); Image = DomainImage (Zpol->P,(Matrix *)Zpol->Lat,MAXNOOFRAYS); l2 = FindHermiteBasisofDomain(Image,&B2); if (l1 != l2) fprintf(stderr,"In CNF : Something wrong with the Input Zpolyhedra \n"); B2inv = Matrix_Alloc(B2->NbRows, B2->NbColumns); temp = Matrix_Copy(B2); Matrix_Inverse(temp,B2inv); Matrix_Free(temp); temp = Matrix_Alloc(B2inv->NbRows,Zpol->Lat->NbColumns); T1 = Matrix_Alloc(temp->NbRows,B1->NbColumns); Matrix_Product(B2inv,(Matrix *)Zpol->Lat,temp); Matrix_Product(temp,B1,T1); Matrix_Free(temp); T2 = ChangeLatticeDimension(T1,l1); temp = ChangeLatticeDimension(T2,T2->NbRows+1); /* Adding the affine part */ for(i = 0; i < l1; i ++) value_assign(temp->p[i][temp->NbColumns-1],T1->p[i][T1->NbColumns-1]); AffineHermite(temp,&H,&U); Hprime = ChangeLatticeDimension(H,Zpol->Lat->NbRows); /* Exchanging the Affine part */ for(i = 0; i < l1; i ++) { value_assign(tmp,Hprime->p[i][Hprime->NbColumns-1]); value_assign(Hprime->p[i][Hprime->NbColumns-1],Hprime->p[i][H->NbColumns-1]); value_assign(Hprime->p[i][H->NbColumns-1],tmp); } Uprime = ChangeLatticeDimension(U,Zpol->Lat->NbRows); /* Exchanging the Affine part */ for (i = 0;i < l1; i++) { value_assign(tmp,Uprime->p[i][Uprime->NbColumns-1]); value_assign(Uprime->p[i][Uprime->NbColumns-1],Uprime->p[i][U->NbColumns-1]); value_assign(Uprime->p[i][U->NbColumns-1],tmp); } Polyhedron_Free (Image); Matrix_Free (B2inv); B2inv = Matrix_Alloc(B1->NbRows, B1->NbColumns); Matrix_Inverse(B1,B2inv); ImageP = DomainImage(Zpol->P, B2inv, MAXNOOFRAYS); Matrix_Free(B2inv); Image = DomainImage(ImageP, Uprime, MAXNOOFRAYS); Domain_Free(ImageP); Result[0] = ZPolyhedron_Alloc(Hprime, Image); Basis[0] = Matrix_Copy(B2); /* Free the variables */ Polyhedron_Free (Image); Matrix_Free (B1); Matrix_Free (B2); Matrix_Free (temp); Matrix_Free (T1); Matrix_Free (T2); Matrix_Free (H); Matrix_Free (U); Matrix_Free (Hprime); Matrix_Free (Uprime); value_clear(tmp); return; } /* CanonicalForm */
/* * 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 */
/** * Eliminates all the equalities in a set of constraints and returns the set of * constraints defining a full-dimensional polyhedron, such that there is a * bijection between integer points of the original polyhedron and these of the * resulting (projected) polyhedron). * If VL is set to NULL, this funciton allocates it. Else, it assumes that * (*VL) points to a matrix of the right size. * <p> The following things are done: * <ol> * <li> remove equalities involving only parameters, and remove as many * parameters as there are such equalities. From that, the list of * eliminated parameters <i>elimParms</i> is built. * <li> remove equalities that involve variables. This requires a compression * of the parameters and of the other variables that are not eliminated. * The affine compresson is represented by matrix VL (for <i>validity * lattice</i>) and is such that (N I 1)^T = VL.(N' I' 1), where N', I' * are integer (they are the parameters and variables after compression). *</ol> *</p> */ void Constraints_fullDimensionize(Matrix ** M, Matrix ** C, Matrix ** VL, Matrix ** Eqs, Matrix ** ParmEqs, unsigned int ** elimVars, unsigned int ** elimParms, int maxRays) { unsigned int i, j; Matrix * A=NULL, *B=NULL; Matrix * Ineqs=NULL; unsigned int nbVars = (*M)->NbColumns - (*C)->NbColumns; unsigned int nbParms; int nbElimVars; Matrix * fullDim = NULL; /* variables for permutations */ unsigned int * permutation; Matrix * permutedEqs=NULL, * permutedIneqs=NULL; /* 1- Eliminate the equalities involving only parameters. */ (*ParmEqs) = Constraints_removeParmEqs(M, C, 0, elimParms); /* if the polyehdron is empty, return now. */ if ((*M)->NbColumns==0) return; /* eliminate the columns corresponding to the eliminated parameters */ if (elimParms[0]!=0) { Constraints_removeElimCols(*M, nbVars, (*elimParms), &A); Matrix_Free(*M); (*M) = A; Constraints_removeElimCols(*C, 0, (*elimParms), &B); Matrix_Free(*C); (*C) = B; if (dbgCompParm) { printf("After false parameter elimination: \n"); show_matrix(*M); show_matrix(*C); } } nbParms = (*C)->NbColumns-2; /* 2- Eliminate the equalities involving variables */ /* a- extract the (remaining) equalities from the poyhedron */ split_constraints((*M), Eqs, &Ineqs); nbElimVars = (*Eqs)->NbRows; /* if the polyhedron is already full-dimensional, return */ if ((*Eqs)->NbRows==0) { Matrix_identity(nbParms+1, VL); return; } /* b- choose variables to be eliminated */ permutation = find_a_permutation((*Eqs), nbParms); if (dbgCompParm) { printf("Permuting the vars/parms this way: [ "); for (i=0; i< (*Eqs)->NbColumns-2; i++) { printf("%d ", permutation[i]); } printf("]\n"); } Constraints_permute((*Eqs), permutation, &permutedEqs); Equalities_validityLattice(permutedEqs, (*Eqs)->NbRows, VL); if (dbgCompParm) { printf("Validity lattice: "); show_matrix(*VL); } Constraints_compressLastVars(permutedEqs, (*VL)); Constraints_permute(Ineqs, permutation, &permutedIneqs); if (dbgCompParmMore) { show_matrix(permutedIneqs); show_matrix(permutedEqs); } Matrix_Free(*Eqs); Matrix_Free(Ineqs); Constraints_compressLastVars(permutedIneqs, (*VL)); if (dbgCompParm) { printf("After compression: "); show_matrix(permutedIneqs); } /* c- eliminate the first variables */ assert(Constraints_eliminateFirstVars(permutedEqs, permutedIneqs)); if (dbgCompParmMore) { printf("After elimination of the variables: "); show_matrix(permutedIneqs); } /* d- get rid of the first (zero) columns, which are now useless, and put the parameters back at the end */ fullDim = Matrix_Alloc(permutedIneqs->NbRows, permutedIneqs->NbColumns-nbElimVars); for (i=0; i< permutedIneqs->NbRows; i++) { value_set_si(fullDim->p[i][0], 1); for (j=0; j< nbParms; j++) { value_assign(fullDim->p[i][j+fullDim->NbColumns-nbParms-1], permutedIneqs->p[i][j+nbElimVars+1]); } for (j=0; j< permutedIneqs->NbColumns-nbParms-2-nbElimVars; j++) { value_assign(fullDim->p[i][j+1], permutedIneqs->p[i][nbElimVars+nbParms+j+1]); } value_assign(fullDim->p[i][fullDim->NbColumns-1], permutedIneqs->p[i][permutedIneqs->NbColumns-1]); } Matrix_Free(permutedIneqs); } /* Constraints_fullDimensionize */
/* * 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 */
/* * 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 */
/** * Given a matrix with m parameterized equations, compress the nb_parms * parameters and n-m variables so that m variables are integer, and transform * the variable space into a n-m space by eliminating the m variables (using * the equalities) the variables to be eliminated are chosen automatically by * the function. * <b>Deprecated.</b> Try to use Constraints_fullDimensionize instead. * @param M the constraints * @param the number of parameters * @param validityLattice the the integer lattice underlying the integer * solutions. */ Matrix * full_dimensionize(Matrix const * M, int nbParms, Matrix ** validityLattice) { Matrix * Eqs, * Ineqs; Matrix * permutedEqs, * permutedIneqs; Matrix * Full_Dim; Matrix * WVL; /* The Whole Validity Lattice (vars+parms) */ unsigned int i,j; int nbElimVars; unsigned int * permutation, * permutationInv; /* 0- Split the equalities and inequalities from each other */ split_constraints(M, &Eqs, &Ineqs); /* 1- if the polyhedron is already full-dimensional, return it */ if (Eqs->NbRows==0) { Matrix_Free(Eqs); (*validityLattice) = Identity_Matrix(nbParms+1); return Ineqs; } nbElimVars = Eqs->NbRows; /* 2- put the vars to be eliminated at the first positions, and compress the other vars/parms -> [ variables to eliminate / parameters / variables to keep ] */ permutation = find_a_permutation(Eqs, nbParms); if (dbgCompParm) { printf("Permuting the vars/parms this way: [ "); for (i=0; i< Eqs->NbColumns; i++) { printf("%d ", permutation[i]); } printf("]\n"); } permutedEqs = mpolyhedron_permute(Eqs, permutation); WVL = compress_parms(permutedEqs, Eqs->NbColumns-2-Eqs->NbRows); if (dbgCompParm) { printf("Whole validity lattice: "); show_matrix(WVL); } mpolyhedron_compress_last_vars(permutedEqs, WVL); permutedIneqs = mpolyhedron_permute(Ineqs, permutation); if (dbgCompParm) { show_matrix(permutedEqs); } Matrix_Free(Eqs); Matrix_Free(Ineqs); mpolyhedron_compress_last_vars(permutedIneqs, WVL); if (dbgCompParm) { printf("After compression: "); show_matrix(permutedIneqs); } /* 3- eliminate the first variables */ if (!mpolyhedron_eliminate_first_variables(permutedEqs, permutedIneqs)) { fprintf(stderr,"full-dimensionize > variable elimination failed. \n"); return NULL; } if (dbgCompParm) { printf("After elimination of the variables: "); show_matrix(permutedIneqs); } /* 4- get rid of the first (zero) columns, which are now useless, and put the parameters back at the end */ Full_Dim = Matrix_Alloc(permutedIneqs->NbRows, permutedIneqs->NbColumns-nbElimVars); for (i=0; i< permutedIneqs->NbRows; i++) { value_set_si(Full_Dim->p[i][0], 1); for (j=0; j< nbParms; j++) value_assign(Full_Dim->p[i][j+Full_Dim->NbColumns-nbParms-1], permutedIneqs->p[i][j+nbElimVars+1]); for (j=0; j< permutedIneqs->NbColumns-nbParms-2-nbElimVars; j++) value_assign(Full_Dim->p[i][j+1], permutedIneqs->p[i][nbElimVars+nbParms+j+1]); value_assign(Full_Dim->p[i][Full_Dim->NbColumns-1], permutedIneqs->p[i][permutedIneqs->NbColumns-1]); } Matrix_Free(permutedIneqs); /* 5- Keep only the the validity lattice restricted to the parameters */ *validityLattice = Matrix_Alloc(nbParms+1, nbParms+1); for (i=0; i< nbParms; i++) { for (j=0; j< nbParms; j++) value_assign((*validityLattice)->p[i][j], WVL->p[i][j]); value_assign((*validityLattice)->p[i][nbParms], WVL->p[i][WVL->NbColumns-1]); } for (j=0; j< nbParms; j++) value_set_si((*validityLattice)->p[nbParms][j], 0); value_assign((*validityLattice)->p[nbParms][nbParms], WVL->p[WVL->NbColumns-1][WVL->NbColumns-1]); /* 6- Clean up */ Matrix_Free(WVL); return Full_Dim; } /* full_dimensionize */
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 */