Home Page Toolkit Overview Using GML User Input Services Finger Tracker Calibrator Frame Grabber Service protocol Obtaining GML Installing GML Licence Developer Documentation Tcl/Tk API The GML Canvas Image processing Tcl Scripts Library List of Classes List of Files C/C++ API List of Classes List of Files |
gml_Math.hGo to the documentation of this file.00001 /** @file gml_Math.h 00002 * 00003 * Overloaded and optimized math functions. 00004 * Probably no performance improvement will occur if inlining is disabled. 00005 * 00006 * Copyright (c) 2003-2004 CLIPS-IMAG 00007 * 00008 * See the file "gml_LicenseTerms.txt" for information on usage and redistribution 00009 * of this file, and for a DISCLAIMER OF ALL WARRANTIES. 00010 * 00011 * Created on November 20, 2003 (FB). 00012 */ 00013 #ifndef __GML_MATH__ 00014 #define __GML_MATH__ 00015 00016 #include <math.h> 00017 #include <assert.h> 00018 #include <stdlib.h> 00019 00020 #include "gml/base/gml_Types.h" 00021 00022 #if defined(__POWERPC__) && defined(HAVE_PPC_INTRINSICS_H) 00023 # include <ppc_intrinsics.h> 00024 #else 00025 # undef __GML_MATH_USE_PPC_INTRINSICS 00026 #endif 00027 00028 #ifndef __cplusplus 00029 #error C++ is required for this file 00030 #endif 00031 00032 /// @name Overloaded mathematical functions. 00033 /// Standard C library mathematical functions, 00034 /// overloaded to accept any precision. 00035 //@{ 00036 inline Float32 Cos (Float32 a) { return cosf (a); } 00037 inline Float64 Cos (Float64 a) { return cos (a); } 00038 inline Float32 Acos (Float32 a) { return acosf (a); } 00039 inline Float64 Acos (Float64 a) { return acos (a); } 00040 inline Float32 Sin (Float32 a) { return sinf (a); } 00041 inline Float64 Sin (Float64 a) { return sin (a); } 00042 inline Float32 Asin (Float32 a) { return asinf (a); } 00043 inline Float64 Asin (Float64 a) { return asin (a); } 00044 inline Float32 Tan (Float32 a) { return tanf (a); } 00045 inline Float64 Tan (Float64 a) { return tan (a); } 00046 inline Float32 Atan (Float32 a) { return atanf (a); } 00047 inline Float64 Atan (Float64 a) { return atan (a); } 00048 inline Float32 Atan2 (Float32 y, Float32 x) { return atan2f (y, x); } 00049 inline Float64 Atan2 (Float64 y, Float64 x) { return atan2 (y, x); } 00050 inline Float32 Hypot (Float32 y, Float32 x) { return hypotf (y, x); } 00051 inline Float64 Hypot (Float64 y, Float64 x) { return hypot (y, x); } 00052 inline Float32 Exp (Float32 a) { return expf (a); } 00053 inline Float64 Exp (Float64 a) { return exp (a); } 00054 inline Float32 Exp2 (Float32 a) { return exp2f (a); } 00055 inline Float64 Exp2 (Float64 a) { return exp2 (a); } 00056 00057 inline UInt8 Abs (SInt8 a) { return labs (a); } 00058 inline UInt16 Abs (SInt16 a) { return labs (a); } 00059 inline UInt32 Abs (SInt32 a) { return labs (a); } 00060 inline UInt64 Abs (SInt64 a) { return llabs (a); } 00061 inline Float32 Abs (Float32 a) { return fabsf (a); } 00062 inline Float64 Abs (Float64 a) { return fabs (a); } 00063 inline Float32 Sqrt (Float32 a); 00064 inline Float64 Sqrt (Float64 a); 00065 inline Float32 Cbrt (Float32 a) { return cbrtf (a); } 00066 inline Float64 Cbrt (Float64 a) { return cbrt (a); } 00067 inline Float32 Log1p (Float32 a) { return log1p (a); } 00068 inline Float64 Log1p (Float64 a) { return log1pf (a); } 00069 inline Float32 Log (Float32 a) { return log (a); } 00070 inline Float64 Log (Float64 a) { return logf (a); } 00071 00072 /// Count the digits in <a>. 00073 inline UInt8 Log2 (UInt32 a); 00074 //@} 00075 00076 /// @name Not A Number functions 00077 /// Generate and check NaNs. 00078 //@{ 00079 inline void Nan (Float32 &a) { a = nanf (""); } 00080 inline void Nan (Float64 &a) { a = nan (""); } 00081 inline int Isnan (Float32 a) { return isnan (a); } 00082 inline int Isnan (Float64 a) { return isnan (a); } 00083 //@} 00084 00085 /// @name Optimized selection functions 00086 /// Select() is equivalent to: (a < b) ? alt1 : alt2 00087 /// Whenever possible, Select() is implemented without branching. 00088 //@{ 00089 inline UInt8 Select ( UInt8 a, UInt8 b, UInt8 alt1, UInt8 alt2); 00090 inline SInt8 Select ( SInt8 a, SInt8 b, SInt8 alt1, SInt8 alt2); 00091 inline UInt16 Select ( UInt16 a, UInt16 b, UInt16 alt1, UInt16 alt2); 00092 inline SInt16 Select ( SInt16 a, SInt16 b, SInt16 alt1, SInt16 alt2); 00093 inline UInt32 Select ( UInt32 a, UInt32 b, UInt32 alt1, UInt32 alt2); 00094 inline SInt32 Select ( SInt32 a, SInt32 b, SInt32 alt1, SInt32 alt2); 00095 inline UInt64 Select ( UInt64 a, UInt64 b, UInt64 alt1, UInt64 alt2); 00096 inline SInt64 Select ( SInt64 a, SInt64 b, SInt64 alt1, SInt64 alt2); 00097 00098 inline Float32 Select (Float32 a, Float32 b, Float32 alt1, Float32 alt2); 00099 inline Float64 Select (Float64 a, Float64 b, Float64 alt1, Float64 alt2); 00100 //@} 00101 00102 /// @name Fast minimum, maximum, clamping and clipping functions 00103 /// These functions use the optimized Select() flavours above to acheive performance. 00104 /// They work with any integer or floating-point type. 00105 //@{ 00106 00107 template <typename T> inline T Min (T n, T p); 00108 template <typename T> inline T Max (T n, T p); 00109 template <typename T> inline T Min (T a, T b, T c); 00110 template <typename T> inline T Max (T a, T b, T c); 00111 template <typename T> inline T Clamp (T v, T min, T max); 00112 template <typename T> inline T Clip (T v, T min, T max); 00113 00114 //@} 00115 00116 /// @name Rounding 00117 //@{ 00118 inline UInt32 LFloor (Float32 a); 00119 inline UInt32 LFloor (Float64 a); 00120 inline SInt32 LRound (Float32 d); 00121 inline Float32 Floor (Float32 a) { return floorf (a); } 00122 inline Float64 Floor (Float64 a) { return floor (a); } 00123 inline Float32 Ceil (Float32 a) { return ceilf (a); } 00124 inline Float64 Ceil (Float64 a) { return ceil (a); } 00125 //@} 00126 00127 /// Floating-point division 00128 inline Float32 Divide (Float32 x, Float32 y); 00129 00130 /// Average of three integers 00131 inline UInt32 Average (UInt32 a, UInt32 b, UInt32 c); 00132 00133 /// Integer square root 00134 inline UInt16 Sqrt (UInt32 a); 00135 00136 /// @name Euclidian vector norm 00137 //@{ 00138 inline UInt32 Norm (UInt32 a, UInt32 b); 00139 inline Float32 Norm (Float32 a, Float32 b); 00140 inline UInt32 Norm (UInt32 a1, UInt32 b1, UInt32 a2, UInt32 b2); 00141 inline Float32 Norm (Float32 a1, Float32 b1, Float32 a2, Float32 b2); 00142 //@} 00143 00144 /// @name Square function 00145 //@{ 00146 inline UInt32 Sqr (SInt32 a) { return a * a; } 00147 inline UInt32 Sqr (UInt32 a) { return a * a; } 00148 inline Float32 Sqr (Float32 a) { return a * a; } 00149 inline Float64 Sqr (Float64 a) { return a * a; } 00150 //@} 00151 00152 00153 /// @name Fast bit shifting 00154 //@{ 00155 00156 /// 00157 /// ShiftLeft -- 00158 /// Shift <integer> left by a signed offset: if negative, a right shift is applied. 00159 /// If <offset> is a compile-time constant, no branch should be generated by your 00160 /// compiler -- it should actually only output one assembly instruction. 00161 /// 00162 template <typename T> 00163 inline T ShiftLeft (T const integer, SInt8 const offset); 00164 00165 /// 00166 /// ShiftRight -- 00167 /// Shift <integer> right by a signed offset: if negative, a left shift is applied. 00168 /// If <offset> is a compile-time constant, no branch should be generated by your 00169 /// compiler -- it should actually only output one assembly instruction. 00170 /// 00171 template <typename T> 00172 inline T ShiftRight (T const integer, SInt8 const offset); 00173 00174 00175 /// 00176 /// ShiftLeft -- 00177 /// Fast, Select()-based bit shifting for 64-bit integers on 32-bit machines. 00178 /// 00179 inline UInt64 ShiftLeft (UInt64 const integer, UInt8 const s); 00180 00181 /// 00182 /// ShiftRight -- 00183 /// Fast, Select()-based bit shifting for 64-bit integers on 32-bit machines. 00184 /// 00185 inline UInt64 ShiftRight (UInt64 const integer, UInt8 const s); 00186 00187 //@} 00188 00189 // 00190 // Implementation follows 00191 // 00192 00193 inline UInt8 Log2 (UInt32 a) 00194 { 00195 #if defined(__GML_MATH_USE_PPC_INTRINSICS) 00196 return UInt8 (32 - __cntlzw (a)); 00197 #else 00198 if (a == 0) return 0; 00199 for (int k = 32; k; --k) { 00200 if (a == (a & (1 << (k-1)))) return k; 00201 } 00202 return 0; // prevent compiler warning 00203 #endif /* __GML_MATH_USE_PPC_INTRINSICS */ 00204 } 00205 00206 inline UInt8 Select (UInt8 a, UInt8 b, UInt8 alt1, UInt8 alt2) 00207 { 00208 return (UInt8) Select (UInt32(a), UInt32(b), UInt32(alt1), UInt32(alt2)); 00209 } 00210 00211 inline UInt16 Select (UInt16 a, UInt16 b, UInt16 alt1, UInt16 alt2) 00212 { 00213 return (UInt16) Select (UInt32(a), UInt32(b), UInt32(alt1), UInt32(alt2)); 00214 } 00215 00216 inline UInt32 Select (UInt32 a, UInt32 b, UInt32 alt1, UInt32 alt2) 00217 { 00218 #ifdef __GML_MATH_FAST_SELECT 00219 const UInt32 sign = ((a - b)) >> 31; 00220 return (alt1 * sign) + (alt2 * (SInt32(1) - sign)); 00221 #else 00222 return (a < b) ? alt1 : alt2; 00223 #endif // __GML_MATH_FAST_SELECT 00224 } 00225 00226 inline UInt64 Select (UInt64 a, UInt64 b, UInt64 alt1, UInt64 alt2) 00227 { 00228 #ifdef __GML_MATH_FAST_SELECT 00229 const UInt64 sign = ((UInt64) ((SInt64) a - b)) >> 63; 00230 return (alt1 * sign) + (alt2 * (SInt64(1) - sign)); 00231 #else 00232 return (a < b) ? alt1 : alt2; 00233 #endif // __GML_MATH_FAST_SELECT 00234 } 00235 00236 inline SInt8 Select (SInt8 a, SInt8 b, SInt8 alt1, SInt8 alt2) 00237 { 00238 return (a < b) ? alt1 : alt2; 00239 } 00240 00241 inline SInt16 Select (SInt16 a, SInt16 b, SInt16 alt1, SInt16 alt2) 00242 { 00243 return (a < b) ? alt1 : alt2; 00244 } 00245 00246 inline SInt32 Select (SInt32 a, SInt32 b, SInt32 alt1, SInt32 alt2) 00247 { 00248 return (a < b) ? alt1 : alt2; 00249 } 00250 00251 inline SInt64 Select (SInt64 a, SInt64 b, SInt64 alt1, SInt64 alt2) 00252 { 00253 return (a < b) ? alt1 : alt2; 00254 } 00255 00256 00257 inline Float64 Select (Float64 a, Float64 b, Float64 alt1, Float64 alt2) 00258 { 00259 #if defined(__GML_MATH_FAST_SELECT) && defined(__GML_MATH_USE_PPC_INTRINSICS) 00260 return __fsel (b-a, alt1, alt2); 00261 #else 00262 return (a < b) ? alt1 : alt2; 00263 #endif // __GML_MATH_FAST_SELECT 00264 } 00265 00266 inline Float32 Select (Float32 a, Float32 b, Float32 alt1, Float32 alt2) 00267 { 00268 #if defined(__GML_MATH_FAST_SELECT) && defined(__GML_MATH_USE_PPC_INTRINSICS) 00269 return __fsels (b-a, alt1, alt2); 00270 #else 00271 return (a < b) ? alt1 : alt2; 00272 #endif // __GML_MATH_FAST_SELECT 00273 } 00274 00275 template <typename T> 00276 inline T Select (T a, T b, T alt1, T alt2) 00277 { 00278 return (a < b) ? alt1 : alt2; 00279 } 00280 00281 template <typename T> 00282 inline T Min (T n, T p) 00283 { 00284 return Select (n, p, n, p); 00285 } 00286 00287 template <typename T> 00288 inline T Max (T n, T p) 00289 { 00290 return Select (n, p, p, n); 00291 } 00292 00293 template <typename T> 00294 inline T Min (T a, T b, T c) 00295 { 00296 return Min (a, Min (b, c)); 00297 } 00298 00299 template <typename T> 00300 inline T Max (T a, T b, T c) 00301 { 00302 return Max (a, Max (b, c)); 00303 } 00304 00305 00306 template <typename T> 00307 inline T Clamp (T v, T min, T max) 00308 { 00309 return Max (min, Min (v, max)); 00310 } 00311 00312 template <typename T> 00313 inline T Clip (T v, T min, T max) 00314 { 00315 return Select (v, min, v, Select (v, max, max, v)); 00316 } 00317 00318 00319 00320 inline SInt32 LRound (Float32 d) 00321 { 00322 #ifdef __GML_MATH_USE_PPC_INTRINSICS 00323 Float32 ff = Floor (d); 00324 return (SInt32) __fsel (d - ff - 0.5F, ff + 1.0F, ff); 00325 #else 00326 return (SInt32) lroundf (d); 00327 #endif /* __GML_MATH_USE_PPC_INTRINSICS */ 00328 } 00329 00330 inline Float32 Divide (Float32 x, Float32 y) 00331 { 00332 #ifdef __GML_MATH_USE_PPC_INTRINSICS 00333 return x * __fres (y); 00334 #else 00335 return x/y; 00336 #endif /* __GML_MATH_USE_PPC_INTRINSICS */ 00337 } 00338 00339 inline UInt32 LFloor (Float32 d) 00340 { 00341 #ifdef __GML_MATH_USE_PPC_INTRINSICS 00342 typedef union { Float64 d; UInt64 u; } T; 00343 T res; res.d = __fctiwz (d); 00344 return (UInt32) res.u; 00345 #else 00346 return (UInt32) floorf (d); 00347 #endif /* __GML_MATH_USE_PPC_INTRINSICS */ 00348 } 00349 00350 inline UInt32 LFloor (Float64 d) 00351 { 00352 #ifdef __GML_MATH_USE_PPC_INTRINSICS 00353 typedef union { Float64 d; UInt64 u; } T; 00354 T res; res.d = __fctiwz (d); 00355 return (UInt32) res.u; 00356 #else 00357 return (UInt32) floor (d); 00358 #endif /* __GML_MATH_USE_PPC_INTRINSICS */ 00359 } 00360 00361 inline UInt32 Average (UInt32 a, UInt32 b, UInt32 c) 00362 { 00363 return (a+b+c)/3; 00364 } 00365 00366 inline UInt16 Sqrt (UInt32 a) 00367 { 00368 #if defined(__GML_MATH_USE_PPC_INTRINSICS) && defined(__GML_MATH_FAST_SQRT) 00369 const Float64 b = (Float64) a; 00370 return (UInt16) LFloor (b * __frsqrte (b)); 00371 #else 00372 UInt32 rem = 0; 00373 UInt32 root = 0; 00374 00375 for (int i = 0; i < 16; i++) { 00376 root <<= 1; 00377 rem = ((rem << 2) + (a >> 30)); 00378 a <<= 2; 00379 root++; 00380 if (root <= rem) { 00381 rem -= root; 00382 root++; 00383 } else 00384 root--; 00385 } 00386 00387 return (UInt16) (root >> 1); 00388 #endif 00389 } 00390 00391 inline Float32 Sqrtr (Float32 a) 00392 { 00393 #if defined(__GML_MATH_USE_PPC_INTRINSICS) && defined(__GML_MATH_FAST_SQRT) 00394 Float32 e = __frsqrtes (a); 00395 #ifdef __GML_MATH_FAST_SQRT_REFINE 00396 // two rounds of Newton-Raphson refinement 00397 e = (.5F * e * (3.0F - a * e * e)); 00398 e = (.5F * e * (3.0F - a * e * e)); 00399 #endif 00400 return e; 00401 #else 00402 return 1.0F / sqrtf (a); 00403 #endif 00404 } 00405 00406 inline Float64 Sqrtr (Float64 a) 00407 { 00408 #if defined(__GML_MATH_USE_PPC_INTRINSICS) && defined(__GML_MATH_FAST_SQRT) 00409 Float64 e = __frsqrte (a); 00410 #ifdef __GML_MATH_FAST_SQRT_REFINE 00411 // two rounds of Newton-Raphson refinement 00412 e = (.5 * e * (3.0 - a * e * e)); 00413 e = (.5 * e * (3.0 - a * e * e)); 00414 #endif 00415 return e; 00416 #else 00417 return 1.0 / sqrt (a); 00418 #endif 00419 } 00420 00421 inline Float32 Sqrt (Float32 a) 00422 { 00423 #if defined(__GML_MATH_USE_PPC_INTRINSICS) && defined(__GML_MATH_FAST_SQRT) 00424 return a * Sqrtr (a); 00425 #else 00426 return sqrtf (a); 00427 #endif 00428 } 00429 00430 inline Float64 Sqrt (Float64 a) 00431 { 00432 #if defined(__GML_MATH_USE_PPC_INTRINSICS) && defined(__GML_MATH_FAST_SQRT) 00433 return a * Sqrtr (a); 00434 #else 00435 return sqrt (a); 00436 #endif 00437 } 00438 00439 inline UInt32 Norm (UInt32 a, UInt32 b) 00440 { 00441 return Sqrt (a*a + b*b); 00442 } 00443 00444 inline Float32 Norm (Float32 a, Float32 b) 00445 { 00446 return Sqrt (a*a + b*b); 00447 } 00448 00449 inline UInt32 Norm (UInt32 a1, UInt32 b1, UInt32 a2, UInt32 b2) 00450 { 00451 return Norm (Abs ((SInt32) a1 - (SInt32) a2), Abs ((SInt32) b1 - (SInt32) b2)); 00452 } 00453 00454 inline Float32 Norm (Float32 a1, Float32 b1, Float32 a2, Float32 b2) 00455 { 00456 return Norm (a1 - a2, b1 - b2); 00457 } 00458 00459 template <typename T> 00460 inline 00461 T ShiftLeft (T const integer, SInt8 const offset) 00462 { 00463 if (offset > 0) { 00464 return integer << offset; 00465 } else if (offset < 0) { 00466 return integer >> -offset; 00467 } else { 00468 return integer; 00469 } 00470 } 00471 00472 template <typename T> 00473 inline 00474 T ShiftRight (T const integer, SInt8 const offset) 00475 { 00476 if (offset > 0) { 00477 return integer >> offset; 00478 } else if (offset < 0) { 00479 return integer << -offset; 00480 } else { 00481 return integer; 00482 } 00483 } 00484 00485 00486 union UInt64_union { 00487 UInt64 val; 00488 struct { 00489 #if BYTE_ORDER == BIG_ENDIAN 00490 UInt32 hi; 00491 UInt32 lo; 00492 #else 00493 UInt32 lo; 00494 UInt32 hi; 00495 #endif 00496 }; 00497 }; 00498 00499 inline 00500 UInt64 ShiftLeft (UInt64 const integer, UInt8 const s) 00501 { 00502 UInt64_union ui; 00503 UInt64_union res; 00504 assert (s <= 64); 00505 ui.val = integer; 00506 res.hi = Select ((UInt32) s, 32UL, (ui.hi << s) | (ui.lo >> (32-s)), (ui.lo << (s-32))); 00507 res.lo = Select ((UInt32) s, 32UL, (ui.lo << s), (UInt32) 0); 00508 assert (res.val == (integer << s)); 00509 return res.val; 00510 } 00511 00512 inline 00513 UInt64 ShiftRight (UInt64 const integer, UInt8 const s) 00514 { 00515 UInt64_union ui; 00516 UInt64_union res; 00517 assert (s <= 64); 00518 ui.val = integer; 00519 res.hi = Select ((UInt32) s, 32UL, (ui.hi >> s), (UInt32) 0); 00520 res.lo = Select ((UInt32) s, 32UL, (ui.hi << (32-s)) | (ui.lo >> s), (ui.hi >> (s-32))); 00521 assert (res.val == (integer >> s)); 00522 return res.val; 00523 } 00524 00525 #endif 00526
Generated on Tue Jun 12 14:03:27 2007 for gml by
Doxygen 1.5.2.
|
Contact: julien (dot) letessier (at) gmail (dot) com.
Copyright (c) 2000-2007 CLIPS-IMAG Laboratory, Grenoble, France. All rights reserved. W3CXHTML 1.0 W3CCSS 2.0 |