00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <math.h>
00025 #include <string.h>
00026 #include "volume_planes.h"
00027
00028 class VINCI_Lass
00029 {
00030 public:
00031
00033 enum {G_d=3};
00034
00036 enum {MAX_G_m=20};
00037
00039 typedef double rational;
00040
00041 private:
00042
00043 #define MIN_PIVOT_LASS 0.1
00044 #define EPSILON 1e-10
00045
00046 #define MAXIMUM 1.0e150
00047 #define EPSILON_LASS EPSILON
00048 #define EPS1 EPSILON
00049 #define EPS_NORM EPSILON
00050 #define LaShiftLevel 0
00051 #define LaShift 1
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062 rational planescopy[MAX_G_m * (G_d+1)];
00063
00064
00065
00066
00067
00068 template <int d>
00069 void rm_constraint(rational* A, int *LastPlane_, int rm_index)
00070
00071
00072 { rational *p1, *p2;
00073 int i;
00074
00075 p1=A+rm_index*(d+1);
00076 p2=A+(rm_index+1)*(d+1);
00077 for (i=0; i<(((*LastPlane_)-rm_index)*(d+1)); i++) {
00078 *p1=*p2;
00079 p1++;
00080 p2++;
00081 };
00082 (*LastPlane_)--;
00083 }
00084
00085
00086
00087
00088
00089
00090 bool notInPivot(int * pivot, int col, int i)
00091 { int h;
00092 for (h=0;h<col;h++)
00093 if (pivot[h]==i) return false;
00094 return true;
00095 }
00096
00097 template <int d>
00098 void shift_P(rational *A, int LastPlane_)
00099
00100
00101
00102 { rational *p1, *p2, *p3, d1, d2, d3;
00103 int col, i, j;
00104 int pivot[d+1];
00105
00106 #ifdef STATISTICS
00107 Stat_CountShifts ++;
00108 #endif
00109
00110 p1=A;
00111 pivot[0]=0;
00112 d3=fabs(d1=*p1);
00113 for (i=0; i<=LastPlane_; i++) {
00114 d2=fabs(*p1);
00115 #if PIVOTING_LASS == 0
00116 if (d2>=MIN_PIVOT_LASS) {pivot[0]=i; d1=*p1; break;};
00117 #endif
00118 if (d2>d3) { pivot[0]=i; d1=*p1; d3=d2; };
00119 p1+=(d+1);
00120 }
00121
00122 p1=A+pivot[0]*(d+1)+1;
00123 p2=planescopy+pivot[0]*(d+1)+1;
00124 for (i=1,d2=1.0/d1; i<=d; i++,p1++,p2++) *p2 = (*p1)*d2;
00125
00126 p1=A+1;
00127 p2=planescopy+1;
00128 for (i=0; i<=LastPlane_; i++, p1++, p2++) {
00129 if (i==pivot[0]) {
00130 p1+=d;
00131 p2+=d;
00132 continue;
00133 }
00134 d1=*(p1-1);
00135 p3=planescopy+pivot[0]*(d+1)+1;
00136 for (j=1; j<=d; j++, p1++, p2++, p3++) (*p2)=(*p1)-d1*(*p3);
00137 }
00138
00139
00140
00141 for (col=1;col<d;col++) {
00142 for (i=0;i<=LastPlane_;i++)
00143 if (notInPivot(pivot,col,i)) {
00144 pivot[col]=i;
00145 break;
00146 }
00147 p1=planescopy+i*(d+1)+col;
00148 d3=fabs(d1=*p1);
00149 for (; i<=LastPlane_; i++, p1+=(d+1))
00150 if (notInPivot(pivot,col,i)) {
00151 d2=fabs(*(p1));
00152 #if PIVOTING_LASS == 0
00153 if (d2>=MIN_PIVOT_LASS) {
00154 pivot[col]=i;
00155 d1=*p1;
00156 break;
00157 }
00158 #endif
00159 if (d2>d3) {
00160 pivot[col]=i;
00161 d1=*p1;
00162 d3=d2;
00163 }
00164 };
00165
00166 p1=planescopy+pivot[col]*(d+1)+col+1;
00167 d2=1.0/d1;
00168 for (j=col+1; j<=d; j++, p1++) (*p1) *= d2;
00169 if (col==(d-1)) break;
00170
00171 p1=planescopy+col+1;
00172 p2=planescopy+pivot[col]*(d+1)+col+1;
00173 for (i=0; i<=LastPlane_; i++, p1+=(col+1)) {
00174 if (!notInPivot(pivot,col+1,i)) {
00175 p1+=d-col;
00176 continue;
00177 }
00178 d1=*(p1-1);
00179 for (j=col+1; j<=d; j++, p1++, p2++) *p1=(*p1)-d1*(*p2);
00180 p2-=d-col;
00181 }
00182 };
00183
00184
00185
00186 for (i=d-2; 0<=i; i--){
00187 p1=planescopy+pivot[i]*(d+1)+d;
00188 p2=p1-d+i+1;
00189 for (j=i+1; j<d; j++, p2++)
00190 *(p1)-= (*p2)*(*(planescopy+pivot[j]*(d+1)+d));
00191 }
00192
00193
00194
00195 for (i=0; i<=LastPlane_; i++) {
00196 p1=A+i*(d+1);
00197 p2=p1+d;
00198 if (notInPivot(pivot,d,i))
00199 for (j=0; j<d; j++,p1++) {
00200 *p2 -= (*p1)*(*(planescopy+pivot[j]*(d+1)+d));
00201 }
00202 else *p2=0;
00203 }
00204 }
00205
00206 template <int d>
00207 rational dot(rational *A,rational *B) {
00208 rational sum=0.0;
00209 for (int i=0;i<d;i++) sum+=A[i]*B[i];
00210 return sum;
00211 }
00212
00213 template <int d>
00214 int norm_and_clean_constraints(rational* A, int *LastPlane_)
00215
00216
00217
00218
00219
00220
00221 { int i, j, row = 0;
00222 rational r0, *p1, *p2;
00223
00224
00225 p1=A;
00226 while (row<=(*LastPlane_)) {
00227 r0=dot<d>(p1,p1);
00228 if (r0<EPS_NORM*EPS_NORM) {
00229 if ((p1[d])<-100000*EPS1){
00230 return 1;
00231 }
00232 rm_constraint<d>(A, LastPlane_, row);
00233 }
00234 else {
00235 r0=1.0/sqrt(r0);
00236 for (j=0; j<=d; j++,p1++) (*p1)*=r0;
00237 row++;
00238 }
00239 }
00240
00241
00242 for (row=0; row<(*LastPlane_); row++) {
00243 for (i=row+1;i<=*LastPlane_;i++)
00244 {
00245 p1=A+row*(d+1);
00246 p2=A+i*(d+1);
00247 r0=dot<d>(p1,p2);
00248 if (r0>=1.0-EPS_NORM)
00249 {
00250 if (p1[d]>p2[d]){
00251 rm_constraint<d>(A, LastPlane_,row);
00252 i=row;
00253 }
00254 else {
00255 if (i<(*LastPlane_))
00256 rm_constraint<d>(A, LastPlane_,i);
00257 else (*LastPlane_)--;
00258 i--;
00259 }
00260 }
00261 else if (r0<=-1.0+EPS_NORM)
00262 {
00263 if (p1[d]>0){
00264 if (p2[d]<EPS1-p1[d]) return 1;
00265 }
00266 else {
00267 if (p1[d]<EPS1-p2[d]) return 1;
00268 }
00269 }
00270 }
00271 }
00272 return 0;
00273 }
00274
00281 template <int d>
00282 rational lass(rational *A, int LastPlane_)
00283
00284
00285
00286 {
00287 int i, j;
00288 int baserow = 0, basecol = 0, col;
00289 int row;
00290 bool i_balance = false;
00291 rational ma, mi,*realp1, *realp2;
00292
00293 ma=0;
00294 if (norm_and_clean_constraints<d>(A, &LastPlane_)!=0)
00295 return 0.0;
00296
00297
00298
00299 if (d>=LaShiftLevel) {
00300 realp1=A+d;
00301 realp2=realp1+LastPlane_*(d+1);
00302 j=0;
00303 while (realp1<=realp2) {
00304 if (fabs(*realp1)<EPSILON_LASS) j++;
00305 realp1+=d+1;
00306 }
00307 if (d-j>=LaShift) shift_P<d>(A, LastPlane_);
00308 }
00309
00310
00311 rational redA[(MAX_G_m-1)*G_d];
00312
00313 #ifdef ReverseLass
00314 for (row=LastPlane_; row>=0; row--) {
00315 #else
00316 for (row=0; row<=LastPlane_; row++) {
00317 #endif
00318 if (fabs(A[row*(d+1)+d])<EPSILON_LASS)
00319 continue;
00320 rational pivotrow[G_d+1];
00321 memcpy(&pivotrow[0], A+row*(d+1), sizeof(rational)*(d+1));
00322 col=0;
00323 for (i=0; i<d; i++) {
00324 #if PIVOTING_LASS == 0
00325 if (fabs(pivotrow[i])>=MIN_PIVOT_LASS) {col=i; break;};
00326 #endif
00327 if (fabs(pivotrow[i])>fabs(pivotrow[col])) col=i;
00328 };
00329
00330
00331
00332 mi=1.0/pivotrow[col];
00333 for (i=0; i<=d; i++) pivotrow[i]*=mi;
00334 realp1=A;
00335 realp2=redA;
00336 for (i=0; i<=LastPlane_; i++) {
00337 if (i==row) {
00338 realp1+=d+1;
00339 continue;
00340 };
00341 mi=A[(i*(d+1))+col];
00342 for (j=0; j<=d; j++) {
00343 if (j==col) {
00344 realp1++;
00345 continue;
00346 };
00347 *realp2=(*realp1)-pivotrow[j]*mi;
00348 realp1++;
00349 realp2++;
00350 };
00351 };
00352 ma+= A[row*(d+1)+d]/(d*fabs(A[row*(d+1)+col]))
00353 *lass<d-1>(redA, LastPlane_-1);
00354 #ifdef verboseFirstLevel
00355 if (d==G_d)
00356 printf("\nVolume accumulated to iteration %i is %20.12f",row,ma );
00357 #endif
00358 };
00359
00360 return ma;
00361 }
00362
00367 template <>
00368 rational lass<1>(rational *A, int LastPlane_)
00369 {
00370 int i;
00371 rational ma, mi;
00372
00373 ma=-MAXIMUM;
00374 mi= MAXIMUM;
00375 for (i=0; i<=LastPlane_; i++,A+=2) {
00376 if (*A>EPSILON_LASS) { if ((*(A+1)/ *A)<mi) mi=(*(A+1)/ *A); }
00377 else if (*A<-EPSILON_LASS) { if ((*(A+1)/ *A)>ma) ma=*(A+1)/ *A; }
00378 else if ((*(A+1))<-(100000*EPSILON_LASS)) return 0;
00379 }
00380 if ((ma<-.5*MAXIMUM)||(mi>.5*MAXIMUM)) {
00381 printf("\nVolume is unbounded!\n");
00382 exit(0);
00383 }
00384 if ((mi-ma)>EPSILON_LASS) {
00385 return mi-ma;
00386 }
00387 return 0;
00388 }
00389
00390
00391 public:
00392
00393 rational computeVolume(rational *planes,int nPlanes)
00394 {
00395 memcpy(planescopy,planes,sizeof(rational)*nPlanes*(G_d+1));
00396 return lass<G_d>(planes, nPlanes-1);
00397 }
00398
00399 };
00400
00408 double computeVolumePlanes(const double *planes,int nPlanes)
00409 {
00410 VINCI_Lass c;
00411 return c.computeVolume((double *)planes,nPlanes);
00412 }
00413