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
1.2.13.1 written by Dimitri van Heesch,
© 1997-2001