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 <math.h>
00029 #include <limits.h>
00030 #if defined( CINDER_MSW )
00031 #undef min
00032 #undef max
00033 #endif
00034 
00035 namespace cinder {
00036 
00037 template<typename T>
00038 struct math
00039 {
00040     static T    acos  (T x)     {return ::acos (double(x));}
00041     static T    asin  (T x)     {return ::asin (double(x));}
00042     static T    atan  (T x)     {return ::atan (double(x));}
00043     static T    atan2 (T x, T y)    {return ::atan2 (double(x), double(y));}
00044     static T    cos   (T x)     {return ::cos (double(x));}
00045     static T    sin   (T x)     {return ::sin (double(x));}
00046     static T    tan   (T x)     {return ::tan (double(x));}
00047     static T    cosh  (T x)     {return ::cosh (double(x));}
00048     static T    sinh  (T x)     {return ::sinh (double(x));}
00049     static T    tanh  (T x)     {return ::tanh (double(x));}
00050     static T    exp   (T x)     {return ::exp (double(x));}
00051     static T    log   (T x)     {return ::log (double(x));}
00052     static T    log10 (T x)     {return ::log10 (double(x));}
00053     static T    modf  (T x, T *iptr)
00054     {
00055         double ival;
00056         T rval( ::modf (double(x),&ival));
00057     *iptr = ival;
00058     return rval;
00059     }
00060     static T    pow   (T x, T y)    {return ::pow (double(x), double(y));}
00061     static T    sqrt  (T x)     {return ::sqrt (double(x));}
00062 #if defined( _MSC_VER )
00063     static T    cbrt( T x )     { return ( x > 0 ) ? (::pow( x, 1.0 / 3.0 )) : (- ::pow( -x, 1.0 / 3.0 ) ); }
00064 #else
00065     static T    cbrt( T x )     { return ::cbrt( x ); }
00066 #endif
00067     static T    ceil  (T x)     {return ::ceil (double(x));}
00068     static T    abs  (T x)      {return ::fabs (double(x));}
00069     static T    floor (T x)     {return ::floor (double(x));}
00070     static T    fmod  (T x, T y)    {return ::fmod (double(x), double(y));}
00071     static T    hypot (T x, T y)    {return ::hypot (double(x), double(y));}
00072     static T    signum (T x)        {return ( x >0.0 ) ? 1.0 : ( ( x < 0.0 ) ? -1.0 : 0.0 ); }
00073     static T    min(T x, T y)               {return ( x < y ) ? x : y; }
00074     static T    max(T x, T y)               {return ( x > y ) ? x : y; }
00075     static T    clamp(T x, T min=0, T max=1)    {return ( x < min ) ? min : ( ( x > max ) ? max : x );}
00076 };
00077 
00078 
00079 template<>
00080 struct math<float>
00081 {
00082     static float    acos  (float x)         {return ::acosf (x);}
00083     static float    asin  (float x)         {return ::asinf (x);}
00084     static float    atan  (float x)         {return ::atanf (x);}
00085     static float    atan2 (float x, float y)    {return ::atan2f (x, y);}
00086     static float    cos   (float x)         {return ::cosf (x);}
00087     static float    sin   (float x)         {return ::sinf (x);}
00088     static float    tan   (float x)         {return ::tanf (x);}
00089     static float    cosh  (float x)         {return ::coshf (x);}
00090     static float    sinh  (float x)         {return ::sinhf (x);}
00091     static float    tanh  (float x)         {return ::tanhf (x);}
00092     static float    exp   (float x)         {return ::expf (x);}
00093     static float    log   (float x)         {return ::logf (x);}
00094     static float    log10 (float x)         {return ::log10f (x);}
00095     static float    modf  (float x, float *y)   {return ::modff (x, y);}
00096     static float    pow   (float x, float y)    {return ::powf (x, y);}
00097     static float    sqrt  (float x)         {return ::sqrtf (x);}
00098 #if defined( _MSC_VER )
00099     static float    cbrt( float x )     { return ( x > 0 ) ? (::powf( x, 1.0f / 3.0f )) : (- ::powf( -x, 1.0f / 3.0f ) ); }
00100 #else
00101     static float    cbrt  (float x)         { return ::cbrtf( x ); }    
00102 #endif
00103     static float    ceil  (float x)         {return ::ceilf (x);}
00104     static float    abs   (float x)         {return ::fabsf (x);}
00105     static float    floor (float x)         {return ::floorf (x);}
00106     static float    fmod  (float x, float y)    {return ::fmodf (x, y);}
00107     #if !defined(_MSC_VER)
00108     static float    hypot (float x, float y)    {return ::hypotf (x, y);}
00109     #else
00110     static float hypot (float x, float y)   {return ::sqrtf(x*x + y*y);}
00111     #endif
00112     static float signum (float x)       {return ( x > 0.0f ) ? 1.0f : ( ( x < 0.0f ) ? -1.0f : 0.0f ); }
00113     static float min(float x, float y)                  {return ( x < y ) ? x : y; }
00114     static float max(float x, float y)                  {return ( x > y ) ? x : y; }
00115     static float clamp(float x, float min=0, float max=1)   {return ( x < min ) ? min : ( ( x > max ) ? max : x );}
00116 };
00117 
00118 #ifndef M_PI
00119 #define M_PI           3.14159265358979323846
00120 #endif
00121 
00122 const double EPSILON_VALUE = 4.37114e-05;
00123 #define EPSILON EPSILON_VALUE
00124 
00125 inline float toRadians( float x )
00126 {
00127     return x * 0.017453292519943295769f; // ( x * PI / 180 )
00128 }
00129 
00130 inline double toRadians( double x )
00131 {
00132     return x * 0.017453292519943295769; // ( x * PI / 180 )
00133 }
00134 
00135 inline float toDegrees( float x )
00136 {
00137     return x * 57.295779513082321f; // ( x * 180 / PI )
00138 }
00139 
00140 inline double toDegrees( double x )
00141 {
00142     return x * 57.295779513082321; // ( x * 180 / PI )
00143 }
00144 
00145 template<typename T, typename L>
00146 T lerp( const T &a, const T &b, L factor )
00147 {
00148     return a + ( b - a ) * factor;
00149 }
00150 
00151 template<typename T>
00152 T lmap(T val, T inMin, T inMax, T outMin, T outMax)
00153 {
00154     return outMin + (outMax - outMin) * ((val - inMin) / (inMax - inMin));
00155 }
00156 
00157 template<typename T, typename L>
00158 T bezierInterp( T a, T b, T c, T d, L t)
00159 {
00160     L t1 = static_cast<L>(1.0) - t;
00161     return a*(t1*t1*t1) + b*(3*t*t1*t1) + c*(3*t*t*t1) + d*(t*t*t);
00162 }
00163 
00164 template<typename T, typename L>
00165 T bezierInterpRef( const T &a, const T &b, const T &c, const T &d, L t)
00166 {
00167     L t1 = static_cast<L>(1.0) - t;
00168     return a*(t1*t1*t1) + b*(3*t*t1*t1) + c*(3*t*t*t1) + d*(t*t*t);
00169 }
00170 
00171 template<typename T>
00172 T constrain( T val, T minVal, T maxVal )
00173 {
00174     if( val < minVal ) return minVal;
00175     else if( val > maxVal ) return maxVal;
00176     else return val;
00177 }
00178 
00179 // Don Hatch's version of sin(x)/x, which is accurate for very small x.
00180 // Returns 1 for x == 0.
00181 template <class T>
00182 T sinx_over_x( T x )
00183 {
00184     if( x * x < 1.19209290E-07F )
00185     return T( 1 );
00186     else
00187     return math<T>::sin( x ) / x;
00188 }
00189 
00190 // There are faster techniques for this, but this is portable
00191 inline uint32_t log2floor( uint32_t x )
00192 {
00193     uint32_t result = 0;
00194     while( x >>= 1 )
00195         ++result;
00196 
00197     return result;
00198 }
00199 
00200 inline uint32_t log2ceil( uint32_t x )
00201 {
00202     uint32_t isNotPowerOf2 = (x & (x - 1));
00203     return ( isNotPowerOf2 ) ? (log2floor( x ) + 1) : log2floor( x );
00204 }
00205 
00206 inline uint32_t nextPowerOf2( uint32_t x )
00207 {
00208     x |= (x >> 1);
00209     x |= (x >> 2);
00210     x |= (x >> 4);
00211     x |= (x >> 8);
00212     x |= (x >> 16);
00213     return(x+1);
00214 }
00215 
00216 template<typename T>
00217 inline int solveLinear( T a, T b, T result[1] )
00218 {
00219     if( a == 0 ) return (b == 0 ? -1 : 0 );
00220     result[0] = -b / a;
00221     return 1;
00222 }
00223 
00224 template<typename T>
00225 inline int solveQuadratic( T a, T b, T c, T result[2] )
00226 {
00227     if( a == 0 ) return solveLinear( b, c, result );
00228 
00229     T radical = b * b - 4 * a * c;
00230     if( radical < 0 ) return 0;
00231 
00232     if( radical == 0 ) {
00233         result[0] = -b / (2 * a);
00234         return 1;
00235     }
00236 
00237     T srad = math<T>::sqrt( radical );
00238     result[0] = ( -b - srad ) / (2 * a);
00239     result[1] = ( -b + srad ) / (2 * a);
00240     if( a < 0 ) std::swap( result[0], result[1] );
00241     return 2;
00242 }
00243 
00244 template<typename T>
00245 int solveCubic( T a, T b, T c, T d, T result[3] );
00246 
00247 } // namespace cinder