00001
00006
00007
00008
00009
00010
00011
00012
00013 #ifndef VL_MATHOP_H
00014 #define VL_MATHOP_H
00015
00016 #include "generic.h"
00017 #include <math.h>
00018
00020 #define VL_LOG_OF_2 0.693147180559945
00021
00023 #define VL_PI 3.141592653589793
00024
00032 #define VL_EPSILON_F 1.19209290E-07F
00033
00040 #define VL_EPSILON_D 2.220446049250313e-16
00041
00042
00043
00044
00045
00046
00047
00048
00050 static union { vl_uint32 raw ; float value ; }
00051 const vl_nan_f =
00052 { 0x7FC00000UL } ;
00053
00055 static union { vl_uint32 raw ; float value ; }
00056 const vl_infinity_f =
00057 { 0x7F800000UL } ;
00058
00060 static union { vl_uint64 raw ; double value ; }
00061 const vl_nan_d =
00062 #ifdef VL_COMPILER_MSC
00063 { 0x7FF8000000000000ui64 } ;
00064 #else
00065 { 0x7FF8000000000000ULL } ;
00066 #endif
00067
00069 static union { vl_uint64 raw ; double value ; }
00070 const vl_infinity_d =
00071 #ifdef VL_COMPILER_MSC
00072 { 0x7FF0000000000000ui64 } ;
00073 #else
00074 { 0x7FF0000000000000ULL } ;
00075 #endif
00076
00078 #define VL_NAN_F (vl_nan_f.value)
00079
00081 #define VL_INFINITY_F (vl_infinity_f.value)
00082
00084 #define VL_NAN_D (vl_nan_d.value)
00085
00087 #define VL_INFINITY_D (vl_infinity_d.value)
00088
00089
00090
00104 VL_INLINE float
00105 vl_mod_2pi_f (float x)
00106 {
00107 while (x > (float)(2 * VL_PI)) x -= (float) (2 * VL_PI) ;
00108 while (x < 0.0F) x += (float) (2 * VL_PI);
00109 return x ;
00110 }
00111
00116 VL_INLINE double
00117 vl_mod_2pi_d (double x)
00118 {
00119 while (x > 2.0 * VL_PI) x -= 2 * VL_PI ;
00120 while (x < 0.0) x += 2 * VL_PI ;
00121 return x ;
00122 }
00123
00129 VL_INLINE int
00130 vl_floor_f (float x)
00131 {
00132 int xi = (int) x ;
00133 if (x >= 0 || (float) xi == x) return xi ;
00134 else return xi - 1 ;
00135 }
00136
00141 VL_INLINE int
00142 vl_floor_d (double x)
00143 {
00144 int xi = (int) x ;
00145 if (x >= 0 || (double) xi == x) return xi ;
00146 else return xi - 1 ;
00147 }
00148
00154 VL_INLINE float
00155 vl_abs_f (float x)
00156 {
00157 #ifdef VL_COMPILER_GNU
00158 return __builtin_fabsf (x) ;
00159 #else
00160 return fabsf(x) ;
00161 #endif
00162 }
00163
00168 VL_INLINE double
00169 vl_abs_d (double x)
00170 {
00171 #ifdef VL_COMPILER_GNU
00172 return __builtin_fabs (x) ;
00173 #else
00174 return fabs(x) ;
00175 #endif
00176 }
00177
00178 VL_INLINE double
00179 vl_log2_d (double x)
00180 {
00181 #ifdef VL_COMPILER_GNU
00182 return __builtin_log2(x) ;
00183 #elif VL_COMPILER_MSC
00184 return log(x) / 0.693147180559945 ;
00185 #else
00186 return log2(x) ;
00187 #endif
00188 }
00189
00190 VL_INLINE float
00191 vl_log2_f (float x)
00192 {
00193 #ifdef VL_COMPILER_GNU
00194 return __builtin_log2f (x) ;
00195 #elif VL_COMPILER_MSC
00196 return logf(x) / 0.6931472F ;
00197 #else
00198 return log2(x) ;
00199 #endif
00200 }
00201
00238 VL_INLINE float
00239 vl_fast_atan2_f (float y, float x)
00240 {
00241 float angle, r ;
00242 float const c3 = 0.1821F ;
00243 float const c1 = 0.9675F ;
00244 float abs_y = vl_abs_f (y) + VL_EPSILON_F ;
00245
00246 if (x >= 0) {
00247 r = (x - abs_y) / (x + abs_y) ;
00248 angle = (float) (VL_PI / 4) ;
00249 } else {
00250 r = (x + abs_y) / (abs_y - x) ;
00251 angle = (float) (3 * VL_PI / 4) ;
00252 }
00253 angle += (c3*r*r - c1) * r ;
00254 return (y < 0) ? - angle : angle ;
00255 }
00256
00261 VL_INLINE double
00262 vl_fast_atan2_d (double y, double x)
00263 {
00264 double angle, r ;
00265 double const c3 = 0.1821 ;
00266 double const c1 = 0.9675 ;
00267 double abs_y = vl_abs_d (y) + VL_EPSILON_D ;
00268
00269 if (x >= 0) {
00270 r = (x - abs_y) / (x + abs_y) ;
00271 angle = VL_PI / 4 ;
00272 } else {
00273 r = (x + abs_y) / (abs_y - x) ;
00274 angle = 3 * VL_PI / 4 ;
00275 }
00276 angle += (c3*r*r - c1) * r ;
00277 return (y < 0) ? - angle : angle ;
00278 }
00279
00310 VL_INLINE float
00311 vl_fast_resqrt_f (float x)
00312 {
00313
00314 union {
00315 float x ;
00316 vl_int32 i ;
00317 } u ;
00318
00319 float xhalf = (float) 0.5 * x ;
00320
00321
00322 u.x = x ;
00323
00324
00325 u.i = 0x5f3759df - (u.i >> 1);
00326
00327
00328
00329 u.x = u.x * ( (float) 1.5 - xhalf*u.x*u.x) ;
00330 u.x = u.x * ( (float) 1.5 - xhalf*u.x*u.x) ;
00331 return u.x ;
00332 }
00333
00338 VL_INLINE double
00339 vl_fast_resqrt_d (double x)
00340 {
00341
00342 union {
00343 double x ;
00344 vl_int64 i ;
00345 } u ;
00346
00347 double xhalf = (double) 0.5 * x ;
00348
00349
00350 u.x = x ;
00351
00352
00353 #ifdef VL_COMPILER_MSC
00354 u.i = 0x5fe6ec85e7de30dai64 - (u.i >> 1) ;
00355 #else
00356 u.i = 0x5fe6ec85e7de30daLL - (u.i >> 1) ;
00357 #endif
00358
00359
00360 u.x = u.x * ( (double) 1.5 - xhalf*u.x*u.x) ;
00361 u.x = u.x * ( (double) 1.5 - xhalf*u.x*u.x) ;
00362 return u.x ;
00363 }
00364
00411 VL_INLINE float
00412 vl_fast_sqrt_f (float x)
00413 {
00414 return (x < 1e-8) ? 0 : x * vl_fast_resqrt_f (x) ;
00415 }
00416
00421 VL_INLINE double
00422 vl_fast_sqrt_d (float x)
00423 {
00424 return (x < 1e-8) ? 0 : x * vl_fast_resqrt_d (x) ;
00425 }
00426
00431 VL_INLINE vl_uint32 vl_fast_sqrt_ui32 (vl_uint32 x) ;
00432
00437 VL_INLINE vl_uint16 vl_fast_sqrt_ui16 (vl_uint16 x) ;
00438
00443 VL_INLINE vl_uint8 vl_fast_sqrt_ui8 (vl_uint8 x) ;
00444
00445 #define VL_FAST_SQRT_UI(T,SFX) \
00446 VL_INLINE T \
00447 vl_fast_sqrt_ ## SFX (T x) \
00448 { \
00449 T y = 0 ; \
00450 T tmp = 0 ; \
00451 int twok ; \
00452 \
00453 for (twok = 8 * sizeof(T) - 2 ; \
00454 twok >= 0 ; twok -= 2) { \
00455 y <<= 1 ; \
00456 tmp = (2*y + 1) << twok ; \
00457 if (x >= tmp) { \
00458 x -= tmp ; \
00459 y += 1 ; \
00460 } \
00461 } \
00462 return y ; \
00463 }
00464
00465 VL_FAST_SQRT_UI(vl_uint32,ui32)
00466 VL_FAST_SQRT_UI(vl_uint16,ui16)
00467 VL_FAST_SQRT_UI(vl_uint8,ui8)
00468
00469
00470
00471
00472
00476 typedef float (*VlFloatVectorComparisonFunction)(vl_size dimension, float const * X, float const * Y) ;
00477
00481 typedef double (*VlDoubleVectorComparisonFunction)(vl_size dimension, double const * X, double const * Y) ;
00482
00484 enum _VlVectorComparisonType {
00485 VlDistanceL1,
00486 VlDistanceL2,
00487 VlDistanceChi2,
00488 VlDistanceHellinger,
00489 VlDistanceJS,
00490 VlKernelL1,
00491 VlKernelL2,
00492 VlKernelChi2,
00493 VlKernelHellinger,
00494 VlKernelJS
00495 } ;
00496
00498 typedef enum _VlVectorComparisonType VlVectorComparisonType ;
00499
00505 VL_INLINE char const *
00506 vl_get_vector_comparison_type_name (int type)
00507 {
00508 switch (type) {
00509 case VlDistanceL1 : return "l1" ;
00510 case VlDistanceL2 : return "l2" ;
00511 case VlDistanceChi2 : return "chi2" ;
00512 case VlKernelL1 : return "kl1" ;
00513 case VlKernelL2 : return "kl2" ;
00514 case VlKernelChi2 : return "kchi2" ;
00515 default: return NULL ;
00516 }
00517 }
00518
00519 VL_EXPORT VlFloatVectorComparisonFunction
00520 vl_get_vector_comparison_function_f (VlVectorComparisonType type) ;
00521
00522 VL_EXPORT VlDoubleVectorComparisonFunction
00523 vl_get_vector_comparison_function_d (VlVectorComparisonType type) ;
00524
00525 VL_EXPORT void
00526 vl_eval_vector_comparison_on_all_pairs_f (float * result, vl_size dimension,
00527 float const * X, vl_size numDataX,
00528 float const * Y, vl_size numDataY,
00529 VlFloatVectorComparisonFunction function) ;
00530
00531 VL_EXPORT void
00532 vl_eval_vector_comparison_on_all_pairs_d (double * result, vl_size dimension,
00533 double const * X, vl_size numDataX,
00534 double const * Y, vl_size numDataY,
00535 VlDoubleVectorComparisonFunction function) ;
00536
00537
00538 #endif