Not Enough Math
Lightweight zero-dependency C++ math library
Loading...
Searching...
No Matches
config.hpp
Go to the documentation of this file.
1#pragma once
2
3// options can be defined here, in CMake, in IDE project settings preprocessor definitions or in building arguments
4
5#include <type_traits>
6#include <concepts>
7#include <cassert>
8
9#ifdef NEM_NO_INLINE
10 #define NEM_INLINE
11#else
12 #define NEM_INLINE inline
13#endif
14
15namespace nem
16{
17#if defined(NEM_ERR_THROW)
18 constexpr bool ERR_THROW = true;
19#else
20 constexpr bool ERR_THROW = false;
21#endif
22
23#if defined(NEM_ERR_LOG)
24 constexpr bool ERR_LOG = true;
25#else
26 constexpr bool ERR_LOG = false;
27#endif
28
29#if defined(NEM_ERR_USE_NAN)
30 constexpr bool ERR_USE_NAN = true;
31#else
32 constexpr bool ERR_USE_NAN = false;
33#endif
34
35#if defined(NEM_ERR_SAFE_FALLBACK)
36 constexpr bool ERR_SAFE_FALLBACK = true;
37#else
38 constexpr bool ERR_SAFE_FALLBACK = false;
39#endif
40
41#if defined(NEM_CPP_STRING)
42#include <string>
43 using nem_string = std::string;
44 constexpr bool USE_C_STRING = false;
45 NEM_INLINE const char* GET_C_STRING(nem_string str) { return str.c_str(); }
46#else
47 using nem_string = const char*;
48 constexpr bool USE_C_STRING = true;
49 NEM_INLINE const char* GET_C_STRING(nem_string str) { return str; }
50#endif
51
52#if defined(NEM_USE_DOUBLE_PRECISION)
53 using real = double;
54#else
55 using real = float;
56#endif
57 template <typename T>
58 concept scalar_type = std::integral<T> || std::floating_point<T>;
59
60 struct safe_t { explicit constexpr safe_t() = default; };
61 struct unsafe_t { explicit constexpr unsafe_t() = default; };
62
63 inline constexpr safe_t safe{};
64 inline constexpr unsafe_t unsafe{};
65
66 enum class Precision : unsigned char
67 {
68 Fast = 0,
69 Accurate = 1
70 };
71
73
74 template <nem::scalar_type T>
75 constexpr T abs_to_rel_error(T x, T abs_error)
76 {
77 if (x < 0)
78 x = -x;
79 if constexpr (std::is_floating_point_v<T>)
80 {
81 return (x + abs_error) * abs_error;
82 }
83 else
84 {
85 return (T)0;
86 }
87 }
88
89 template <nem::scalar_type T>
90 constexpr T eps()
91 {
92 if constexpr (std::is_same_v<T, float>) return T{ 1e-6f };
93 else if constexpr (std::is_same_v<T, double>) return T{ 1e-9 };
94 else if constexpr (std::is_same_v<T, long double>) return T{ 1e-14 };
95 return (T)0;
96 }
97
98 namespace fast
99 {
100
102
103 template <nem::scalar_type T>
104 constexpr T abs_error()
105 {
106 if constexpr (std::is_same_v<T, float>) return T{ 3.0e-2f }; // absolute 0.03 or 3.0% relative
107 else if constexpr (std::is_same_v<T, double>) return T{ 3e-3 }; // absolute 0.003 or 0.3% relative
108 else if constexpr (std::is_same_v<T, long double>) return T{ 1e-4 }; // absolute 0.001 or 0.01% relative
109 return (T)0;
110 }
111
112 template <nem::scalar_type T>
113 constexpr T rel_error(T x)
114 {
116 }
117
118 } // namespace fast
119
120
121 namespace accurate
122 {
123
125
126 template <nem::scalar_type T>
127 constexpr T abs_error()
128 {
129 if constexpr (std::is_same_v<T, float>) return T{ 8.0e-3f }; // absolute 0.008 or 0.8% relative
130 else if constexpr (std::is_same_v<T, double>) return T{ 5e-4 }; // absolute 0.0005 or 0.05% relative
131 else if constexpr (std::is_same_v<T, long double>) return T{ 1e-5 }; // absolute 0.00001 or 0.001% relative
132 return (T)0;
133 }
134
135 template <nem::scalar_type T>
136 constexpr T rel_error(T x)
137 {
139 }
140
141 } // namespace accurate
142
143 template <nem::scalar_type T, nem::Precision Prec = nem::default_precision>
144 constexpr T abs_error()
145 {
146 if constexpr (Prec == nem::fast::mode)
147 {
149 }
150
151 if constexpr (Prec == nem::accurate::mode)
152 {
154 }
155 }
156
157 template <nem::scalar_type T, nem::Precision Prec = nem::default_precision>
158 constexpr T rel_error(T x)
159 {
160 if constexpr (Prec == nem::fast::mode)
161 {
162 return nem::fast::rel_error<T>(x);
163 }
164
165 if constexpr (Prec == nem::accurate::mode)
166 {
168 }
169 }
170
171 template <class From, class To>
173 : std::integral_constant<bool, (std::is_floating_point_v<To>
174 ? std::is_floating_point_v<From> || std::is_integral_v<From>
175 : ((std::is_integral_v<To> ? std::is_integral_v<From> : false)))>
176 {
177 };
178
179 template <class From, class To>
181}
#define NEM_INLINE
Definition config.hpp:12
constexpr nem::Precision mode
Definition config.hpp:124
constexpr T rel_error(T x)
Definition config.hpp:136
constexpr T abs_error()
Definition config.hpp:127
constexpr T abs_error()
Definition config.hpp:104
constexpr T rel_error(T x)
Definition config.hpp:113
constexpr nem::Precision mode
Definition config.hpp:101
Definition config.hpp:16
constexpr T eps()
Definition config.hpp:90
constexpr bool ERR_SAFE_FALLBACK
Definition config.hpp:38
constexpr nem::Precision default_precision
Definition config.hpp:72
constexpr bool is_subset_of_v
Definition config.hpp:180
constexpr T abs_to_rel_error(T x, T abs_error)
Definition config.hpp:75
constexpr bool USE_C_STRING
Definition config.hpp:48
float real
Definition config.hpp:55
constexpr bool ERR_LOG
Definition config.hpp:24
constexpr unsafe_t unsafe
Definition config.hpp:64
Precision
Definition config.hpp:67
const char * GET_C_STRING(nem_string str)
Definition config.hpp:49
constexpr safe_t safe
Definition config.hpp:63
constexpr bool ERR_THROW
Definition config.hpp:18
const char * nem_string
Definition config.hpp:47
constexpr bool ERR_USE_NAN
Definition config.hpp:30
constexpr T rel_error(T x)
Definition config.hpp:158
constexpr T abs_error()
Definition config.hpp:144
constexpr safe_t()=default
constexpr unsafe_t()=default