include/cinder/CinderMath.h
Go to the documentation of this file.
00001 /*
00002  Copyright (c) 2010, The Barbarian Group
00003  All rights reserved.
00004 
00005  Portions Copyright (c) 2004, Laminar Research.
00006 
00007  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
00008  the following conditions are met:
00009 
00010     * Redistributions of source code must retain the above copyright notice, this list of conditions and
00011     the following disclaimer.
00012     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
00013     the following disclaimer in the documentation and/or other materials provided with the distribution.
00014 
00015  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
00016  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00017  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00018  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
00019  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00020  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00021  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00022  POSSIBILITY OF SUCH DAMAGE.
00023 */
00024 
00025 #pragma once
00026 
00027 #include "cinder/Cinder.h"
00028 #include <cmath>
00029 #include <climits>
00030 #if defined( CINDER_MSW )
00031     #undef min
00032     #undef max
00033     #include <float.h>
00034 #endif
00035 
00036 namespace cinder {
00037 
00038 template<typename T>
00039 struct math
00040 {
00041     static T    acos  (T x)     {return ::acos (double(x));}
00042     static T    asin  (T x)     {return ::asin (double(x));}
00043     static T    atan  (T x)     {return ::atan (double(x));}
00044     static T    atan2 (T y, T x)    {return ::atan2 (double(y), double(x));}
00045     static T    cos   (T x)     {return ::cos (double(x));}
00046     static T    sin   (T x)     {return ::sin (double(x));}
00047     static T    tan   (T x)     {return ::tan (double(x));}
00048     static T    cosh  (T x)     {return ::cosh (double(x));}
00049     static T    sinh  (T x)     {return ::sinh (double(x));}
00050     static T    tanh  (T x)     {return ::tanh (double(x));}
00051     static T    exp   (T x)     {return ::exp (double(x));}
00052     static T    log   (T x)     {return ::log (double(x));}
00053     static T    log10 (T x)     {return ::log10 (double(x));}
00054     static T    modf  (T x, T *iptr)
00055     {
00056         double ival;
00057         T rval( ::modf (double(x),&ival));
00058     *iptr = ival;
00059     return rval;
00060     }
00061     static T    pow   (T x, T y)    {return ::pow (double(x), double(y));}
00062     static T    sqrt  (T x)     {return ::sqrt (double(x));}
00063 #if defined( _MSC_VER )
00064     static T    cbrt( T x )     { return ( x > 0 ) ? (::pow( x, 1.0 / 3.0 )) : (- ::pow( -x, 1.0 / 3.0 ) ); }
00065 #else
00066     static T    cbrt( T x )     { return ::cbrt( x ); }
00067 #endif
00068     static T    ceil  (T x)     {return ::ceil (double(x));}
00069     static T    abs  (T x)      {return ::fabs (double(x));}
00070     static T    floor (T x)     {return ::floor (double(x));}
00071     static T    fmod  (T x, T y)    {return ::fmod (double(x), double(y));}
00072     static T    hypot (T x, T y)    {return ::hypot (double(x), double(y));}
00073     static T    signum (T x)        {return ( x >0.0 ) ? 1.0 : ( ( x < 0.0 ) ? -1.0 : 0.0 ); }
00074     static T    min(T x, T y)               {return ( x < y ) ? x : y; }
00075     static T    max(T x, T y)               {return ( x > y ) ? x : y; }
00076     static T    clamp(T x, T min=0, T max=1)    {return ( x < min ) ? min : ( ( x > max ) ? max : x );}
00077 };
00078 
00079 
00080 template<>
00081 struct math<float>
00082 {
00083     static float    acos  (float x)         {return ::acosf (x);}
00084     static float    asin  (float x)         {return ::asinf (x);}
00085     static float    atan  (float x)         {return ::atanf (x);}
00086     static float    atan2 (float y, float x)    {return ::atan2f (y, x);}
00087     static float    cos   (float x)         {return ::cosf (x);}
00088     static float    sin   (float x)         {return ::sinf (x);}
00089     static float    tan   (float x)         {return ::tanf (x);}
00090     static float    cosh  (float x)         {return ::coshf (x);}
00091     static float    sinh  (float x)         {return ::sinhf (x);}
00092     static float    tanh  (float x)         {return ::tanhf (x);}
00093     static float    exp   (float x)         {return ::expf (x);}
00094     static float    log   (float x)         {return ::logf (x);}
00095     static float    log10 (float x)         {return ::log10f (x);}
00096     static float    modf  (float x, float *y)   {return ::modff (x, y);}
00097     static float    pow   (float x, float y)    {return ::powf (x, y);}
00098     static float    sqrt  (float x)         {return ::sqrtf (x);}
00099 #if defined( _MSC_VER )
00100     static float    cbrt( float x )     { return ( x > 0 ) ? (::powf( x, 1.0f / 3.0f )) : (- ::powf( -x, 1.0f / 3.0f ) ); }
00101 #else
00102     static float    cbrt  (float x)         { return ::cbrtf( x ); }    
00103 #endif
00104     static float    ceil  (float x)         {return ::ceilf (x);}
00105     static float    abs   (float x)         {return ::fabsf (x);}
00106     static float    floor (float x)         {return ::floorf (x);}
00107     static float    fmod  (float x, float y)    {return ::fmodf (x, y);}
00108     #if !defined(_MSC_VER)
00109     static float    hypot (float x, float y)    {return ::hypotf (x, y);}
00110     #else
00111     static float hypot (float x, float y)   {return ::sqrtf(x*x + y*y);}
00112     #endif
00113     static float signum (float x)       {return ( x > 0.0f ) ? 1.0f : ( ( x < 0.0f ) ? -1.0f : 0.0f ); }
00114     static float min(float x, float y)                  {return ( x < y ) ? x : y; }
00115     static float max(float x, float y)                  {return ( x > y ) ? x : y; }
00116     static float clamp(float x, float min=0, float max=1)   {return ( x < min ) ? min : ( ( x > max ) ? max : x );}
00117 };
00118 
00119 #ifndef M_PI
00120 #define M_PI           3.14159265358979323846
00121 #endif
00122 
00123 const double EPSILON_VALUE = 4.37114e-05;
00124 #define EPSILON EPSILON_VALUE
00125 
00126 inline float toRadians( float x )
00127 {
00128     return x * 0.017453292519943295769f; // ( x * PI / 180 )
00129 }
00130 
00131 inline double toRadians( double x )
00132 {
00133     return x * 0.017453292519943295769; // ( x * PI / 180 )
00134 }
00135 
00136 inline float toDegrees( float x )
00137 {
00138     return x * 57.295779513082321f; // ( x * 180 / PI )
00139 }
00140 
00141 inline double toDegrees( double x )
00142 {
00143     return x * 57.295779513082321; // ( x * 180 / PI )
00144 }
00145 
00146 template<typename T, typename L>
00147 T lerp( const T &a, const T &b, L factor )
00148 {
00149     return a + ( b - a ) * factor;
00150 }
00151 
00152 template<typename T>
00153 T lmap(T val, T inMin, T inMax, T outMin, T outMax)
00154 {
00155     return outMin + (outMax - outMin) * ((val - inMin) / (inMax - inMin));
00156 }
00157 
00158 template<typename T, typename L>
00159 T bezierInterp( T a, T b, T c, T d, L t)
00160 {
00161     L t1 = static_cast<L>(1.0) - t;
00162     return a*(t1*t1*t1) + b*(3*t*t1*t1) + c*(3*t*t*t1) + d*(t*t*t);
00163 }
00164 
00165 template<typename T, typename L>
00166 T bezierInterpRef( const T &a, const T &b, const T &c, const T &d, L t)
00167 {
00168     L t1 = static_cast<L>(1.0) - t;
00169     return a*(t1*t1*t1) + b*(3*t*t1*t1) + c*(3*t*t*t1) + d*(t*t*t);
00170 }
00171 
00172 template<typename T>
00173 T constrain( T val, T minVal, T maxVal )
00174 {
00175     if( val < minVal ) return minVal;
00176     else if( val > maxVal ) return maxVal;
00177     else return val;
00178 }
00179 
00180 // Don Hatch's version of sin(x)/x, which is accurate for very small x.
00181 // Returns 1 for x == 0.
00182 template <class T>
00183 T sinx_over_x( T x )
00184 {
00185     if( x * x < 1.19209290E-07F )
00186     return T( 1 );
00187     else
00188     return math<T>::sin( x ) / x;
00189 }
00190 
00191 // There are faster techniques for this, but this is portable
00192 inline uint32_t log2floor( uint32_t x )
00193 {
00194     uint32_t result = 0;
00195     while( x >>= 1 )
00196         ++result;
00197 
00198     return result;
00199 }
00200 
00201 inline uint32_t log2ceil( uint32_t x )
00202 {
00203     uint32_t isNotPowerOf2 = (x & (x - 1));
00204     return ( isNotPowerOf2 ) ? (log2floor( x ) + 1) : log2floor( x );
00205 }
00206 
00207 inline uint32_t nextPowerOf2( uint32_t x )
00208 {
00209     x |= (x >> 1);
00210     x |= (x >> 2);
00211     x |= (x >> 4);
00212     x |= (x >> 8);
00213     x |= (x >> 16);
00214     return(x+1);
00215 }
00216 
00217 template<typename T>
00218 inline int solveLinear( T a, T b, T result[1] )
00219 {
00220     if( a == 0 ) return (b == 0 ? -1 : 0 );
00221     result[0] = -b / a;
00222     return 1;
00223 }
00224 
00225 template<typename T>
00226 inline int solveQuadratic( T a, T b, T c, T result[2] )
00227 {
00228     if( a == 0 ) return solveLinear( b, c, result );
00229 
00230     T radical = b * b - 4 * a * c;
00231     if( radical < 0 ) return 0;
00232 
00233     if( radical == 0 ) {
00234         result[0] = -b / (2 * a);
00235         return 1;
00236     }
00237 
00238     T srad = math<T>::sqrt( radical );
00239     result[0] = ( -b - srad ) / (2 * a);
00240     result[1] = ( -b + srad ) / (2 * a);
00241     if( a < 0 ) std::swap( result[0], result[1] );
00242     return 2;
00243 }
00244 
00245 template<typename T>
00246 int solveCubic( T a, T b, T c, T d, T result[3] );
00247 
00248 } // namespace cinder
00249 
00250 #if defined( _MSC_VER )
00251 namespace std {
00252     inline bool isfinite( float arg ) { return _finite( arg ) != 0; }
00253     inline bool isfinite( double arg ) { return _finite( arg ) != 0; }
00254 }
00255 #endif