00001 #ifndef GUL_FLOAT_H 00002 #define GUL_FLOAT_H 00003 00004 namespace gul { 00005 00006 /*--------------------------------------------------------------------------- 00007 check if two floating point numbers are approximately equal. in this check 00008 the relative error is measured. 00009 ( remark: according to knuth 00010 |a-b| <= eps*|b| => a ~ b ('approximately rel_equal') 00011 and |a-b| > eps*|b| => a !~~ b (not 'essentialy rel_equal', for eps < 1 00012 & normalized floating point numbers) 00013 this check mixes both relations, 'approximately rel_equal' and 00014 'essentialy rel_equal', so it isn't 100% correct!) 00015 -----------------------------------------------------------------------------*/ 00016 template< class T > 00017 inline bool rel_equal( const T& a, const T& b, const T& eps ) 00018 { 00019 return rtr<T>::fabs(a-b) <= rtr<T>::fabs(b) * eps; 00020 } 00021 00022 /*-------------------------------------------------------------------------- 00023 check if two vectors are approximately equal. in this check 00024 the relative error is measured. 00025 ( remark: the maximum norm {..} is used to estimate the euclidian norm |..| 00026 by the equation: {v} <= |v| <= {v}*sqrt(dim(v)) <= eps 00027 if this check succeeds, it is still possible that |v| <= eps < {v}*sqrt(dim), 00028 so this check isn't 100% correct!) 00029 ---------------------------------------------------------------------------*/ 00030 template< class T > 00031 inline bool rel_equal( const gul::hpoint<T>& a, const gul::hpoint<T>& b, 00032 const T& eps ) 00033 { 00034 T tol = eps / (T)2; 00035 00036 if( !rel_equal(a.x, b.x, tol) ) return false; 00037 if( !rel_equal(a.y, b.y, tol) ) return false; 00038 if( !rel_equal(a.z, b.z, tol) ) return false; 00039 if( !rel_equal(a.w, b.w, tol) ) return false; 00040 00041 return true; 00042 } 00043 00044 template< class T > 00045 inline bool rel_equal( const gul::hpoint2<T>& a, const gul::hpoint2<T>& b, 00046 const T& eps ) 00047 { 00048 T tol = eps / rtr<T>::root2_3(); 00049 00050 if( !rel_equal(a.x, b.x, tol) ) return false; 00051 if( !rel_equal(a.y, b.y, tol) ) return false; 00052 if( !rel_equal(a.w, b.w, tol) ) return false; 00053 00054 return true; 00055 } 00056 00057 template< class T > 00058 inline bool rel_equal( const gul::hpoint1<T>& a, const gul::hpoint1<T>& b, 00059 const T& eps ) 00060 { 00061 T tol = eps / rtr<T>::root2_2(); 00062 00063 if( !rel_equal(a.x, b.x, tol) ) return false; 00064 if( !rel_equal(a.w, b.w, tol) ) return false; 00065 00066 return true; 00067 } 00068 00069 template< class T > 00070 inline bool rel_equal( const gul::point<T>& a, const gul::point<T>& b, 00071 const T& eps ) 00072 { 00073 T tol = eps / rtr<T>::root2_3(); 00074 00075 if( !rel_equal(a.x, b.x, tol) ) return false; 00076 if( !rel_equal(a.y, b.y, tol) ) return false; 00077 if( !rel_equal(a.z, b.z, tol) ) return false; 00078 00079 return true; 00080 } 00081 00082 template< class T > 00083 inline bool rel_equal( const gul::point2<T>& a, const gul::point2<T>& b, 00084 const T& eps ) 00085 { 00086 T tol = eps / rtr<T>::root2_2(); 00087 00088 if( !rel_equal(a.x, b.x, tol) ) return false; 00089 if( !rel_equal(a.y, b.y, tol) ) return false; 00090 00091 return true; 00092 } 00093 00094 template< class T > 00095 inline bool rel_equal( const gul::point1<T>& a, const gul::point1<T>& b, 00096 const T& eps ) 00097 { 00098 T tol = eps; 00099 00100 if( !rel_equal(a.x, b.x, tol) ) return false; 00101 00102 return true; 00103 } 00104 00105 /*----------------------------------------------------------------------- 00106 approximate normalization of a vector 00107 ------------------------------------------------------------------------*/ 00108 template< class T > 00109 T max_norm( const point<T>& a ) 00110 { 00111 T m; 00112 00113 m = rtr<T>::fabs(a.x); 00114 if( rtr<T>::fabs(a.y) > m ) m = rtr<T>::fabs(a.y); 00115 if( rtr<T>::fabs(a.z) > m ) m = rtr<T>::fabs(a.z); 00116 return m; 00117 } 00118 00119 template< class T > 00120 T max_norm( const point2<T>& a ) 00121 { 00122 T m; 00123 00124 m = rtr<T>::fabs(a.x); 00125 if( rtr<T>::fabs(a.y) > m ) m = rtr<T>::fabs(a.y); 00126 return m; 00127 } 00128 00129 /*----------------------------------------------------------------------- 00130 check if the cross-product of two vectors is approximately zero 00131 ------------------------------------------------------------------------*/ 00132 template< class T > 00133 bool zero_sine( const point<T>& ina, const point<T>& inb, const T& eps ) 00134 { 00135 T la,lb; 00136 point<T> a,b; 00137 00138 // normalize a,b (approximately) 00139 la = max_norm(ina); 00140 if( !la ) return true; 00141 a = ((T)1/la)*ina; 00142 00143 lb = max_norm(inb); 00144 if( !lb ) return true; 00145 b = ((T)1/lb)*inb; 00146 00147 if( rel_equal(a.y*b.z,b.y*a.z,eps) && 00148 rel_equal(b.x*a.z,a.x*b.z,eps) && 00149 rel_equal(a.x*b.y,b.x*a.y,eps) ) 00150 return true; 00151 00152 return false; 00153 } 00154 00155 template< class T > 00156 bool zero_sine( const point2<T>& ina, const point2<T>& inb, const T& eps ) 00157 { 00158 T la,lb; 00159 00160 // normalize a,b (approximately) 00161 la = max_norm(a); 00162 if( !la ) return true; 00163 a = ((T)1/la)*ina; 00164 00165 lb = max_norm(b); 00166 if( !lb ) return true; 00167 b = ((T)1/lb)*inb; 00168 00169 if( rel_equal(a.x*b.y-b.x*a.y,eps) ) 00170 return true; 00171 00172 return false; 00173 } 00174 00175 /*--------------------------------------------------------------------------- 00176 check if two floating point numbers are approximately equal. in this check 00177 the absolute error is measured. 00178 -----------------------------------------------------------------------------*/ 00179 template< class T > 00180 inline bool abs_equal( const T& a, const T& b, const T& eps ) 00181 { 00182 return rtr<T>::fabs(a-b) <= eps; 00183 } 00184 00185 /*-------------------------------------------------------------------------- 00186 check if two vectors are approximately equal. in this check 00187 the absolute error is measured. 00188 ( remark: the maximum norm {..} is used to estimate the euclidian norm |..| 00189 by the equation: {v} <= |v| <= {v}*sqrt(dim(v)) <= eps 00190 if this check succeeds, it is still possible that |v| <= eps < {v}*sqrt(dim), 00191 so this check isn't 100% correct!) 00192 ---------------------------------------------------------------------------*/ 00193 template< class T > 00194 inline bool abs_equal( const gul::hpoint<T>& a, const gul::hpoint<T>& b, 00195 const T& eps ) 00196 { 00197 T tol = eps / (T)2; 00198 00199 if( !abs_equal(a.x, b.x, tol) ) return false; 00200 if( !abs_equal(a.y, b.y, tol) ) return false; 00201 if( !abs_equal(a.z, b.z, tol) ) return false; 00202 if( !abs_equal(a.w, b.w, tol) ) return false; 00203 00204 return true; 00205 } 00206 00207 template< class T > 00208 inline bool abs_equal( const gul::hpoint2<T>& a, const gul::hpoint2<T>& b, 00209 const T& eps ) 00210 { 00211 T tol = eps / rtr<T>::root2_3(); 00212 00213 if( !abs_equal(a.x, b.x, tol) ) return false; 00214 if( !abs_equal(a.y, b.y, tol) ) return false; 00215 if( !abs_equal(a.w, b.w, tol) ) return false; 00216 00217 return true; 00218 } 00219 00220 template< class T > 00221 inline bool abs_equal( const gul::hpoint1<T>& a, const gul::hpoint1<T>& b, 00222 const T& eps ) 00223 { 00224 T tol = eps / rtr<T>::root2_2(); 00225 00226 if( !abs_equal(a.x, b.x, tol) ) return false; 00227 if( !abs_equal(a.w, b.w, tol) ) return false; 00228 00229 return true; 00230 } 00231 00232 template< class T > 00233 inline bool abs_equal( const gul::point<T>& a, const gul::point<T>& b, 00234 const T& eps ) 00235 { 00236 T tol = eps / rtr<T>::root2_3(); 00237 00238 if( !abs_equal(a.x, b.x, tol) ) return false; 00239 if( !abs_equal(a.y, b.y, tol) ) return false; 00240 if( !abs_equal(a.z, b.z, tol) ) return false; 00241 00242 return true; 00243 } 00244 00245 template< class T > 00246 inline bool abs_equal( const gul::point2<T>& a, const gul::point2<T>& b, 00247 const T& eps ) 00248 { 00249 T tol = eps / rtr<T>::root2_2(); 00250 00251 if( !abs_equal(a.x, b.x, tol) ) return false; 00252 if( !abs_equal(a.y, b.y, tol) ) return false; 00253 00254 return true; 00255 } 00256 00257 template< class T > 00258 inline bool abs_equal( const gul::point1<T>& a, const gul::point1<T>& b, 00259 const T& eps ) 00260 { 00261 T tol = eps; 00262 00263 if( !abs_equal(a.x, b.x, tol) ) return false; 00264 00265 return true; 00266 } 00267 00268 00269 } 00270 00271 #endif 00272 00273 00274 #if 0 00275 ################################################################################## 00276 OLD STUFF 00277 ################################################################################## 00278 00279 00280 /* 00281 template< class T > 00282 inline bool equal( const T& a, const T& b, const T& eps ) 00283 { 00284 T scaled = rtr<T>::fabs(a-b)/ 00285 rtr<T>::scalbn( (T)1, 00286 Max( rtr<T>::ilogb(rtr<T>::fabs(a)), 00287 rtr<T>::ilogb(rtr<T>::fabs(b))) ); 00288 return scaled <= eps; 00289 } 00290 00291 template< class T > 00292 inline bool equal( const T& a, const T& b, const T& eps, T& scaled ) 00293 { 00294 scaled = rtr<T>::fabs(a-b)/ 00295 rtr<T>::scalbn( (T)1, 00296 Max( rtr<T>::ilogb(rtr<T>::fabs(a)), 00297 rtr<T>::ilogb(rtr<T>::fabs(b))) ); 00298 return scaled <= eps; 00299 } 00300 */ 00301 00302 /* 00303 bool strongly_equal( const T& a, const T& b, const T& eps ) 00304 { 00305 T diff = rtr<T>::fabs(a-b); 00306 return (diff/rtr<T>::fabs(a) < eps) && (diff/rtr<T>::fabs(b) < eps); 00307 } 00308 00309 bool greater( const T& a, const T& b, const T& eps ) 00310 { 00311 T diff = a-b; 00312 return (diff/rtr<T>::fabs(a) > eps) && (diff/rtr<T>::fabs(b) > eps); 00313 } 00314 00315 bool lower( const T& a, const T& b, const T& eps ) 00316 { 00317 T diff = b-a; 00318 return (diff/rtr<T>::fabs(a) > eps) && (diff/rtr<T>::fabs(b) > eps); 00319 } 00320 */ 00321 00322 ################################################################## 00323 00324 /* -- check, if vector is (almost) zero --- */ 00325 /* 00326 template< class T > 00327 inline bool is_zero( const point<T>& a, const rtl<T>& t ) 00328 { 00329 T x,y,z; 00330 00331 x = rtr<T>::fabs(a.x); 00332 if( x > t.zero_tol ) return false; 00333 y = rtr<T>::fabs(a.y); 00334 if( y > t.zero_tol ) return false; 00335 z = rtr<T>::fabs(a.z); 00336 if( z > t.zero_tol ) return false; 00337 00338 if( (x <= t.zero_tol_v3) && (y <= t.zero_tol_v3) && 00339 (z <= t.zero_tol_v3) ) 00340 return true; 00341 00342 if( rtr<T>::sqrt(x*x + y*y + z*z) > t.zero_tol ) return false; 00343 00344 return true; 00345 } 00346 template< class T > 00347 inline bool is_zero( const point2<T>& a, const rtl<T>& t ) 00348 { 00349 T x,y; 00350 00351 x = rtr<T>::fabs(a.x); 00352 if( x > t.zero_tol ) return false; 00353 y = rtr<T>::fabs(a.y); 00354 if( y > t.zero_tol ) return false; 00355 00356 if( (x <= t.zero_tol_v2) && (y <= t.zero_tol_v2) ) 00357 return true; 00358 00359 if( rtr<T>::sqrt(x*x + y*y) > t.zero_tol ) return false; 00360 00361 return true; 00362 } 00363 */ 00364 00365 /* check, if the difference of two homogeneous vectors is (almost) zero */ 00366 /* 00367 template< class T > 00368 inline bool dist_is_zero( const hpoint<T>& a, const hpoint<T>& b, 00369 const rtl<T>& t ) 00370 { 00371 T x,y,z,w; 00372 00373 if( !equal(a.x, b.x, t.zero_tol, x) ) return false; 00374 if( !equal(a.y, b.y, t.zero_tol, y) ) return false; 00375 if( !equal(a.z, b.z, t.zero_tol, z) ) return false; 00376 if( !equal(a.w, b.w, t.zero_tol, w) ) return false; 00377 */ 00378 /* 00379 x = rtr<T>::fabs(a.x-b.x); 00380 if( x > t.zero_tol ) return false; 00381 y = rtr<T>::fabs(a.y-b.y); 00382 if( y > t.zero_tol ) return false; 00383 z = rtr<T>::fabs(a.z-b.z); 00384 if( z > t.zero_tol ) return false; 00385 w = rtr<T>::fabs(a.w-b.w); 00386 if( w > t.zero_tol ) return false; 00387 00388 if( (x <= t.zero_tol_v4) && (y <= t.zero_tol_v4) && 00389 (z <= t.zero_tol_v4) && (w <= t.zero_tol_v4) ) 00390 return true; 00391 00392 if( rtr<T>::sqrt( x*x + y*y + z*z + w*w ) > t.zero_tol ) return false; 00393 */ 00394 /* 00395 return true; 00396 } 00397 */ 00398 /* check, if the difference of two homogeneous vectors has a greater length 00399 than tol. */ 00400 /* 00401 template< class T > 00402 inline bool dist_longer_than( const hpoint<T>& a, const hpoint<T>& b, 00403 const T tolerance ) 00404 { 00405 T x,y,z,w; 00406 00407 if( !equal(a.x, b.x, tolerance, x) ) return true; 00408 if( !equal(a.y, b.y, tolerance, y) ) return true; 00409 if( !equal(a.z, b.z, tolerance, z) ) return true; 00410 if( !equal(a.w, b.w, tolerance, w) ) return true; 00411 */ 00412 /* 00413 x = rtr<T>::fabs(a.x-b.x); 00414 if( x > tolerance ) return true; 00415 y = rtr<T>::fabs(a.y-b.y); 00416 if( y > tolerance ) return true; 00417 z = rtr<T>::fabs(a.z-b.z); 00418 if( z > tolerance ) return true; 00419 w = rtr<T>::fabs(a.w-b.w); 00420 if( w > tolerance ) return true; 00421 00422 tol_v4 = tolerance / (T)2; // sqrt(4)=2 00423 00424 if( (x <= tol_v4) && (y <= tol_v4) && 00425 (z <= tol_v4) && (w <= tol_v4) ) 00426 return false; 00427 00428 if( rtr<T>::sqrt(x*x + y*y + z*z + w*w) > tolerance ) return true; 00429 */ 00430 /* 00431 return false; 00432 } 00433 */ 00434 00435 /* 00436 template< class T > 00437 inline bool dist_longer_than( const hpoint2<T>& a, const hpoint2<T>& b, 00438 const T tolerance ) 00439 { 00440 T x,y,w; 00441 00442 if( !equal(a.x, b.x, tolerance, x) ) return true; 00443 if( !equal(a.y, b.y, tolerance, y) ) return true; 00444 if( !equal(a.w, b.w, tolerance, w) ) return true; 00445 */ 00446 /* 00447 x = rtr<T>::fabs(a.x-b.x); 00448 if( x > tolerance ) return true; 00449 y = rtr<T>::fabs(a.y-b.y); 00450 if( y > tolerance ) return true; 00451 w = rtr<T>::fabs(a.w-b.w); 00452 if( w > tolerance ) return true; 00453 00454 tol_v3 = tolerance / rtr<T>::root2_3(); 00455 00456 if( (x <= tol_v3) && (y <= tol_v3) && (w <= tol_v3) ) 00457 return false; 00458 00459 if( rtr<T>::sqrt(x*x + y*y + w*w) > tolerance ) return true; 00460 */ 00461 /* 00462 return false; 00463 } 00464 */ 00465 /* check, if a vector has a greater length than tolerance */ 00466 /* 00467 template< class T > 00468 inline bool longer_than( const point<T>& a, const T tolerance ) 00469 { 00470 T x,y,z,tol_v3; 00471 00472 x = rtr<T>::fabs(a.x); 00473 if( x > tolerance ) return true; 00474 y = rtr<T>::fabs(a.y); 00475 if( y > tolerance ) return true; 00476 z = rtr<T>::fabs(a.z); 00477 if( z > tolerance ) return true; 00478 00479 tol_v3 = tolerance / rtr<T>::root2_3(); 00480 00481 if( (x <= tol_v3) && (y <= tol_v3) && (z <= tol_v3) ) return false; 00482 00483 if( rtr<T>::sqrt(x*x + y*y + z*z) > tolerance ) return true; 00484 00485 return false; 00486 } 00487 template< class T > 00488 inline bool longer_than( const point2<T>& a, const T tolerance ) 00489 { 00490 T x,y,tol_v2; 00491 00492 x = rtr<T>::fabs(a.x); 00493 if( x > tolerance ) return true; 00494 y = rtr<T>::fabs(a.y); 00495 if( y > tolerance ) return true; 00496 00497 tol_v2 = tolerance / rtr<T>::root2_2(); 00498 00499 if( (x <= tol_v2) && (y <= tol_v2) ) return false; 00500 00501 if( rtr<T>::sqrt(x*x + y*y) > tolerance ) return true; 00502 00503 return false; 00504 } 00505 */ 00506 /* check, if the difference of two vectors has a greater length than tol. */ 00507 /* 00508 template< class T > 00509 inline bool dist_longer_than( const point<T>& a, const point<T>& b, 00510 const T tolerance ) 00511 { 00512 T x,y,z; 00513 00514 if( !equal(a.x, b.x, tolerance, x) ) return true; 00515 if( !equal(a.y, b.y, tolerance, y) ) return true; 00516 if( !equal(a.z, b.z, tolerance, z) ) return true; 00517 */ 00518 /* 00519 x = rtr<T>::fabs(a.x-b.x); 00520 if( x > tolerance ) return true; 00521 y = rtr<T>::fabs(a.y-b.y); 00522 if( y > tolerance ) return true; 00523 z = rtr<T>::fabs(a.z-b.z); 00524 if( z > tolerance ) return true; 00525 00526 tol_v3 = tolerance / rtr<T>::root2_3(); 00527 00528 if( (x <= tol_v3) && (y <= tol_v3) && (z <= tol_v3) ) return false; 00529 00530 if( rtr<T>::sqrt(x*x + y*y + z*z) > tolerance ) return true; 00531 */ 00532 /* 00533 return false; 00534 } 00535 */ 00536 00537 /* 00538 template< class T > 00539 inline bool dist_longer_than( const point2<T>& a, const point2<T>& b, 00540 const T tolerance ) 00541 { 00542 T x,y; 00543 00544 if( !equal(a.x, b.x, tolerance, x) ) return true; 00545 if( !equal(a.y, b.y, tolerance, y) ) return true; 00546 */ 00547 /* 00548 x = rtr<T>::fabs(a.x-b.x); 00549 if( x > tolerance ) return true; 00550 y = rtr<T>::fabs(a.y-b.y); 00551 if( y > tolerance ) return true; 00552 00553 tol_v2 = tolerance / rtr<T>::root2_2(); 00554 00555 if( (x <= tol_v2) && (y <= tol_v2) ) return false; 00556 00557 if( rtr<T>::sqrt(x*x + y*y) > tolerance ) return true; 00558 */ 00559 /* 00560 return false; 00561 } 00562 */ 00563 00564 ################################################################################ 00565 #endif 00566