functions.H

00001 /*
00002  * This file is part of the "Archon" framework.
00003  * (http://files3d.sourceforge.net)
00004  *
00005  * Copyright © 2002 by Kristian Spangsege and Brian Kristiansen.
00006  *
00007  * Permission to use, copy, modify, and distribute this software and
00008  * its documentation under the terms of the GNU General Public License is
00009  * hereby granted. No representations are made about the suitability of
00010  * this software for any purpose. It is provided "as is" without express
00011  * or implied warranty. See the GNU General Public License
00012  * (http://www.gnu.org/copyleft/gpl.html) for more details.
00013  *
00014  * The characters in this file are ISO8859-1 encoded.
00015  *
00016  * The documentation in this file is in "Doxygen" style
00017  * (http://www.doxygen.org).
00018  */
00019 
00020 #ifndef ARCHON_MATH_FUNCTIONS_H
00021 #define ARCHON_MATH_FUNCTIONS_H
00022 
00023 #include <cmath>
00024 
00025 namespace Archon
00026 {
00030   namespace Math
00031   {
00043     template<typename T> inline T clamp(T v, T l, T h)
00044     {
00045       return v < l ? l : v > h ? h : v;
00046     }
00047 
00069     template<typename T> inline T modulo(T x, T m);
00070 
00081     template<typename T> inline T modulo(T x, T m, long &n);
00082 
00086     template<typename T>
00087     inline T sq(T v)
00088     {
00089       return v*v;
00090     }
00091 
00095     template<typename T>
00096     inline T inv(T v)
00097     {
00098       return 1/v;
00099     }
00100 
00104     template<typename T>
00105     inline T length(T x, T y)
00106     {
00107       return sqrt(sq(x) + sq(y));
00108     }
00109 
00125     template<typename T>
00126     inline T angle(T x, T y)
00127     {
00128       if(x==0) return y==0 ? 0 : y>0 ? M_PI/2 : 3*M_PI/2;
00129       double a = atan(y/x);
00130       return x < 0 ? M_PI + a : y < 0 ? 2*M_PI + a : a;
00131     }
00132 
00139     template<typename T>
00140     inline T linInterp(double x, double x1, double x2, T y1, T y2)
00141     {
00142       return y1 + (y2-y1)*(x-x1)/(x2-x1);
00143     }
00144 
00145     template<typename T>
00146     void sort3(T x0, T x1, T x2, int &i0, int &i1, int &i2)
00147     {
00148       if(x1 > x0)
00149       {
00150         if(x2 > x1)      { i0 = 2; i1 = 1; i2 = 0; }
00151         else if(x2 > x0) { i0 = 1; i1 = 2; i2 = 0; }
00152         else             { i0 = 1; i1 = 0; i2 = 2; }
00153       }
00154       else
00155       {
00156         if(x2 > x0)      { i0 = 2; i1 = 0; i2 = 1; }
00157         else if(x2 > x1) { i0 = 0; i1 = 2; i2 = 1; }
00158         else             { i0 = 0; i1 = 1; i2 = 2; }
00159       }
00160     }
00161 
00162 
00163     template<> inline short modulo(short x, short m)
00164     {
00165       if(x<0 || x>=m) { x%=m; if(x<0) x+=m; }
00166       return x;
00167     }
00168 
00169     template<> inline int modulo(int x, int m)
00170     {
00171       if(x<0 || x>=m) { x%=m; if(x<0) x+=m; }
00172       return x;
00173     }
00174 
00175     template<> inline long modulo(long x, long m)
00176     {
00177       if(x<0 || x>=m) { x%=m; if(x<0) x+=m; }
00178       return x;
00179     }
00180 
00181     template<> inline float modulo(float x, float m)
00182     {
00183       if(0<=x && x<m) return x;
00184       x=fmodf(x, m);
00185       if(x<0) x+=m;
00186       // Prevent numeric instability from breaking 0 <= x < m.
00187       return 0<=x && x<m ? x : 0;
00188     }
00189 
00190     template<> inline double modulo(double x, double m)
00191     {
00192       if(0<=x && x<m) return x;
00193       x=fmod(x, m);
00194       if(x<0) x+=m;
00195       // Prevent numeric instability from breaking 0 <= x < m.
00196       return 0<=x && x<m ? x : 0;
00197     }
00198 
00199     template<> inline long double modulo(long double x, long double m)
00200     {
00201       if(0<=x && x<m) return x;
00202       x=fmodl(x, m);
00203       if(x<0) x+=m;
00204       // Prevent numeric instability from breaking 0 <= x < m.
00205       return 0<=x && x<m ? x : 0;
00206     }
00207 
00208     template<> inline short modulo(short x, short m, long &n)
00209     {
00210       if(x<0 || x>=m)
00211       {
00212         div_t d = div(x, m);
00213         x = d.rem;
00214         n = d.quot;
00215         if(x<0)
00216         {
00217           x+=m;
00218           --n;
00219         }
00220       }
00221       else n = 0;
00222       return x;
00223     }
00224 
00225     template<> inline int modulo(int x, int m, long &n)
00226     {
00227       if(x<0 || x>=m)
00228       {
00229         div_t d = div(x, m);
00230         x = d.rem;
00231         n = d.quot;
00232         if(x<0)
00233         {
00234           x+=m;
00235           --n;
00236         }
00237       }
00238       else n = 0;
00239       return x;
00240     }
00241 
00242     template<> inline long modulo(long x, long m, long &n)
00243     {
00244       if(x<0 || x>=m)
00245       {
00246         ldiv_t d = ldiv(x, m);
00247         x = d.rem;
00248         n = d.quot;
00249         if(x<0)
00250         {
00251           x+=m;
00252           --n;
00253         }
00254       }
00255       else n = 0;
00256       return x;
00257     }
00258 
00259     template<> inline float modulo(float x, float m, long &n)
00260     {
00261       // Be sure not to break  0 <= x < m.
00262       float y = modulo(x, m);
00263       n = static_cast<long>((x-y)/m + 0.5);
00264       return y;
00265     }
00266 
00267     template<> inline double modulo(double x, double m, long &n)
00268     {
00269       // Be sure not to break  0 <= x < m.
00270       double y = modulo(x, m);
00271       n = static_cast<long>((x-y)/m + 0.5);
00272       return y;
00273     }
00274 
00275     template<> inline long double modulo(long double x, long double m, long &n)
00276     {
00277       // Be sure not to break  0 <= x < m.
00278       long double y = modulo(x, m);
00279       n = static_cast<long>((x-y)/m + 0.5);
00280       return y;
00281     }
00282 
00283 
00284   }
00285 }
00286 
00287 #endif // ARCHON_MATH_FUNCTIONS_H

Generated on Sun Jul 30 22:55:43 2006 for Archon by  doxygen 1.4.4