00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
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
00040
00041
00042
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
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
00057 template<typename I, typename F> inline I ifloor (F arg)
00058 {
00059 using namespace std;
00060 return I(floor(arg));
00061 }
00062
00063
00064 template<typename I, typename F> inline I nearest (F arg)
00065 { return ifloor<I>(arg+0.5); }
00066
00067
00068
00069
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
00078 }
00079
00080
00081
00082
00083 template<typename I> inline I imodulo (I v1, I v2)
00084 { I v=v1%v2; return (v>=0) ? v : v+v2; }
00085
00086
00087 template<typename T> inline T sign (const T& signvalue)
00088 { return (signvalue>=0) ? 1 : -1; }
00089
00090
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
00120 template<typename I> inline uint32 isqrt (I arg)
00121 { return isqrt_helper__<I,(sizeof(I)>4)>::isqrt(arg); }
00122
00123
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
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
00185
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
00199
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;
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