core/vnl/vnl_math.h
Go to the documentation of this file.
00001 // This is core/vnl/vnl_math.h
00002 #ifndef vnl_math_h_
00003 #define vnl_math_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Namespace with standard math functions
00010 //
00011 //  The vnl_math namespace provides a standard set of the simple mathematical
00012 //  functions (min, max, sqr, sgn, rnd, abs), and some predefined constants
00013 //  such as pi and e, which are not defined by the ANSI C++ standard.
00014 //
00015 //  There are complex versions defined in vnl_complex.h
00016 //
00017 //  That's right, M_PI is nonstandard!
00018 //
00019 //  Aside from e, pi and their associates the class also defines eps,
00020 //  the IEEE double machine precision.  This is the smallest number
00021 //  eps such that 1+eps != 1.
00022 //
00023 //  The operations are overloaded for int, float and double arguments,
00024 //  which in combination with inlining can make them  more efficient than
00025 //  their counterparts in the standard C library.
00026 //
00027 // \author Andrew W. Fitzgibbon, Oxford RRG
00028 // \date   July 13, 1996
00029 //
00030 // \verbatim
00031 //  Modifications
00032 //   21 May 1998 AWF Removed conditional VCL_IMPLEMENT_STATIC_CONSTS, sometimes gcc needs them.
00033 //   LSB (Modifications) 23 Jan 2001 Documentation tidied
00034 //   Peter Vanroose - 7 Sep 2002 - maxdouble etc. replaced by vnl_numeric_traits<T>::maxval
00035 //   Amitha Perera - 13 Sep 2002 - make constant initialization standards compliant.
00036 // \endverbatim
00037 
00038 #include <vcl_cmath.h>
00039 #include "dll.h"
00040 #include <vxl_config.h>
00041 #include <vnl/vnl_config.h> // for VNL_CONFIG_ENABLE_SSE2_ROUNDING
00042 #ifdef VNL_CHECK_FPU_ROUNDING_MODE
00043 # include <vcl_cassert.h>
00044 #endif
00045 
00046 // Figure out when the fast implementation can be used
00047 #if VNL_CONFIG_ENABLE_SSE2_ROUNDING
00048 # if !VXL_HAS_EMMINTRIN_H
00049 #   error "Required file emmintrin.h for SSE2 not found"
00050 # else
00051 #   include <emmintrin.h> // sse 2 intrinsics
00052 # endif
00053 #endif
00054 // Turn on fast impl when using GCC on Intel-based machines with the following exception:
00055 //   PPC with Mac OS X
00056 #if defined(__GNUC__) && (!defined(__APPLE__)  || !defined(__ppc__) )
00057 # define GCC_USE_FAST_IMPL 1
00058 #else
00059 # define GCC_USE_FAST_IMPL 0
00060 #endif
00061 // Turn on fast impl when using msvc on 32 bits windows
00062 #if defined(VCL_VC) && !defined(_WIN64)
00063 # define VC_USE_FAST_IMPL 1
00064 #else
00065 # define VC_USE_FAST_IMPL 0
00066 #endif
00067 
00068 
00069 //: Type-accessible infinities for use in templates.
00070 template <class T> T vnl_huge_val(T);
00071 double   vnl_huge_val(double);
00072 float    vnl_huge_val(float);
00073 long int vnl_huge_val(long int);
00074 int      vnl_huge_val(int);
00075 short    vnl_huge_val(short);
00076 char     vnl_huge_val(char);
00077 
00078 //: real numerical constants
00079 class vnl_math
00080 {
00081  public:
00082   //: pi, e and all that
00083   static VNL_DLL_DATA const double e                VCL_STATIC_CONST_INIT_FLOAT_DECL(2.7182818284590452354);
00084   static VNL_DLL_DATA const double log2e            VCL_STATIC_CONST_INIT_FLOAT_DECL(1.4426950408889634074);
00085   static VNL_DLL_DATA const double log10e           VCL_STATIC_CONST_INIT_FLOAT_DECL(0.43429448190325182765);
00086   static VNL_DLL_DATA const double ln2              VCL_STATIC_CONST_INIT_FLOAT_DECL(0.69314718055994530942);
00087   static VNL_DLL_DATA const double ln10             VCL_STATIC_CONST_INIT_FLOAT_DECL(2.30258509299404568402);
00088   static VNL_DLL_DATA const double pi               VCL_STATIC_CONST_INIT_FLOAT_DECL(3.14159265358979323846);
00089   static VNL_DLL_DATA const double pi_over_2        VCL_STATIC_CONST_INIT_FLOAT_DECL(1.57079632679489661923);
00090   static VNL_DLL_DATA const double pi_over_4        VCL_STATIC_CONST_INIT_FLOAT_DECL(0.78539816339744830962);
00091   static VNL_DLL_DATA const double pi_over_180      VCL_STATIC_CONST_INIT_FLOAT_DECL(0.01745329251994329577);
00092   static VNL_DLL_DATA const double one_over_pi      VCL_STATIC_CONST_INIT_FLOAT_DECL(0.31830988618379067154);
00093   static VNL_DLL_DATA const double two_over_pi      VCL_STATIC_CONST_INIT_FLOAT_DECL(0.63661977236758134308);
00094   static VNL_DLL_DATA const double deg_per_rad      VCL_STATIC_CONST_INIT_FLOAT_DECL(57.2957795130823208772);
00095   static VNL_DLL_DATA const double two_over_sqrtpi  VCL_STATIC_CONST_INIT_FLOAT_DECL(1.12837916709551257390);
00096   static VNL_DLL_DATA const double one_over_sqrt2pi VCL_STATIC_CONST_INIT_FLOAT_DECL(0.39894228040143267794);
00097   static VNL_DLL_DATA const double sqrt2            VCL_STATIC_CONST_INIT_FLOAT_DECL(1.41421356237309504880);
00098   static VNL_DLL_DATA const double sqrt1_2          VCL_STATIC_CONST_INIT_FLOAT_DECL(0.70710678118654752440);
00099   static VNL_DLL_DATA const double sqrt1_3          VCL_STATIC_CONST_INIT_FLOAT_DECL(0.57735026918962573106);
00100   static VNL_DLL_DATA const double euler            VCL_STATIC_CONST_INIT_FLOAT_DECL(0.57721566490153286061);
00101 
00102   //: IEEE double machine precision
00103   static VNL_DLL_DATA const double eps             VCL_STATIC_CONST_INIT_FLOAT_DECL(2.2204460492503131e-16);
00104   static VNL_DLL_DATA const double sqrteps         VCL_STATIC_CONST_INIT_FLOAT_DECL(1.490116119384766e-08);
00105   //: IEEE single machine precision
00106   static VNL_DLL_DATA const float float_eps        VCL_STATIC_CONST_INIT_FLOAT_DECL(1.192092896e-07f);
00107   static VNL_DLL_DATA const float float_sqrteps    VCL_STATIC_CONST_INIT_FLOAT_DECL(3.4526698307e-4f);
00108 //: Convert an angle to [0, 2Pi) range
00109   static double angle_0_to_2pi(double angle);
00110 };
00111 
00112 // We do not want to make assumptions about unknown types that happen
00113 // to have conversions to one of the fundamental types.  The templated
00114 // versions of isnan, isinf, and isfinite below serve as catch-alls to
00115 // cause linker errors if these functions are invoked with an unknown
00116 // type.  However, due to compiler bugs, the templates sometimes match
00117 // too often (see documentation of VCL_TEMPLATE_MATCHES_TOO_OFTEN) and
00118 // are selected over reference-binding overloads like those in
00119 // vnl_rational.h.  We add the catch-all templates only if the
00120 // compiler does not have this bug. -- Brad King
00121 
00122 // Note that the three template functions below should not be declared "inline"
00123 // since that would override the non-inline specialisations. - PVr.
00124 //
00125 
00126 // isnan
00127 inline bool vnl_math_isnan(char)               { return false; }
00128 inline bool vnl_math_isnan(short)              { return false; }
00129 inline bool vnl_math_isnan(int)                { return false; }
00130 inline bool vnl_math_isnan(long)               { return false; }
00131 inline bool vnl_math_isnan(signed char)        { return false; }
00132 inline bool vnl_math_isnan(unsigned char)      { return false; }
00133 inline bool vnl_math_isnan(unsigned short)     { return false; }
00134 inline bool vnl_math_isnan(unsigned int)       { return false; }
00135 inline bool vnl_math_isnan(unsigned long)      { return false; }
00136 #if VCL_HAS_LONG_LONG
00137 inline bool vnl_math_isnan(long long)          { return false; }
00138 inline bool vnl_math_isnan(unsigned long long) { return false; }
00139 #endif
00140 bool vnl_math_isnan(float);
00141 bool vnl_math_isnan(double);
00142 bool vnl_math_isnan(long double);
00143 #if !VCL_TEMPLATE_MATCHES_TOO_OFTEN
00144 template <class T> bool vnl_math_isnan(T);
00145 #endif
00146 
00147 
00148 
00149 
00150 // isinf
00151 inline bool vnl_math_isinf(char)               { return false; }
00152 inline bool vnl_math_isinf(short)              { return false; }
00153 inline bool vnl_math_isinf(int)                { return false; }
00154 inline bool vnl_math_isinf(long)               { return false; }
00155 inline bool vnl_math_isinf(signed char)        { return false; }
00156 inline bool vnl_math_isinf(unsigned char)      { return false; }
00157 inline bool vnl_math_isinf(unsigned short)     { return false; }
00158 inline bool vnl_math_isinf(unsigned int)       { return false; }
00159 inline bool vnl_math_isinf(unsigned long)      { return false; }
00160 #if VCL_HAS_LONG_LONG
00161 inline bool vnl_math_isinf(long long)          { return false; }
00162 inline bool vnl_math_isinf(unsigned long long) { return false; }
00163 #endif
00164 bool vnl_math_isinf(float);
00165 bool vnl_math_isinf(double);
00166 bool vnl_math_isinf(long double);
00167 #if !VCL_TEMPLATE_MATCHES_TOO_OFTEN
00168 template <class T> bool vnl_math_isinf(T);
00169 #endif
00170 
00171 // isfinite
00172 inline bool vnl_math_isfinite(char)               { return true; }
00173 inline bool vnl_math_isfinite(short)              { return true; }
00174 inline bool vnl_math_isfinite(int)                { return true; }
00175 inline bool vnl_math_isfinite(long)               { return true; }
00176 inline bool vnl_math_isfinite(signed char)        { return true; }
00177 inline bool vnl_math_isfinite(unsigned char)      { return true; }
00178 inline bool vnl_math_isfinite(unsigned short)     { return true; }
00179 inline bool vnl_math_isfinite(unsigned int)       { return true; }
00180 inline bool vnl_math_isfinite(unsigned long)      { return true; }
00181 #if VCL_HAS_LONG_LONG
00182 inline bool vnl_math_isfinite(long long)          { return true; }
00183 inline bool vnl_math_isfinite(unsigned long long) { return true; }
00184 #endif
00185 bool vnl_math_isfinite(float);
00186 bool vnl_math_isfinite(double);
00187 bool vnl_math_isfinite(long double);
00188 #if !VCL_TEMPLATE_MATCHES_TOO_OFTEN
00189 template <class T> bool vnl_math_isfinite(T);
00190 #endif
00191 
00192 
00193 
00194 // vnl_math_rnd_halfinttoeven  -- round towards nearest integer
00195 //         halfway cases are rounded towards the nearest even integer, e.g.
00196 //         vnl_math_rnd_halfinttoeven( 1.5) ==  2
00197 //         vnl_math_rnd_halfinttoeven(-1.5) == -2
00198 //         vnl_math_rnd_halfinttoeven( 2.5) ==  2
00199 //         vnl_math_rnd_halfinttoeven( 3.5) ==  4
00200 //
00201 // We assume that the rounding mode is not changed from the default
00202 // one (or at least that it is always restored to the default one).
00203 
00204 #if VNL_CONFIG_ENABLE_SSE2_ROUNDING // Fast sse2 implementation
00205 
00206 inline int vnl_math_rnd_halfinttoeven(float  x)
00207 {
00208 # if defined(VNL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00209   assert(fegetround()==FE_TONEAREST);
00210 # endif
00211   return _mm_cvtss_si32(_mm_set_ss(x));
00212 }
00213 inline int vnl_math_rnd_halfinttoeven(double  x)
00214 {
00215 # if defined(VNL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00216   assert(fegetround()==FE_TONEAREST);
00217 # endif
00218   return _mm_cvtsd_si32(_mm_set_sd(x));
00219 }
00220 
00221 #elif GCC_USE_FAST_IMPL // Fast gcc asm implementation
00222 
00223 inline int vnl_math_rnd_halfinttoeven(float  x)
00224 {
00225 # ifdef VNL_CHECK_FPU_ROUNDING_MODE
00226   assert(fegetround()==FE_TONEAREST);
00227 # endif
00228   int r;
00229   __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00230   return r;
00231 }
00232 inline int vnl_math_rnd_halfinttoeven(double  x)
00233 {
00234 # ifdef VNL_CHECK_FPU_ROUNDING_MODE
00235   assert(fegetround()==FE_TONEAREST);
00236 # endif
00237   int r;
00238   __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00239   return r;
00240 }
00241 
00242 #elif VC_USE_FAST_IMPL // Fast msvc asm implementation
00243 
00244 inline int vnl_math_rnd_halfinttoeven(float  x)
00245 {
00246   int r;
00247   __asm {
00248     fld x
00249     fistp r
00250   }
00251   return r;
00252 }
00253 inline int vnl_math_rnd_halfinttoeven(double  x)
00254 {
00255   int r;
00256   __asm {
00257     fld x
00258     fistp r
00259   }
00260   return r;
00261 }
00262 
00263 #else // Vanilla implementation
00264 
00265 inline int vnl_math_rnd_halfinttoeven(float  x)
00266 {
00267   if (x>=0.f)
00268   {
00269      x+=0.5f;
00270      const int r = static_cast<int>(x);
00271      if ( x != static_cast<float>(r) ) return r;
00272      return 2*(r/2);
00273   }
00274   else
00275   {
00276      x-=0.5f;
00277      const int r = static_cast<int>(x);
00278      if ( x != static_cast<float>(r) ) return r;
00279      return 2*(r/2);
00280   }
00281 }
00282 inline int vnl_math_rnd_halfinttoeven(double x)
00283 {
00284   if (x>=0.)
00285   {
00286      x+=0.5;
00287      const int r = static_cast<int>(x);
00288      if ( x != static_cast<double>(r) ) return r;
00289      return 2*(r/2);
00290   }
00291   else
00292   {
00293      x-=0.5;
00294      const int r = static_cast<int>(x);
00295      if ( x != static_cast<double>(r) ) return r;
00296      return 2*(r/2);
00297   }
00298 }
00299 
00300 #endif
00301 
00302 
00303 
00304 // vnl_math_rnd_halfintup  -- round towards nearest integer
00305 //         halfway cases are rounded upward, e.g.
00306 //         vnl_math_rnd_halfintup( 1.5) ==  2
00307 //         vnl_math_rnd_halfintup(-1.5) == -1
00308 //         vnl_math_rnd_halfintup( 2.5) ==  3
00309 //
00310 // Be careful: argument absolute value must be less than INT_MAX/2
00311 // for vnl_math_rnd_halfintup to be guaranteed to work.
00312 // We also assume that the rounding mode is not changed from the default
00313 // one (or at least that it is always restored to the default one).
00314 
00315 #if VNL_CONFIG_ENABLE_SSE2_ROUNDING || GCC_USE_FAST_IMPL || VC_USE_FAST_IMPL
00316 
00317 inline int vnl_math_rnd_halfintup(float  x) { return vnl_math_rnd_halfinttoeven(2*x+0.5f)>>1; }
00318 inline int vnl_math_rnd_halfintup(double  x) { return vnl_math_rnd_halfinttoeven(2*x+0.5)>>1; }
00319 
00320 #else // Vanilla implementation
00321 
00322 inline int vnl_math_rnd_halfintup(float  x)
00323 {
00324   x+=0.5f;
00325   return static_cast<int>(x>=0.f?x:(x==static_cast<int>(x)?x:x-1.f));
00326 }
00327 inline int vnl_math_rnd_halfintup(double x)
00328 {
00329   x+=0.5;
00330   return static_cast<int>(x>=0.?x:(x==static_cast<int>(x)?x:x-1.));
00331 }
00332 
00333 #endif
00334 
00335 
00336 
00337 // vnl_math_rnd  -- round towards nearest integer
00338 //         halfway cases such as 0.5 may be rounded either up or down
00339 //         so as to maximize the efficiency, e.g.
00340 //         vnl_math_rnd_halfinttoeven( 1.5) ==  1 or  2
00341 //         vnl_math_rnd_halfinttoeven(-1.5) == -2 or -1
00342 //         vnl_math_rnd_halfinttoeven( 2.5) ==  2 or  3
00343 //         vnl_math_rnd_halfinttoeven( 3.5) ==  3 or  4
00344 //
00345 // We assume that the rounding mode is not changed from the default
00346 // one (or at least that it is always restored to the default one).
00347 
00348 #if VNL_CONFIG_ENABLE_SSE2_ROUNDING || GCC_USE_FAST_IMPL || VC_USE_FAST_IMPL
00349 
00350 inline int vnl_math_rnd(float  x) { return vnl_math_rnd_halfinttoeven(x); }
00351 inline int vnl_math_rnd(double  x) { return vnl_math_rnd_halfinttoeven(x); }
00352 
00353 #else // Vanilla implementation
00354 
00355 inline int vnl_math_rnd(float  x) { return x>=0.f?static_cast<int>(x+.5f):static_cast<int>(x-.5f); }
00356 inline int vnl_math_rnd(double x) { return x>=0.0?static_cast<int>(x+0.5):static_cast<int>(x-0.5); }
00357 
00358 
00359 #endif
00360 
00361 
00362 
00363 // vnl_math_floor -- round towards minus infinity
00364 //
00365 // Be careful: argument absolute value must be less than INT_MAX/2
00366 // for vnl_math_floor to be guaranteed to work.
00367 // We also assume that the rounding mode is not changed from the default
00368 // one (or at least that it is always restored to the default one).
00369 
00370 #if VNL_CONFIG_ENABLE_SSE2_ROUNDING // Fast sse2 implementation
00371 
00372 inline int vnl_math_floor(float  x)
00373 {
00374 # if defined(VNL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00375   assert(fegetround()==FE_TONEAREST);
00376 # endif
00377    return _mm_cvtss_si32(_mm_set_ss(2*x-.5f))>>1;
00378 }
00379 inline int vnl_math_floor(double  x)
00380 {
00381 # if defined(VNL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00382   assert(fegetround()==FE_TONEAREST);
00383 # endif
00384    return _mm_cvtsd_si32(_mm_set_sd(2*x-.5))>>1;
00385 }
00386 
00387 #elif GCC_USE_FAST_IMPL // Fast gcc asm implementation
00388 
00389 inline int vnl_math_floor(float  x)
00390 {
00391 # ifdef VNL_CHECK_FPU_ROUNDING_MODE
00392   assert(fegetround()==FE_TONEAREST);
00393 # endif
00394   int r;
00395   x = 2*x-.5f;
00396   __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00397   return r>>1;
00398 }
00399 inline int vnl_math_floor(double  x)
00400 {
00401 # ifdef VNL_CHECK_FPU_ROUNDING_MODE
00402   assert(fegetround()==FE_TONEAREST);
00403 # endif
00404   int r;
00405   x = 2*x-.5;
00406   __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00407   return r>>1;
00408 }
00409 
00410 #elif VC_USE_FAST_IMPL // Fast msvc asm implementation
00411 
00412 inline int vnl_math_floor(float  x)
00413 {
00414   int r;
00415   x = 2*x-.5f;
00416   __asm {
00417     fld x
00418     fistp r
00419   }
00420   return r>>1;
00421 }
00422 inline int vnl_math_floor(double  x)
00423 {
00424   int r;
00425   x = 2*x-.5;
00426   __asm {
00427     fld x
00428     fistp r
00429   }
00430   return r>>1;
00431 }
00432 
00433 #else // Vanilla implementation
00434 
00435 inline int vnl_math_floor(float  x)
00436 {
00437   return static_cast<int>(x>=0.f?x:(x==static_cast<int>(x)?x:x-1.f));
00438 }
00439 inline int vnl_math_floor(double x)
00440 {
00441   return static_cast<int>(x>=0.0?x:(x==static_cast<int>(x)?x:x-1.0));
00442 }
00443 
00444 #endif
00445 
00446 
00447 
00448 // vnl_math_ceil -- round towards plus infinity
00449 //
00450 // Be careful: argument absolute value must be less than INT_MAX/2
00451 // for vnl_math_ceil to be guaranteed to work.
00452 // We also assume that the rounding mode is not changed from the default
00453 // one (or at least that it is always restored to the default one).
00454 
00455 #if VNL_CONFIG_ENABLE_SSE2_ROUNDING // Fast sse2 implementation
00456 
00457 inline int vnl_math_ceil(float  x)
00458 {
00459 # if defined(VNL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00460   assert(fegetround()==FE_TONEAREST);
00461 # endif
00462    return -(_mm_cvtss_si32(_mm_set_ss(-.5f-2*x))>>1);
00463 }
00464 inline int vnl_math_ceil(double  x)
00465 {
00466 # if defined(VNL_CHECK_FPU_ROUNDING_MODE) && defined(__GNUC__)
00467   assert(fegetround()==FE_TONEAREST);
00468 # endif
00469    return -(_mm_cvtsd_si32(_mm_set_sd(-.5-2*x))>>1);
00470 }
00471 
00472 #elif GCC_USE_FAST_IMPL // Fast gcc asm implementation
00473 
00474 inline int vnl_math_ceil(float  x)
00475 {
00476 # ifdef VNL_CHECK_FPU_ROUNDING_MODE
00477   assert(fegetround()==FE_TONEAREST);
00478 # endif
00479   int r;
00480   x = -.5f-2*x;
00481   __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00482   return -(r>>1);
00483 }
00484 inline int vnl_math_ceil(double  x)
00485 {
00486 # ifdef VNL_CHECK_FPU_ROUNDING_MODE
00487   assert(fegetround()==FE_TONEAREST);
00488 # endif
00489   int r;
00490   x = -.5-2*x;
00491   __asm__ __volatile__ ("fistpl %0" : "=m"(r) : "t"(x) : "st");
00492   return -(r>>1);
00493 }
00494 
00495 #elif VC_USE_FAST_IMPL // Fast msvc asm implementation
00496 
00497 inline int vnl_math_ceil(float  x)
00498 {
00499   int r;
00500   x = -.5f-2*x;
00501   __asm {
00502     fld x
00503     fistp r
00504   }
00505   return -(r>>1);
00506 }
00507 inline int vnl_math_ceil(double  x)
00508 {
00509   int r;
00510   x = -.5-2*x;
00511   __asm {
00512     fld x
00513     fistp r
00514   }
00515   return -(r>>1);
00516 }
00517 
00518 #else // Vanilla implementation
00519 
00520 inline int vnl_math_ceil(float  x)
00521 {
00522   return static_cast<int>(x<0.f?x:(x==static_cast<int>(x)?x:x+1.f));
00523 }
00524 inline int vnl_math_ceil(double x)
00525 {
00526   return static_cast<int>(x<0.0?x:(x==static_cast<int>(x)?x:x+1.0));
00527 }
00528 
00529 #endif
00530 
00531 
00532 
00533 // abs
00534 inline bool               vnl_math_abs(bool x)               { return x; }
00535 inline unsigned char      vnl_math_abs(unsigned char x)      { return x; }
00536 inline unsigned char      vnl_math_abs(signed char x)        { return x < 0 ? static_cast<unsigned char>(-x) : x; }
00537 inline unsigned char      vnl_math_abs(char x)               { return static_cast<unsigned char>(x); }
00538 inline unsigned short     vnl_math_abs(short x)              { return x < 0 ? static_cast<unsigned short>(-x) : x; }
00539 inline unsigned short     vnl_math_abs(unsigned short x)     { return x; }
00540 inline unsigned int       vnl_math_abs(int x)                { return x < 0 ? -x : x; }
00541 inline unsigned int       vnl_math_abs(unsigned int x)       { return x; }
00542 inline unsigned long      vnl_math_abs(long x)               { return x < 0L ? -x : x; }
00543 inline unsigned long      vnl_math_abs(unsigned long x)      { return x; }
00544 #if VCL_HAS_LONG_LONG
00545 inline unsigned long long vnl_math_abs(long long x)          { return x < 0LL ? -x : x; }
00546 inline unsigned long long vnl_math_abs(unsigned long long x) { return x; }
00547 #endif
00548 inline float              vnl_math_abs(float x)              { return x < 0.0f ? -x : x; }
00549 inline double             vnl_math_abs(double x)             { return x < 0.0 ? -x : x; }
00550 inline long double        vnl_math_abs(long double x)        { return x < 0.0 ? -x : x; }
00551 
00552 // max
00553 inline int                vnl_math_max(int x, int y)                               { return (x > y) ? x : y; }
00554 inline unsigned int       vnl_math_max(unsigned int x, unsigned int y)             { return (x > y) ? x : y; }
00555 inline long               vnl_math_max(long x, long y)                             { return (x > y) ? x : y; }
00556 inline unsigned long      vnl_math_max(unsigned long x, unsigned long y)           { return (x > y) ? x : y; }
00557 #if VCL_HAS_LONG_LONG
00558 inline long long          vnl_math_max(long long x, long long y)                   { return (x > y) ? x : y; }
00559 inline unsigned long long vnl_math_max(unsigned long long x, unsigned long long y) { return (x > y) ? x : y; }
00560 #endif
00561 inline float              vnl_math_max(float x, float y)                           { return (x < y) ? y : x; }
00562 inline double             vnl_math_max(double x, double y)                         { return (x < y) ? y : x; }
00563 
00564 // min
00565 inline int                vnl_math_min(int x, int y)                               { return (x < y) ? x : y; }
00566 inline unsigned int       vnl_math_min(unsigned int x, unsigned int y)             { return (x < y) ? x : y; }
00567 inline long               vnl_math_min(long x, long y)                             { return (x < y) ? x : y; }
00568 inline unsigned long      vnl_math_min(unsigned long x, unsigned long y)           { return (x < y) ? x : y; }
00569 #if VCL_HAS_LONG_LONG
00570 inline long long          vnl_math_min(long long x, long long y)                   { return (x < y) ? x : y; }
00571 inline unsigned long long vnl_math_min(unsigned long long x, unsigned long long y) { return (x < y) ? x : y; }
00572 #endif
00573 inline float              vnl_math_min(float x, float y)                           { return (x > y) ? y : x; }
00574 inline double             vnl_math_min(double x, double y)                         { return (x > y) ? y : x; }
00575 
00576 // sqr (square)
00577 inline bool               vnl_math_sqr(bool x)               { return x; }
00578 inline int                vnl_math_sqr(int x)                { return x*x; }
00579 inline unsigned int       vnl_math_sqr(unsigned int x)       { return x*x; }
00580 inline long               vnl_math_sqr(long x)               { return x*x; }
00581 inline unsigned long      vnl_math_sqr(unsigned long x)      { return x*x; }
00582 #if VCL_HAS_LONG_LONG
00583 inline long long          vnl_math_sqr(long long x)          { return x*x; }
00584 inline unsigned long long vnl_math_sqr(unsigned long long x) { return x*x; }
00585 #endif
00586 inline float              vnl_math_sqr(float x)              { return x*x; }
00587 inline double             vnl_math_sqr(double x)             { return x*x; }
00588 
00589 // cube
00590 inline bool               vnl_math_cube(bool x)               { return x; }
00591 inline int                vnl_math_cube(int x)                { return x*x*x; }
00592 inline unsigned int       vnl_math_cube(unsigned int x)       { return x*x*x; }
00593 inline long               vnl_math_cube(long x)               { return x*x*x; }
00594 inline unsigned long      vnl_math_cube(unsigned long x)      { return x*x*x; }
00595 #if VCL_HAS_LONG_LONG
00596 inline long long          vnl_math_cube(long long x)          { return x*x*x; }
00597 inline unsigned long long vnl_math_cube(unsigned long long x) { return x*x*x; }
00598 #endif
00599 inline float              vnl_math_cube(float x)              { return x*x*x; }
00600 inline double             vnl_math_cube(double x)             { return x*x*x; }
00601 
00602 // sgn (sign in -1, 0, +1)
00603 inline int vnl_math_sgn(int x)       { return x?((x>0)?1:-1):0; }
00604 inline int vnl_math_sgn(long x)      { return x?((x>0)?1:-1):0; }
00605 #if VCL_HAS_LONG_LONG
00606 inline int vnl_math_sgn(long long x) { return x?((x>0)?1:-1):0; }
00607 #endif
00608 inline int vnl_math_sgn(float x)     { return (x != 0)?((x>0)?1:-1):0; }
00609 inline int vnl_math_sgn(double x)    { return (x != 0)?((x>0)?1:-1):0; }
00610 
00611 // sgn0 (sign in -1, +1 only, useful for reals)
00612 inline int vnl_math_sgn0(int x)         { return (x>=0)?1:-1; }
00613 inline int vnl_math_sgn0(long x)        { return (x>=0)?1:-1; }
00614 #if VCL_HAS_LONG_LONG
00615 inline int vnl_math_sgn0(long long x)   { return (x>=0)?1:-1; }
00616 #endif
00617 inline int vnl_math_sgn0(float x)       { return (x>=0)?1:-1; }
00618 inline int vnl_math_sgn0(double x)      { return (x>=0)?1:-1; }
00619 
00620 // squared_magnitude
00621 inline unsigned int       vnl_math_squared_magnitude(char               x) { return int(x)*int(x); }
00622 inline unsigned int       vnl_math_squared_magnitude(unsigned char      x) { return int(x)*int(x); }
00623 inline unsigned int       vnl_math_squared_magnitude(int                x) { return x*x; }
00624 inline unsigned int       vnl_math_squared_magnitude(unsigned int       x) { return x*x; }
00625 inline unsigned long      vnl_math_squared_magnitude(long               x) { return x*x; }
00626 inline unsigned long      vnl_math_squared_magnitude(unsigned long      x) { return x*x; }
00627 #if VCL_HAS_LONG_LONG
00628 inline unsigned long long vnl_math_squared_magnitude(long long          x) { return x*x; }
00629 inline unsigned long long vnl_math_squared_magnitude(unsigned long long x) { return x*x; }
00630 #endif
00631 inline float              vnl_math_squared_magnitude(float              x) { return x*x; }
00632 inline double             vnl_math_squared_magnitude(double             x) { return x*x; }
00633 inline long double        vnl_math_squared_magnitude(long double        x) { return x*x; }
00634 
00635 // cuberoot
00636 inline float  vnl_math_cuberoot(float  a) { return float((a<0) ? -vcl_exp(vcl_log(-a)/3) : vcl_exp(vcl_log(a)/3)); }
00637 inline double vnl_math_cuberoot(double a) { return       (a<0) ? -vcl_exp(vcl_log(-a)/3) : vcl_exp(vcl_log(a)/3); }
00638 
00639 // hypotenuse
00640 inline double      vnl_math_hypot(int         x, int         y) { return vcl_sqrt(double(x*x + y*y)); }
00641 inline float       vnl_math_hypot(float       x, float       y) { return float( vcl_sqrt(double(x*x + y*y)) ); }
00642 inline double      vnl_math_hypot(double      x, double      y) { return vcl_sqrt(x*x + y*y); }
00643 inline long double vnl_math_hypot(long double x, long double y) { return vcl_sqrt(x*x + y*y); }
00644 
00645 #endif // vnl_math_h_