G+Smo  24.08.0
Geometry + Simulation Modules
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gsMath.h
Go to the documentation of this file.
1 
14 #pragma once
15 
17 
18 #include <cmath>
19 #include <complex>
20 
21 #ifdef gsCoDiPack_ENABLED
22  #include <gsCoDiPack/gsCoDiPack.h>
23 #endif
24 
25 namespace gismo {
26 
34 namespace math {
35 
36 typedef std::numeric_limits<real_t> limits;
37 
38 // Math functions
39 using std::abs;
40 using std::acos;
41 using std::asin;
42 using std::atan2;
43 using std::atan;
44 using std::ceil;
45 using std::cos;
46 using std::cosh;
47 using std::exp;
48 using std::floor;
49 using std::frexp;
50 using std::ldexp;
51 using std::log10;
52 using std::log;
53 using std::max;
54 using std::min;
55 using std::pow;
56 using std::sin;
57 using std::sinh;
58 using std::sqrt;
59 using std::tan;
60 using std::tanh;
61 using std::real;
62 using std::imag;
63 using std::conj;
64 
65 #ifdef gsCoDiPack_ENABLED
66 using codi::abs;
67 using codi::acos;
68 using codi::asin;
69 using codi::atan2;
70 using codi::atan;
71 using codi::ceil;
72 using codi::cos;
73 using codi::cosh;
74 using codi::exp;
75 using codi::floor;
76 //using codi::frexp;
77 //using codi::ldexp;
78 using codi::log10;
79 using codi::log;
80 using codi::max;
81 using codi::min;
82 using codi::pow;
83 using codi::sin;
84 using codi::sinh;
85 using codi::sqrt;
86 using codi::tan;
87 using codi::tanh;
88 using codi::isnan;
89 using codi::isfinite;
90 using codi::isinf;
91 //using codi::real;
92 //using codi::imag;
93 //using codi::conj;
94 #endif
95 
96 #ifdef gsUniversal_ENABLED
97 using sw::universal::abs;
98 using sw::universal::acos;
99 using sw::universal::asin;
100 using sw::universal::atan2;
101 using sw::universal::atan;
102 using sw::universal::ceil;
103 using sw::universal::cos;
104 using sw::universal::cosh;
105 using sw::universal::exp;
106 using sw::universal::floor;
107 //using sw::universal::frexp;
108 //using sw::universal::ldexp;
109 using sw::universal::log10;
110 using sw::universal::log;
111 using sw::universal::max;
112 using sw::universal::min;
113 using sw::universal::pow;
114 using sw::universal::sin;
115 using sw::universal::sinh;
116 using sw::universal::sqrt;
117 using sw::universal::tan;
118 using sw::universal::tanh;
119 
120 // dummy
121 template<size_t nbits, size_t es>
122 inline sw::universal::posit<nbits,es> frexp(const sw::universal::posit<nbits,es> & a, int* b) {return a;}
123 
124 template<size_t nbits, size_t es>
125 inline sw::universal::posit<nbits,es> ldexp(const sw::universal::posit<nbits,es> & a, int b ) {return a;}
126 
127 using sw::universal::isnan;
129 using sw::universal::isinf;
130 
131 using sw::universal::real;
132 using sw::universal::imag;
133 using sw::universal::conj;
134 
135 #endif
136 
137 // template <typename T> T min(T a, T b) {return (a < b ? a : b); }
138 // template <typename T> T max(T a, T b) {return (a < b ? b : a); }
139 
140 template <typename T> inline T exp2(const T a) { return 1U << a;}
141 
142 template <typename T>
143 T round(T a) { return math::floor(a+0.5); }
144 
145 
148 
149 template < typename T>
150 inline T nextafter(T x, T y)
151 {
152 # if defined(_MSC_VER) && _MSC_VER < 1800
153  return _nextafter(x,y);
154 # else
155  return ::nextafter(x,y);
156 # endif
157 }
158 
159 #ifdef gsMpfr_ENABLED
160 template<>
161 inline mpfr::mpreal nextafter(mpfr::mpreal x, mpfr::mpreal y)
162 {
163  return x + ( y < x ? -1e-16 : 1e-16 );
164 }
165 #endif
166 
167 #ifdef gsGmp_ENABLED
168 template<>
169 inline mpq_class nextafter(mpq_class x, mpq_class y)
170 {
171  return x + ( y < x ? -1e-16 : 1e-16 );
172 }
173 #endif
174 
175 #ifdef gsUniversal_ENABLED
176 template<size_t nbits, size_t es>
177 inline sw::universal::posit<nbits,es> nextafter(sw::universal::posit<nbits,es> x,
178  sw::universal::posit<nbits,es> y)
179 {
180  return sw::universal::nextafter(x,y);
181 }
182 #endif
183 
184 // inline real_t nextafter(real_t x, real_t y)
185 // {
186 // # if defined(gsMpfr_ENABLED) || defined(gsGmp_ENABLED)
187 // return x + ( y < x ? -1e-16 : 1e-16 );
188 // # elif defined(gsUniversal_ENABLED)
189 // return sw::universal::nextafter(x,y);
190 // # elif defined(_MSC_VER) && _MSC_VER < 1800
191 // return _nextafter(x,y);
192 // # else
193 // return ::nextafter(x,y);
194 // # endif
195 // }
196 
197 
201 template <typename T>
203 {
204  inline static int digits()
205  { return std::numeric_limits<T>::digits; }
206 
207  inline static int digits10()
208  { return std::numeric_limits<T>::digits10; }
209 };
210 
211 #ifdef gsMpfr_ENABLED
212 template <>
213 struct numeric_limits<mpfr::mpreal>
214 {
215  inline static int digits()
216  { return std::numeric_limits<mpfr::mpreal>::digits(); }
217 
218  inline static int digits10()
219  { return std::numeric_limits<mpfr::mpreal>::digits10(); }
220 };
221 #endif
222 
223 //#ifdef gsMpfr_ENABLED
224 //# define REAL_DIG std::numeric_limits<real_t>::digits10()
225 //#else
226 //# define REAL_DIG std::numeric_limits<real_t>::digits10
227 //#endif
228 #define REAL_DIG math::numeric_limits<real_t>::digits10()
229 
230 // functions to check for floating point errors
231 // Get isnan/isinf working on different compilers
232 #ifdef _MSC_VER
233 #include <float.h>
234 template <typename T>
235 int isnan (T a)
236 {return _isnan(a); }
237 //bool isnan (T a) {return a == a;} //equiv.
238 template <typename T>
239 int isfinite(T a)
240 {return _finite(a);}
241 //bool isfinite(T a) {(a - a) == (a - a);} //equiv.
242 template <typename T>
243 bool isinf(T a) {return (_FPCLASS_PINF|_FPCLASS_NINF) & _fpclass(a);}
244 
245 #ifndef NAN
246 // MSVC doesn't have the NAN constant in cmath, so we use the C++
247 // standard definition
248 #define NAN (std::numeric_limits<real_t>::quiet_NaN())
249 #endif
250 
251 #else
252 #ifdef _INTEL_COMPILER
253 #include <mathimf.h>
254 #else
255 using std::isnan;
256 using std::isfinite;
257 using std::isinf;
258 #endif
259 #endif
260 
261 #ifdef gsMpfr_ENABLED
262 // Math functions for MPFR
263 using mpfr::abs;
264 using mpfr::acos;
265 using mpfr::asin;
266 using mpfr::atan2;
267 using mpfr::atan;
268 using mpfr::ceil;
269 using mpfr::cos;
270 using mpfr::cosh;
271 using mpfr::floor;
272 using mpfr::log;
273 using mpfr::log10;
274 using mpfr::pow;
275 using mpfr::sin;
276 using mpfr::sinh;
277 using mpfr::sqrt;
278 using mpfr::tan;
279 using mpfr::tanh;
280 
281 //dummies
282 inline mpfr::mpreal frexp(const mpfr::mpreal & a, int* b) {return a;}
283 inline mpfr::mpreal ldexp(const mpfr::mpreal & a, int b ) {return a;}
284 
285 using mpfr::isfinite;
286 using mpfr::isinf;
287 using mpfr::isnan;
288 
289 #endif
290 
291 #ifdef gsGmp_ENABLED
292 // Math functions for GMP/mpq_class
294 using ::acos;
295 using ::asin;
296 using ::atan2;
297 using ::atan;
298 using ::ceil;
299 using ::cos;
300 using ::cosh;
301 using ::exp;
302 using ::floor;
303 inline mpq_class log10(const mpq_class & a) { return log(a)/log(10); }
304 using ::log;
305 using ::pow;
306 using ::sin;
307 using ::sinh;
308 using ::sqrt;
309 using ::tan;
310 using ::tanh;
311 
312 //fixme: min/max duplication with global
313 inline mpq_class (max)(const mpq_class & a, const mpq_class & b)
314 {return mpq_class(a < b ? b : a);}
315 inline mpq_class (min)(const mpq_class & a, const mpq_class & b)
316 {return mpq_class(a < b ? a : b);}
317 inline bool isfinite(mpq_class a) {return true; }
318 inline bool isinf(mpq_class a) {return false;}
319 inline bool isnan(mpq_class a) {return false;}
320 inline mpq_class frexp(const mpq_class & a, int* b) {return a;}
321 inline mpq_class ldexp(const mpq_class & a, int b ) {return a;}
322 #endif
323 
325 template <typename T> int getSign(T val)
326 {
327  return (T(0) < val) - (val < (T)(0));
328 }
329 
332 template <typename T>
333 inline typename util::make_unsigned<T>::type abs_diff(T a, T b)
334 {
335  typedef typename util::make_unsigned<T>::type unsignedT;
336  return a > b ? unsignedT(a) - unsignedT(b) : unsignedT(b) - unsignedT(a);
337 }
338 
340 inline int ipow(int x, unsigned exp)
341 {
342  int result = 1;
343  while (exp)
344  {
345  if (exp & 1)
346  result *= x;
347  exp >>= 1;
348  x *= x;
349  }
350  return result;
351 }
352 
354 inline unsigned isqrt(unsigned value)
355 {
356  const unsigned sr = static_cast<unsigned>(std::sqrt(static_cast<double>(value)));
357  //do { ++sr; } while(sr * sr <= value); // pick closest integer
358  //do { --sr; } while(sr * sr > value);
359  return sr;
360 }
361 
363 template<class T>
364 inline T mix(T const & a, T const & b, T const & t)
365 {
366  return (1 - t) * a + t * b;
367 }
368 
369 // numerical comparison
370 template<class T>
371 inline bool lessthan (T const a, T const b)
372 { return ( b-a > math::limits::epsilon()); }
373 
374 // numerical equality with \a prec decimal digits
375 template<int prec, class T>
376 bool almostEqual (T const a, T const b)
377 { return ( math::log10(math::abs(b-a)) < -prec); }
378 
379 // numerical equality adjusted to the floating point number type
380 template<class T>
381 bool almostEqualUlp(const T a, const T b, const unsigned ulps)
382 {
383  typedef std::numeric_limits<T> Tlimits;
384 
385  // Handle NaN.
386  if (isnan(a) || isnan(b))
387  return false;
388 
389  // Handle very small and exactly equal values.
390  if (math::abs(a-b) <= ulps * Tlimits::denorm_min())
391  return true;
392 
393  // If we get this far and either number is zero, then the other is
394  // too big, so just handle that now.
395  if (a == 0 || b == 0)
396  return false;
397 
398  // Break the numbers into significand and exponent, sorting them
399  // by exponent. (note that infinity might not be correctly handled)
400  int min_exp(0), max_exp(0);
401  T min_frac = frexp(a, &min_exp);
402  T max_frac = frexp(b, &max_exp);
403  if (min_exp > max_exp)
404  {
405  std::swap(min_frac, max_frac);
406  std::swap(min_exp, max_exp);
407  }
408 
409  // Convert the smaller to the scale of the larger by adjusting its
410  // significand.
411  const T scaled_min_frac = math::ldexp(min_frac, min_exp-max_exp);
412 
413  // Since the significands are now in the same scale, and the
414  // larger is in the range [0.5, 1), 1 ulp is just epsilon/2.
415  return math::abs(max_frac-scaled_min_frac) <= ulps * Tlimits::epsilon() / 2.0;
416 }
417 
418 // Default value for ULPs in the above
419 template<class T>
420 bool almostEqual(const T a, const T b)
421 {return almostEqualUlp<T>(a,b,4); }
422 
423 // static const double pi = 3.141592653589793238462;
424 // static const double e = 2.718281828459045235360;
425 // static const double pi_2 = 1.570796326794896619231;
426 // static const double pi_4 = 0.785398163397448309616;
427 // static const double pi_180 = 0.017453292519943295769;
428 // static const double _1_pi = 0.318309886183790671538;
429 // static const double _2_pi = 0.636619772367581343076;
430 // static const double _180_pi = 57.295779513082320876798;
431 
432 } //end namespace math
433 
438 template <typename T>
439 inline bool gsClose (const T &a, const T &b, const T &tol)
440 {
441  return math::abs(a-b) <= tol;
442 }
443 
451 template <typename matrix_t1, typename matrix_t2>
452 inline bool gsAllCloseRelativeToMax (const matrix_t1 &a, const matrix_t2 &b, const typename matrix_t1::Scalar &tol )
453 {
454  GISMO_ASSERT( a.cols()==b.cols() && a.rows()==b.rows(), "Only matrices of the same size can be compared" );
455  return (a-b).array().abs().maxCoeff() <= tol*math::max(a.array().abs().maxCoeff(), b.array().abs().maxCoeff());
456 }
457 
464 template <typename matrix_t1, typename matrix_t2>
465 inline bool gsAllCloseAbsolute (const matrix_t1 &a, const matrix_t2 &b, const typename matrix_t1::Scalar &tol )
466 {
467  GISMO_ASSERT( a.cols()==b.cols() && a.rows()==b.rows(), "Only matrices of the same size can be compared" );
468  return (a-b).array().abs().maxCoeff() <= tol;
469 }
470 
478 template <typename matrix_t1, typename matrix_t2>
479 inline bool gsAllCloseRelAndAbsWithRef (const matrix_t1 &a, const matrix_t2 &b, const typename matrix_t1::Scalar &tol, const typename matrix_t1::Scalar &ref )
480 {
481  GISMO_ASSERT( a.cols()==b.cols() && a.rows()==b.rows(), "Only matrices of the same size can be compared" );
482  return (a-b).array().abs().maxCoeff() <= tol*math::max(ref,a.array().abs().maxCoeff(), b.array().abs().maxCoeff());
483 }
484 
485 
486 /*
487  CompileTimeLog2 computes the logarithm base 2 of the argument using
488  template recursion.
489 
490 template <unsigned arg>
491 struct CompileTimeLog2
492 {
493  enum { result = CompileTimeLog2< arg / 2 >::result + 1 };
494 };
495 template <>
496 struct CompileTimeLog2<1>
497 {
498  enum { result = 0 };
499 };
500 template <>
501 struct CompileTimeLog2<0>
502 {
503  // empty because the logarithm of 0 is -infinity
504 };
505 template <unsigned arg>
506 unsigned CTLog2 (void) {return CompileTimeLog2<arg>::result;}
507 */
508 
509 } //end namespace gismo
bool gsAllCloseAbsolute(const matrix_t1 &a, const matrix_t2 &b, const typename matrix_t1::Scalar &tol)
tests if the difference between two matrices is bounded by tol in norm
Definition: gsMath.h:465
bool gsAllCloseRelAndAbsWithRef(const matrix_t1 &a, const matrix_t2 &b, const typename matrix_t1::Scalar &tol, const typename matrix_t1::Scalar &ref)
Tests whether the difference between two matrices is bounded by tol in norm.
Definition: gsMath.h:479
int getSign(T val)
Returns the sign of val.
Definition: gsMath.h:325
#define GISMO_ASSERT(cond, message)
Definition: gsDebug.h:89
bool isfinite(const gsEigen::MatrixBase< Derived > &x)
Check if all the entires if the matrix x are not INF (infinite)
Definition: gsLinearAlgebra.h:109
Provides forward declarations of types and structs.
unsigned isqrt(unsigned value)
integer square root
Definition: gsMath.h:354
T mix(T const &a, T const &b, T const &t)
Returns convex combination of a and b with weight t.
Definition: gsMath.h:364
Header for CoDiPack package.
bool gsClose(const T &a, const T &b, const T &tol)
tests if the difference between two numbers is below tolerance
Definition: gsMath.h:439
int ipow(int x, unsigned exp)
integer power
Definition: gsMath.h:340
EIGEN_STRONG_INLINE abs_expr< E > abs(const E &u)
Absolute value.
Definition: gsExpressions.h:4488
util::make_unsigned< T >::type abs_diff(T a, T b)
Definition: gsMath.h:333
T nextafter(T x, T y)
Definition: gsMath.h:150
Definition: gsMath.h:202
bool gsAllCloseRelativeToMax(const matrix_t1 &a, const matrix_t2 &b, const typename matrix_t1::Scalar &tol)
tests if the difference between two matrices is bounded by tol in norm
Definition: gsMath.h:452