BioCMAMC-ST
traits.hpp
1#ifndef __COMMON_TRAITS_HPP__
2#define __COMMON_TRAITS_HPP__
3#include <cassert>
4#include <cmath>
5#include <type_traits>
6
7#if defined __GNUC__
8# define LIKELY(EXPR) __builtin_expect(!!(EXPR), 1)
9#else
10# define LIKELY(EXPR) (!!(EXPR))
11#endif
12
13#if defined NDEBUG
14# define X_ASSERT(CHECK) void(0)
15#else
16# define X_ASSERT(CHECK) \
17 (LIKELY(CHECK) ? void(0) : [] { assert(!(#CHECK)); }())
18#endif
19
20template <typename T>
21concept FloatingPointType = std::is_floating_point_v<std::remove_cvref_t<T>>;
22
23static_assert(FloatingPointType<double>, "double ok");
24static_assert(FloatingPointType<float>, "float ok");
25static_assert(!FloatingPointType<int>, "int ok");
26
27constexpr double tolerance_equality_float = 1e-15;
28
29template <typename T>
30concept IntegerType = requires(T n) {
31 requires std::is_integral_v<std::remove_cvref_t<T>>;
32 requires !std::is_same_v<std::remove_cvref_t<T>, bool>;
33 requires std::is_arithmetic_v<decltype(n + 1)>;
34 requires !std::is_pointer_v<std::remove_cvref_t<T>>;
35};
36
37template <typename T>
39
40// One parameter per argument, so mixed types compare in their common type.
41// Numbers are cheap to copy, by value covers lvalue and rvalue alike
42template <NumberType T, NumberType U, NumberType Tol = double>
43inline bool
44almost_equal(T val, U val2, Tol tolerance = tolerance_equality_float)
45{
46 using CommonT = std::common_type_t<T, U>;
47 return std::abs(static_cast<CommonT>(val) - static_cast<CommonT>(val2))
48 < static_cast<CommonT>(tolerance);
49}
50
51// Overload for pointers
52template <NumberType T, NumberType U, NumberType Tol = double>
53inline bool
54almost_equal(const T* val,
55 const U* val2,
56 Tol tolerance = tolerance_equality_float)
57{
58 if (val == nullptr || val2 == nullptr)
59 {
60 return false; // Null pointer check
61 }
62 return almost_equal(*val, *val2, tolerance);
63}
64
65#endif
Definition traits.hpp:21
Definition traits.hpp:30
Definition traits.hpp:38