G+Smo  25.01.0
Geometry + Simulation Modules
 
Loading...
Searching...
No Matches
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
23#endif
24
25namespace gismo {
26
34namespace math {
35
36typedef std::numeric_limits<real_t> limits;
37
38// Math functions
39using std::abs;
40using std::acos;
41using std::asin;
42using std::atan2;
43using std::atan;
44using std::ceil;
45using std::cos;
46using std::cosh;
47using std::exp;
48using std::floor;
49using std::frexp;
50using std::ldexp;
51using std::log10;
52using std::log;
53using std::max;
54using std::min;
55using std::pow;
56using std::sin;
57using std::sinh;
58using std::sqrt;
59using std::tan;
60using std::tanh;
61using std::real;
62using std::imag;
63using std::conj;
64
65#ifdef gsCoDiPack_ENABLED
66using codi::abs;
67using codi::acos;
68using codi::asin;
69using codi::atan2;
70using codi::atan;
71using codi::ceil;
72using codi::cos;
73using codi::cosh;
74using codi::exp;
75using codi::floor;
76//using codi::frexp;
77//using codi::ldexp;
78using codi::log10;
79using codi::log;
80using codi::max;
81using codi::min;
82using codi::pow;
83using codi::sin;
84using codi::sinh;
85using codi::sqrt;
86using codi::tan;
87using codi::tanh;
88using codi::isnan;
89using codi::isfinite;
90using codi::isinf;
91//using codi::real;
92//using codi::imag;
93//using codi::conj;
94#endif
95
96#ifdef gsUniversal_ENABLED
97using sw::universal::abs;
98using sw::universal::acos;
99using sw::universal::asin;
100using sw::universal::atan2;
101using sw::universal::atan;
102using sw::universal::ceil;
103using sw::universal::cos;
104using sw::universal::cosh;
105using sw::universal::exp;
106using sw::universal::floor;
107//using sw::universal::frexp;
108//using sw::universal::ldexp;
109using sw::universal::log10;
110using sw::universal::log;
111using sw::universal::max;
112using sw::universal::min;
113using sw::universal::pow;
114using sw::universal::sin;
115using sw::universal::sinh;
116using sw::universal::sqrt;
117using sw::universal::tan;
118using sw::universal::tanh;
119
120// dummy
121template<size_t nbits, size_t es>
122inline sw::universal::posit<nbits,es> frexp(const sw::universal::posit<nbits,es> & a, int* b) {return a;}
123
124template<size_t nbits, size_t es>
125inline sw::universal::posit<nbits,es> ldexp(const sw::universal::posit<nbits,es> & a, int b ) {return a;}
126
127using sw::universal::isnan;
128using sw::universal::isfinite;
129using sw::universal::isinf;
130
131using sw::universal::real;
132using sw::universal::imag;
133using 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
140template <typename T> inline T exp2(const T a) { return 1U << a;}
141
142template <typename T>
143T round(T a) { return math::floor(a+0.5); }
144
145
148
149template < typename T>
150inline 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
160template<>
161inline 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
168template<>
169inline 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
176template<size_t nbits, size_t es>
177inline 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
201template <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
212template <>
213struct 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>
234template <typename T>
235int isnan (T a)
236{return _isnan(a); }
237//bool isnan (T a) {return a == a;} //equiv.
238template <typename T>
239int isfinite(T a)
240{return _finite(a);}
241//bool isfinite(T a) {(a - a) == (a - a);} //equiv.
242template <typename T>
243bool 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
255using std::isnan;
256using std::isfinite;
257using std::isinf;
258#endif
259#endif
260
261#ifdef gsMpfr_ENABLED
262// Math functions for MPFR
263using mpfr::abs;
264using mpfr::acos;
265using mpfr::asin;
266using mpfr::atan2;
267using mpfr::atan;
268using mpfr::ceil;
269using mpfr::cos;
270using mpfr::cosh;
271using mpfr::floor;
272using mpfr::log;
273using mpfr::log10;
274using mpfr::pow;
275using mpfr::sin;
276using mpfr::sinh;
277using mpfr::sqrt;
278using mpfr::tan;
279using mpfr::tanh;
280
281//dummies
282inline mpfr::mpreal frexp(const mpfr::mpreal & a, int* b) {return a;}
283inline mpfr::mpreal ldexp(const mpfr::mpreal & a, int b ) {return a;}
284
285using mpfr::isfinite;
286using mpfr::isinf;
287using mpfr::isnan;
288
289#endif
290
291#ifdef gsGmp_ENABLED
292// Math functions for GMP/mpq_class
293using ::abs;
294using ::acos;
295using ::asin;
296using ::atan2;
297using ::atan;
298using ::ceil;
299using ::cos;
300using ::cosh;
301using ::exp;
302using ::floor;
303inline mpq_class log10(const mpq_class & a) { return log(a)/log(10); }
304using ::log;
305using ::pow;
306using ::sin;
307using ::sinh;
308using ::sqrt;
309using ::tan;
310using ::tanh;
311
312//fixme: min/max duplication with global
313inline mpq_class (max)(const mpq_class & a, const mpq_class & b)
314{return mpq_class(a < b ? b : a);}
315inline mpq_class (min)(const mpq_class & a, const mpq_class & b)
316{return mpq_class(a < b ? a : b);}
317inline bool isfinite(mpq_class a) {return true; }
318inline bool isinf(mpq_class a) {return false;}
319inline bool isnan(mpq_class a) {return false;}
320inline mpq_class frexp(const mpq_class & a, int* b) {return a;}
321inline mpq_class ldexp(const mpq_class & a, int b ) {return a;}
322#endif
323
325template <typename T> int getSign(T val)
326{
327 return (T(0) < val) - (val < (T)(0));
328}
329
332template <typename T>
333inline 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
340inline 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
354inline 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
363template<class T>
364inline T mix(T const & a, T const & b, T const & t)
365{
366 return (1 - t) * a + t * b;
367}
368
369// numerical comparison
370template<class T>
371inline bool lessthan (T const a, T const b)
372{ return ( b-a > math::limits::epsilon()); }
373
374// numerical equality with \a prec decimal digits
375template<int prec, class T>
376bool 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
380template<class T>
381bool 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
419template<class T>
420bool 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
438template <typename T>
439inline bool gsClose (const T &a, const T &b, const T &tol)
440{
441 return math::abs(a-b) <= tol;
442}
443
451template <typename matrix_t1, typename matrix_t2>
452inline 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
464template <typename matrix_t1, typename matrix_t2>
465inline 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
478template <typename matrix_t1, typename matrix_t2>
479inline 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
490template <unsigned arg>
491struct CompileTimeLog2
492{
493 enum { result = CompileTimeLog2< arg / 2 >::result + 1 };
494};
495template <>
496struct CompileTimeLog2<1>
497{
498 enum { result = 0 };
499};
500template <>
501struct CompileTimeLog2<0>
502{
503 // empty because the logarithm of 0 is -infinity
504};
505template <unsigned arg>
506unsigned CTLog2 (void) {return CompileTimeLog2<arg>::result;}
507*/
508
509} //end namespace gismo
Header for CoDiPack package.
#define GISMO_ASSERT(cond, message)
Definition gsDebug.h:89
Provides forward declarations of types and structs.
int getSign(T val)
Returns the sign of val.
Definition gsMath.h:325
int ipow(int x, unsigned exp)
integer power
Definition gsMath.h:340
util::make_unsigned< T >::type abs_diff(T a, T b)
Definition gsMath.h:333
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
unsigned isqrt(unsigned value)
integer square root
Definition gsMath.h:354
T nextafter(T x, T y)
Definition gsMath.h:150
The G+Smo namespace, containing all definitions for the library.
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
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
bool isfinite(const gsEigen::MatrixBase< Derived > &x)
Check if all the entires if the matrix x are not INF (infinite)
Definition gsLinearAlgebra.h:109
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 gsClose(const T &a, const T &b, const T &tol)
tests if the difference between two numbers is below tolerance
Definition gsMath.h:439
Definition gsMath.h:203