void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) { int mrows, ncols; int i, j, k; double *volume; double *matrix; extern rational *pivotrow; extern T_LassInt *All_index; extern T_LassInt *Pivot; extern int **p2c; extern rational *A; extern rational * planescopy; extern T_Tree *tree_volumes; extern T_Key key; /* Check for proper number of arguments. */ if (nrhs != 1) { mexErrMsgTxt("One input required."); } else if (nlhs > 1) { mexErrMsgTxt("Too many output arguments"); } /* the input must be a non complex m by 4 matrix */ mrows = mxGetM(prhs[0]); ncols = mxGetN(prhs[0]); if (ncols != 4 || !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0])) { mexErrMsgTxt("Input must be a noncomplex m by 4 double matrix"); } /* Set up the return argument matrix */ plhs[0] = mxCreateDoubleMatrix(1,1, mxREAL); /* The output goes in *volume */ volume = mxGetPr(plhs[0]); /* Get pointer to the right hand side */ matrix = mxGetPr(prhs[0]); /* Set global variables */ G_m = mrows; G_d = ncols - 1; create_hyperplanes (); /* allocates space for hyperplanes */ /* needs to be changed to read data from the array, or use the array(better) */ k=0; for (i = 0; i < G_m; i++) { G_Hyperplanes [i] [G_d] = matrix[k++]; } for (i=0; i < G_m; i++) { G_Hyperplanes [i] [0] = -matrix[k++]; } for (i=0; i < G_m; i++) { G_Hyperplanes [i] [1] = -matrix[k++]; } for (i=0; i < G_m; i++) { G_Hyperplanes [i] [2] = -matrix[k++]; } if (G_Storage > G_d - 3) G_Storage = G_d - 3; /* necessary to prevent memory waste because in the tree arrays of length */ /* G_Storage + 2 are allocated */ pivotrow = (rational *) my_malloc ((G_d + 1) * sizeof (rational)); All_index = (T_LassInt *) my_malloc ((G_m + 1) * sizeof (T_LassInt)); Pivot = (T_LassInt *) my_malloc ((G_d + 1) * sizeof (T_LassInt)); p2c = (int **) my_malloc (G_d * sizeof (int *)); for (i=0; i<G_d; i++){ p2c[i] = (int *) my_malloc (2 * sizeof (int)); } A=compact(); planescopy=compact(); tree_volumes = NULL; create_key (&key, KEY_PLANES_VAR); key.hypervar.hyperplanes [0] = G_m + 1; key.hypervar.variables [0] = G_d + 1; All_index[0]=G_m+2; /* initialization (end mark) */ Pivot[0]=G_m+2; /* initialization (end mark) */ *volume = lass (A, G_m-1, G_d); /* Deallocate memory (didn't work?)*/ free_key (key, KEY_PLANES_VAR); my_free(planescopy, G_m*(G_d+1)*sizeof(rational)); my_free(A, G_m*(G_d+1)*sizeof(rational)); for (i=0; i<G_d; i++){ my_free(p2c[i], 2 * sizeof (int)); } my_free(p2c, G_d * sizeof (int *)); my_free(Pivot, (G_d + 1) * sizeof (T_LassInt)); my_free(All_index,(G_m + 1) * sizeof (T_LassInt)); my_free(pivotrow, (G_d + 1) * sizeof (rational)); free_hyperplanes (); }
static rational lass(rational *A, int LastPlane_, int d) /* A has exact dimension (LastPlane_+1)*(d+1). The function returns the volume; an underscore is appended to LastPlane_ and d */ { rational * redA; /* A reduced by one dimension and constraint */ int i, j; T_LassInt baserow = 0, basecol = 0, col; int dimdiff, row; /* dimension difference */ boolean store_volume; boolean i_balance = FALSE; rational ma, mi, *volume, *realp1, *realp2; int Index_needed; /* Boolean, if index operations are needed */ T_LassInt * Del_index = NULL; /* contains the indices of the deleted planes */ /* test if volume is already known and return it if so */ dimdiff = G_d-d; if ((G_Storage > (dimdiff-2)) && (dimdiff >= 2)) { tree_out (&tree_volumes, &i_balance, key, &volume, &keyfound, KEY_PLANES_VAR); if ((*volume)>=0) { /* this volume has already been computed */ #ifdef STATISTICS Stat_CountRetrieved [d] ++; #endif return (*volume)*scale(dimdiff, keyfound->hypervar.variables, key.hypervar.variables); } (*volume)=0; /* initialize */ store_volume=TRUE; #ifdef STATISTICS Stat_CountStored [d] ++; #endif } else store_volume=FALSE; /* if d==1 compute the volume and give it back */ if (d == 1) { ma=-MAXIMUM; mi= MAXIMUM; for (i=0; i<=LastPlane_; i++,A+=2) { if (*A>EPSILON_LASS) { if ((*(A+1)/ *A)<mi) mi=(*(A+1)/ *A); } else if (*A<-EPSILON_LASS) { if ((*(A+1)/ *A)>ma) ma=*(A+1)/ *A; } else if ((*(A+1))<-(100000*EPSILON_LASS)) return 0; } if ((ma<-.5*MAXIMUM)||(mi>.5*MAXIMUM)) { printf("\nVolume is unbounded!\n"); exit(0); } if ((mi-ma)>EPSILON_LASS) { if (store_volume) (*volume)=mi-ma; return mi-ma; } return 0; } /* if d>1 apply the recursive scheme by fixing constraints. */ Index_needed = (G_Storage>(G_d-d-1)); if (Index_needed){ if (!(Del_index = (T_LassInt *) my_malloc ((LastPlane_ + 2) * sizeof (T_LassInt)))){ fprintf (stderr, "\n***** ERROR/WARNING: Out of memory in 'lass'\n"); exit(0); }; Del_index[0]=G_m+2; /* initialize: mark end */ } ma=0; /* used to sum up the summands */ if (norm_and_clean_constraints(A, &LastPlane_, d, Del_index, Index_needed)!=0) goto label2; /* if appropriate shift polytope */ if (d>=LaShiftLevel) { realp1=A+d; realp2=realp1+LastPlane_*(d+1); j=0; while (realp1<=realp2) { if (fabs(*realp1)<EPSILON_LASS) j++; realp1+=d+1; } if (d-j>=LaShift) shift_P(A, LastPlane_, d); } redA = (rational *) my_malloc (LastPlane_* d*sizeof(rational)); if (redA == NULL) { fprintf (stderr, "\n***** ERROR/WARNING: Out of memory in 'lass.*redA'\n"); exit(0); } #ifdef ReverseLass for (row=LastPlane_; row>=0; row--) { #else for (row=0; row<=LastPlane_; row++) { #endif if (fabs(*(A+row*(d+1)+d))<EPSILON_LASS) continue; /* skip this constraint if b_row == 0 */ if (Index_needed) { baserow=add_reduced_index(row, NULL, All_index); p2c[G_d-d][1] = baserow; add_hypervar (baserow, G_d+1, &key); } memcpy(&pivotrow[0], A+row*(d+1), sizeof(rational)*(d+1)); col=0; /* search for pivot column */ for (i=0; i<d; i++) { #if PIVOTING_LASS == 0 if (fabs(pivotrow[i])>=MIN_PIVOT_LASS) {col=i; break;}; #endif if (fabs(pivotrow[i])>fabs(pivotrow[col])) col=i; }; if (G_Storage>(G_d-d-1)) { basecol=add_reduced_index(col, NULL, Pivot); p2c[G_d-d][0] = basecol; add_hypervar (G_m+1, basecol, &key); } /* copy A onto redA and at the same time perform pivoting */ mi=1.0/pivotrow[col]; for (i=0; i<=d; i++) pivotrow[i]*=mi; realp1=A; realp2=redA; for (i=0; i<=LastPlane_; i++) { if (i==row) { realp1+=d+1; continue; }; mi=*(A+(i*(d+1))+col); for (j=0; j<=d; j++) { if (j==col) { realp1++; continue; }; *realp2=(*realp1)-pivotrow[j]*mi; realp1++; realp2++; }; }; ma+= *(A+row*(d+1)+d)/(d*fabs(*(A+row*(d+1)+col))) *lass(redA, LastPlane_-1, d-1); if (Index_needed) { rm_original_inElAll_index(baserow); delete_hypervar (baserow, G_d+1, &key); } if (G_Storage>(G_d-d-1)) { del_original(basecol, Pivot); delete_hypervar (G_m+1, basecol, &key); } #ifdef verboseFirstLevel if (d==G_d) printf("\nVolume accumulated to iteration %i is %20.12f",row,ma ); #endif }; my_free (redA, LastPlane_* d * sizeof (rational)); label2: if (Index_needed) { del_original_indices(Del_index, All_index); my_free (Del_index, (LastPlane_ + 2) * sizeof (T_LassInt)); }; if (store_volume)(*volume)=ma; return ma; } /****************************************************************************************/ void volume_lasserre_file (rational *volume, char *planesfile) { int i; read_hyperplanes (planesfile); if (G_m > 254) { fprintf (stderr, "\n***** ERROR: Trying to use 'rlass' with more than 254 hyperplanes."); fprintf (stderr, "\nThis restriction can be changed, though. Please contact the authors.\n"); exit (0); } if (G_Storage > G_d - 3) G_Storage = G_d - 3; /* necessary to prevent memory waste because in the tree arrays of length */ /* G_Storage + 2 are allocated */ pivotrow = (rational *) my_malloc ((G_d + 1) * sizeof (rational)); All_index = (T_LassInt *) my_malloc ((G_m + 1) * sizeof (T_LassInt)); Pivot = (T_LassInt *) my_malloc ((G_d + 1) * sizeof (T_LassInt)); p2c = (int **) my_malloc (G_d * sizeof (int *)); for (i=0; i<G_d; i++){ p2c[i] = (int *) my_malloc (2 * sizeof (int)); } A=compact(); planescopy=compact(); tree_volumes = NULL; create_key (&key, KEY_PLANES_VAR); key.hypervar.hyperplanes [0] = G_m + 1; key.hypervar.variables [0] = G_d + 1; All_index[0]=G_m+2; /* initialization (end mark) */ Pivot[0]=G_m+2; /* initialization (end mark) */ #ifdef STATISTICS init_statistics (); #endif *volume = lass (A, G_m-1, G_d); /* free_key (key, KEY_PLANES_VAR); */ }