math_utils.h

Go to the documentation of this file.
00001 /*
00002  *  This file is part of libcxxsupport.
00003  *
00004  *  libcxxsupport is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  libcxxsupport is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with libcxxsupport; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*! \file math_utils.h
00026  *  Various convenience mathematical functions.
00027  *
00028  *  Copyright (C) 2002-2012 Max-Planck-Society
00029  *  \author Martin Reinecke
00030  */
00031 
00032 #ifndef PLANCK_MATH_UTILS_H
00033 #define PLANCK_MATH_UTILS_H
00034 
00035 #include <cmath>
00036 #include <algorithm>
00037 #include "datatypes.h"
00038 
00039 /*! \defgroup mathutilsgroup Mathematical helper functions */
00040 /*! \{ */
00041 
00042 /*! Returns \e true if | \a a-b | <= \a epsilon * | \a b |, else \e false. */
00043 template<typename F> inline bool approx (F a, F b, F epsilon=1e-5)
00044   {
00045   using namespace std;
00046   return abs(a-b) <= (epsilon*abs(b));
00047   }
00048 
00049 /*! Returns \e true if | \a a-b | <= \a epsilon, else \e false. */
00050 template<typename F> inline bool abs_approx (F a, F b, F epsilon=1e-5)
00051   {
00052   using namespace std;
00053   return abs(a-b) <= epsilon;
00054   }
00055 
00056 /*! Returns the largest integer which is smaller than (or equal to) \a arg. */
00057 template<typename I, typename F> inline I ifloor (F arg)
00058   {
00059   using namespace std;
00060   return I(floor(arg));
00061   }
00062 
00063 /*! Returns the integer which is nearest to \a arg. */
00064 template<typename I, typename F> inline I nearest (F arg)
00065   { return ifloor<I>(arg+0.5); }
00066 
00067 /*! Returns the remainder of the division \a v1/v2.
00068     The result is non-negative.
00069     \a v1 can be positive or negative; \a v2 must be positive. */
00070 inline double fmodulo (double v1, double v2)
00071   {
00072   using namespace std;
00073   if (v1>=0)
00074     return (v1<v2) ? v1 : fmod(v1,v2);
00075   double tmp=fmod(v1,v2)+v2;
00076   return (tmp==v2) ? 0. : tmp;
00077 //  return (v1>=0) ? ((v1<v2) ? v1 : fmod(v1,v2)) : (fmod(v1,v2)+v2);
00078   }
00079 
00080 /*! Returns the remainder of the division \a v1/v2.
00081     The result is non-negative.
00082     \a v1 can be positive or negative; \a v2 must be positive. */
00083 template<typename I> inline I imodulo (I v1, I v2)
00084   { I v=v1%v2; return (v>=0) ? v : v+v2; }
00085 
00086 /*! Returns -1 if \a signvalue is negative, else +1. */
00087 template<typename T> inline T sign (const T& signvalue)
00088   { return (signvalue>=0) ? 1 : -1; }
00089 
00090 /*! Returns \a val*pow(-1,m) */
00091 template<typename T, typename I> inline T xpow (I m, T val)
00092   { return (m&1) ? -val : val; }
00093 
00094 template<typename I, bool g4> struct isqrt_helper__
00095   {};
00096 template<typename I> struct isqrt_helper__ <I, false>
00097   {
00098   static uint32 isqrt (I arg)
00099     {
00100     using namespace std;
00101     return uint32 (sqrt(arg+0.5));
00102     }
00103   };
00104 template<typename I> struct isqrt_helper__ <I, true>
00105   {
00106   static uint32 isqrt (I arg)
00107     {
00108     using namespace std;
00109     I res = sqrt(double(arg)+0.5);
00110     if (arg<(int64(1)<<50)) return uint32(res);
00111     if (res*res>arg)
00112       --res;
00113     else if ((res+1)*(res+1)<=arg)
00114       ++res;
00115     return uint32(res);
00116     }
00117   };
00118 
00119 /*! Returns the integer \a n, which fulfills \a n*n<=arg<(n+1)*(n+1). */
00120 template<typename I> inline uint32 isqrt (I arg)
00121   { return isqrt_helper__<I,(sizeof(I)>4)>::isqrt(arg); }
00122 
00123 /*! Returns the largest integer \a n that fulfills \a 2^n<=arg. */
00124 template<typename I> inline int ilog2 (I arg)
00125   {
00126   int res=0;
00127   while (arg > 0x0000FFFF) { res+=16; arg>>=16; }
00128   if (arg > 0x000000FF) { res|=8; arg>>=8; }
00129   if (arg > 0x0000000F) { res|=4; arg>>=4; }
00130   if (arg > 0x00000003) { res|=2; arg>>=2; }
00131   if (arg > 0x00000001) { res|=1; }
00132   return res;
00133   }
00134 
00135 /*! Returns \a atan2(y,x) if \a x!=0 or \a y!=0; else returns 0. */
00136 inline double safe_atan2 (double y, double x)
00137   {
00138   using namespace std;
00139   return ((x==0.) && (y==0.)) ? 0.0 : atan2(y,x);
00140   }
00141 
00142 /*! Helper function for linear interpolation (or extrapolation).
00143     The array must be ordered in ascending order; no two values may be equal. */
00144 template<typename T, typename Iter, typename Comp> inline void interpol_helper
00145   (const Iter &begin, const Iter &end, const T &val, Comp comp, tsize &idx,
00146   T &frac)
00147   {
00148   using namespace std;
00149   planck_assert((end-begin)>1,"sequence too small for interpolation");
00150   idx = lower_bound(begin,end,val,comp)-begin;
00151   if (idx>0) --idx;
00152   idx = min(tsize(end-begin-2),idx);
00153   frac = (val-begin[idx])/(begin[idx+1]-begin[idx]);
00154   }
00155 
00156 /*! Helper function for linear interpolation (or extrapolation).
00157     The array must be ordered in ascending order; no two values may be equal. */
00158 template<typename T, typename Iter> inline void interpol_helper
00159   (const Iter &begin, const Iter &end, const T &val, tsize &idx, T &frac)
00160   { interpol_helper (begin,end,val,std::less<T>(),idx,frac); }
00161 
00162 /*! \} */
00163 
00164 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c)
00165   { return (a==b) && (a==c); }
00166 
00167 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
00168   const T &d)
00169   { return (a==b) && (a==c) && (a==d); }
00170 
00171 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
00172   const T &d, const T &e)
00173   { return (a==b) && (a==c) && (a==d) && (a==e); }
00174 
00175 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
00176   const T &d, const T &e, const T &f)
00177   { return (a==b) && (a==c) && (a==d) && (a==e) && (a==f); }
00178 
00179 #endif

Generated on Wed Apr 24 11:31:17 2013 for LevelS C++ support library