LevelS C++ support library  3.82
math_utils.h
Go to the documentation of this file.
1 /*
2  * This file is part of libcxxsupport.
3  *
4  * libcxxsupport is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * libcxxsupport is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with libcxxsupport; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 /*
20  * libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
21  * and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
22  * (DLR).
23  */
24 
25 /*! \file math_utils.h
26  * Various convenience mathematical functions.
27  *
28  * Copyright (C) 2002-2015 Max-Planck-Society
29  * \author Martin Reinecke
30  */
31 
32 #ifndef PLANCK_MATH_UTILS_H
33 #define PLANCK_MATH_UTILS_H
34 
35 #include <cmath>
36 #include <vector>
37 #include <algorithm>
38 #include "datatypes.h"
39 
40 /*! \defgroup mathutilsgroup Mathematical helper functions */
41 /*! \{ */
42 
43 /*! Returns \e true if | \a a-b | <= \a epsilon * | \a b |, else \e false. */
44 template<typename F> inline bool approx (F a, F b, F epsilon=1e-5)
45  {
46  using namespace std;
47  return abs(a-b) <= (epsilon*abs(b));
48  }
49 
50 /*! Returns \e true if | \a a-b | <= \a epsilon, else \e false. */
51 template<typename F> inline bool abs_approx (F a, F b, F epsilon=1e-5)
52  {
53  using namespace std;
54  return abs(a-b) <= epsilon;
55  }
56 
57 /*! Returns the largest integer which is smaller than (or equal to) \a arg. */
58 template<typename I, typename F> inline I ifloor (F arg)
59  {
60  using namespace std;
61  return I(floor(arg));
62  }
63 
64 /*! Returns the integer which is nearest to \a arg. */
65 template<typename I, typename F> inline I nearest (F arg)
66  { return ifloor<I>(arg+0.5); }
67 
68 /*! Returns the remainder of the division \a v1/v2.
69  The result is non-negative.
70  \a v1 can be positive or negative; \a v2 must be positive. */
71 inline double fmodulo (double v1, double v2)
72  {
73  using namespace std;
74  if (v1>=0)
75  return (v1<v2) ? v1 : fmod(v1,v2);
76  double tmp=fmod(v1,v2)+v2;
77  return (tmp==v2) ? 0. : tmp;
78 // return (v1>=0) ? ((v1<v2) ? v1 : fmod(v1,v2)) : (fmod(v1,v2)+v2);
79  }
80 
81 /*! Returns the remainder of the division \a v1/v2.
82  The result is non-negative.
83  \a v1 can be positive or negative; \a v2 must be positive. */
84 template<typename I> inline I imodulo (I v1, I v2)
85  { I v=v1%v2; return (v>=0) ? v : v+v2; }
86 
87 /*! Returns -1 if \a signvalue is negative, else +1. */
88 template<typename T> inline T sign (const T& signvalue)
89  { return (signvalue>=0) ? 1 : -1; }
90 
91 /*! Returns \a val*pow(-1,m) */
92 template<typename T, typename I> inline T xpow (I m, T val)
93  { return (m&1) ? -val : val; }
94 
95 template<typename I, bool g4> struct isqrt_helper__
96  {};
97 template<typename I> struct isqrt_helper__ <I, false>
98  {
99  static uint32 isqrt (I arg)
100  {
101  using namespace std;
102  return uint32 (sqrt(arg+0.5));
103  }
104  };
105 template<typename I> struct isqrt_helper__ <I, true>
106  {
107  static uint32 isqrt (I arg)
108  {
109  using namespace std;
110  I res = sqrt(double(arg)+0.5);
111  if (arg<(int64(1)<<50)) return uint32(res);
112  if (res*res>arg)
113  --res;
114  else if ((res+1)*(res+1)<=arg)
115  ++res;
116  return uint32(res);
117  }
118  };
119 
120 /*! Returns the integer \a n, which fulfills \a n*n<=arg<(n+1)*(n+1). */
121 template<typename I> inline uint32 isqrt (I arg)
122  { return isqrt_helper__<I,(sizeof(I)>4)>::isqrt(arg); }
123 
124 /*! Returns the largest integer \a n that fulfills \a 2^n<=arg. */
125 template<typename I> inline int ilog2 (I arg)
126  {
127 #ifdef __GNUC__
128  if (arg==0) return 0;
129  if (sizeof(I)==sizeof(int))
130  return 8*sizeof(int)-1-__builtin_clz(arg);
131  if (sizeof(I)==sizeof(long))
132  return 8*sizeof(long)-1-__builtin_clzl(arg);
133  if (sizeof(I)==sizeof(long long))
134  return 8*sizeof(long long)-1-__builtin_clzll(arg);
135 #endif
136  int res=0;
137  while (arg > 0xFFFF) { res+=16; arg>>=16; }
138  if (arg > 0x00FF) { res|=8; arg>>=8; }
139  if (arg > 0x000F) { res|=4; arg>>=4; }
140  if (arg > 0x0003) { res|=2; arg>>=2; }
141  if (arg > 0x0001) { res|=1; }
142  return res;
143  }
144 
145 template<typename I> inline int ilog2_nonnull (I arg)
146  {
147 #ifdef __GNUC__
148  if (sizeof(I)<=sizeof(int))
149  return 8*sizeof(int)-1-__builtin_clz(arg);
150  if (sizeof(I)==sizeof(long))
151  return 8*sizeof(long)-1-__builtin_clzl(arg);
152  if (sizeof(I)==sizeof(long long))
153  return 8*sizeof(long long)-1-__builtin_clzll(arg);
154 #endif
155  return ilog2 (arg);
156  }
157 
158 template<typename I> inline int trailingZeros(I arg)
159  {
160  if (arg==0) return sizeof(I)<<3;
161 #ifdef __GNUC__
162  if (sizeof(I)<=sizeof(int))
163  return __builtin_ctz(arg);
164  if (sizeof(I)==sizeof(long))
165  return __builtin_ctzl(arg);
166  if (sizeof(I)==sizeof(long long))
167  return __builtin_ctzll(arg);
168 #endif
169  int res=0;
170  while ((arg&0xFFFF)==0) { res+=16; arg>>=16; }
171  if ((arg&0x00FF)==0) { res|=8; arg>>=8; }
172  if ((arg&0x000F)==0) { res|=4; arg>>=4; }
173  if ((arg&0x0003)==0) { res|=2; arg>>=2; }
174  if ((arg&0x0001)==0) { res|=1; }
175  return res;
176  }
177 
178 /*! Returns \a atan2(y,x) if \a x!=0 or \a y!=0; else returns 0. */
179 inline double safe_atan2 (double y, double x)
180  {
181  using namespace std;
182  return ((x==0.) && (y==0.)) ? 0.0 : atan2(y,x);
183  }
184 
185 /*! Helper function for linear interpolation (or extrapolation).
186  The array must be ordered in ascending order; no two values may be equal. */
187 template<typename T, typename Iter, typename Comp> inline void interpol_helper
188  (const Iter &begin, const Iter &end, const T &val, Comp comp, tsize &idx,
189  T &frac)
190  {
191  using namespace std;
192  planck_assert((end-begin)>1,"sequence too small for interpolation");
193  idx = lower_bound(begin,end,val,comp)-begin;
194  if (idx>0) --idx;
195  idx = min(tsize(end-begin-2),idx);
196  frac = (val-begin[idx])/(begin[idx+1]-begin[idx]);
197  }
198 
199 /*! Helper function for linear interpolation (or extrapolation).
200  The array must be ordered in ascending order; no two values may be equal. */
201 template<typename T, typename Iter> inline void interpol_helper
202  (const Iter &begin, const Iter &end, const T &val, tsize &idx, T &frac)
203  { interpol_helper (begin,end,val,std::less<T>(),idx,frac); }
204 
205 /*! \} */
206 
207 #if (__cplusplus>=201103L)
208 
209 template<typename T1, typename T2>
210 inline bool multiequal (const T1 &a, const T2 &b)
211  { return (a==b); }
212 
213 template<typename T1, typename T2, typename... Args>
214 inline bool multiequal (const T1 &a, const T2 &b, Args... args)
215  { return (a==b) && multiequal (a, args...); }
216 
217 #else
218 
219 template<typename T> inline bool multiequal (const T &a, const T &b)
220  { return (a==b); }
221 
222 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c)
223  { return (a==b) && (a==c); }
224 
225 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
226  const T &d)
227  { return (a==b) && (a==c) && (a==d); }
228 
229 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
230  const T &d, const T &e)
231  { return (a==b) && (a==c) && (a==d) && (a==e); }
232 
233 template<typename T> inline bool multiequal (const T &a, const T &b, const T &c,
234  const T &d, const T &e, const T &f)
235  { return (a==b) && (a==c) && (a==d) && (a==e) && (a==f); }
236 
237 #endif
238 
239 template<typename T> class kahan_adder
240  {
241  private:
242  T sum, c;
243  public:
244  kahan_adder(): sum(0), c(0) {}
245 
246  void add (const T &val)
247  {
248  volatile T tc=c; // volatile to disable over-eager optimizers
249  volatile T y=val-tc;
250  volatile T t=sum+y;
251  tc=(t-sum)-y;
252  sum=t;
253  c=tc;
254  }
255  T result() const { return sum; }
256  };
257 
258 template<typename T> class tree_adder
259  {
260  private:
261  std::vector<T> state;
262  tsize n;
263 
264  public:
265  tree_adder(): state(1,T(0)), n(0) {}
266 
267  void add (const T &val)
268  {
269  state[0]+=val; ++n;
270  if (n>(tsize(1)<<(state.size()-1)))
271  state.push_back(T(0));
272  int shift=0;
273  while (((n>>shift)&1)==0)
274  {
275  state[shift+1]+=state[shift];
276  state[shift]=T(0);
277  ++shift;
278  }
279  }
280  T result() const
281  {
282  T sum(0);
283  for (tsize i=0; i<state.size(); ++i)
284  sum+=state[i];
285  return sum;
286  }
287  };
288 
289 template<typename Iter> bool checkNan (Iter begin, Iter end)
290  {
291  while (begin!=end)
292  {
293  if (*begin != *begin) return true;
294  ++begin;
295  }
296  return false;
297  }
298 
299 #endif
T xpow(I m, T val)
Definition: math_utils.h:92
I imodulo(I v1, I v2)
Definition: math_utils.h:84
double safe_atan2(double y, double x)
Definition: math_utils.h:179
std::size_t tsize
Definition: datatypes.h:116
int ilog2(I arg)
Definition: math_utils.h:125
I ifloor(F arg)
Definition: math_utils.h:58
bool approx(F a, F b, F epsilon=1e-5)
Definition: math_utils.h:44
#define planck_assert(testval, msg)
void interpol_helper(const Iter &begin, const Iter &end, const T &val, Comp comp, tsize &idx, T &frac)
Definition: math_utils.h:188
double fmodulo(double v1, double v2)
Definition: math_utils.h:71
uint32 isqrt(I arg)
Definition: math_utils.h:121
bool abs_approx(F a, F b, F epsilon=1e-5)
Definition: math_utils.h:51
I nearest(F arg)
Definition: math_utils.h:65
T sign(const T &signvalue)
Definition: math_utils.h:88

Generated on Thu Jul 28 2022 17:32:06 for LevelS C++ support library