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-2015 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 #ifdef __GNUC__
00127   if (arg==0) return 0;
00128   if (sizeof(I)==sizeof(int))
00129     return 8*sizeof(int)-1-__builtin_clz(arg);
00130   if (sizeof(I)==sizeof(long))
00131     return 8*sizeof(long)-1-__builtin_clzl(arg);
00132   if (sizeof(I)==sizeof(long long))
00133     return 8*sizeof(long long)-1-__builtin_clzll(arg);
00134 #endif
00135   int res=0;
00136   while (arg > 0xFFFF) { res+=16; arg>>=16; }
00137   if (arg > 0x00FF) { res|=8; arg>>=8; }
00138   if (arg > 0x000F) { res|=4; arg>>=4; }
00139   if (arg > 0x0003) { res|=2; arg>>=2; }
00140   if (arg > 0x0001) { res|=1; }
00141   return res;
00142   }
00143 
00144 template<typename I> inline int ilog2_nonnull (I arg)
00145   {
00146 #ifdef __GNUC__
00147   if (sizeof(I)<=sizeof(int))
00148     return 8*sizeof(int)-1-__builtin_clz(arg);
00149   if (sizeof(I)==sizeof(long))
00150     return 8*sizeof(long)-1-__builtin_clzl(arg);
00151   if (sizeof(I)==sizeof(long long))
00152     return 8*sizeof(long long)-1-__builtin_clzll(arg);
00153 #endif
00154   return ilog2 (arg);
00155   }
00156 
00157 template<typename I> inline int trailingZeros(I arg)
00158   {
00159   if (arg==0) return sizeof(I)<<3;
00160 #ifdef __GNUC__
00161   if (sizeof(I)<=sizeof(int))
00162     return __builtin_ctz(arg);
00163   if (sizeof(I)==sizeof(long))
00164     return __builtin_ctzl(arg);
00165   if (sizeof(I)==sizeof(long long))
00166     return __builtin_ctzll(arg);
00167 #endif
00168   int res=0;
00169   while ((arg&0xFFFF)==0) { res+=16; arg>>=16; }
00170   if ((arg&0x00FF)==0) { res|=8; arg>>=8; }
00171   if ((arg&0x000F)==0) { res|=4; arg>>=4; }
00172   if ((arg&0x0003)==0) { res|=2; arg>>=2; }
00173   if ((arg&0x0001)==0) { res|=1; }
00174   return res;
00175   }
00176 
00177 /*! Returns \a atan2(y,x) if \a x!=0 or \a y!=0; else returns 0. */
00178 inline double safe_atan2 (double y, double x)
00179   {
00180   using namespace std;
00181   return ((x==0.) && (y==0.)) ? 0.0 : atan2(y,x);
00182   }
00183 
00184 /*! Helper function for linear interpolation (or extrapolation).
00185     The array must be ordered in ascending order; no two values may be equal. */
00186 template<typename T, typename Iter, typename Comp> inline void interpol_helper
00187   (const Iter &begin, const Iter &end, const T &val, Comp comp, tsize &idx,
00188   T &frac)
00189   {
00190   using namespace std;
00191   planck_assert((end-begin)>1,"sequence too small for interpolation");
00192   idx = lower_bound(begin,end,val,comp)-begin;
00193   if (idx>0) --idx;
00194   idx = min(tsize(end-begin-2),idx);
00195   frac = (val-begin[idx])/(begin[idx+1]-begin[idx]);
00196   }
00197 
00198 /*! Helper function for linear interpolation (or extrapolation).
00199     The array must be ordered in ascending order; no two values may be equal. */
00200 template<typename T, typename Iter> inline void interpol_helper
00201   (const Iter &begin, const Iter &end, const T &val, tsize &idx, T &frac)
00202   { interpol_helper (begin,end,val,std::less<T>(),idx,frac); }
00203 
00204 /*! \} */
00205 
00206 #if (__cplusplus>=201103L)
00207 
00208 template<typename T>
00209 inline bool multiequal (const T &a, const T &b)
00210   { return (a==b); }
00211 
00212 template<typename T, typename... Args>
00213 inline bool multiequal (const T &a, const T &b, Args... args)
00214   { return (a==b) && multiequal (a, args...); }
00215 
00216 #else
00217 
00218 template<typename T> inline bool multiequal (const T &a, const T &b)
00219   { return (a==b); }
00220 
00221 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c)
00222   { return (a==b) && (a==c); }
00223 
00224 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
00225   const T &d)
00226   { return (a==b) && (a==c) && (a==d); }
00227 
00228 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
00229   const T &d, const T &e)
00230   { return (a==b) && (a==c) && (a==d) && (a==e); }
00231 
00232 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
00233   const T &d, const T &e, const T &f)
00234   { return (a==b) && (a==c) && (a==d) && (a==e) && (a==f); }
00235 
00236 #endif
00237 
00238 template<typename T> class kahan_adder
00239   {
00240   private:
00241     T sum, c;
00242   public:
00243     kahan_adder(): sum(0), c(0) {}
00244 
00245     void add (const T &val)
00246       {
00247       volatile T tc=c; // volatile to disable over-eager optimizers
00248       volatile T y=val-tc;
00249       volatile T t=sum+y;
00250       tc=(t-sum)-y;
00251       sum=t;
00252       c=tc;
00253       }
00254     T result() const { return sum; }
00255   };
00256 
00257 template<typename Iter> bool checkNan (Iter begin, Iter end)
00258   {
00259   while (begin!=end)
00260     {
00261     if (*begin != *begin) return true;
00262     ++begin;
00263     }
00264   return false;
00265   }
00266 
00267 #endif

Generated on Thu Oct 8 14:48:51 2015 for LevelS C++ support library