AutoPas  3.0.0
Loading...
Searching...
No Matches
Math.h
Go to the documentation of this file.
1
7#pragma once
8
9#include <Eigen/Core>
10#include <cmath>
11#include <vector>
12
13namespace autopas::utils::Math {
17const double normalScale = 1. / std::sqrt(2 * M_PI);
18
29template <class Int_t, std::enable_if_t<std::is_integral_v<Int_t>, bool> = true>
30Int_t safeAdd(const Int_t &a, const Int_t &b, const Int_t &valUnderflow = std::numeric_limits<Int_t>::min(),
31 const Int_t &valOverflow = std::numeric_limits<Int_t>::max()) {
32 Int_t result;
33 bool overflow = __builtin_add_overflow(a, b, &result);
34 if (overflow) {
35 // if both args are negative this is an underflow.
36 if (a < 0 and b < 0) {
37 result = valUnderflow;
38 } else {
39 result = valOverflow;
40 }
41 }
42 return result;
43}
44
58template <class Float_t, std::enable_if_t<std::is_floating_point_v<Float_t>, bool> = true>
59Float_t safeAdd(const Float_t &a, const Float_t &b, const Float_t &valUnderflow = -std::numeric_limits<Float_t>::max(),
60 const Float_t &valOverflow = std::numeric_limits<Float_t>::max()) {
61 Float_t result = a + b;
62 if (std::isinf(result)) {
63 if (result > 0) {
64 result = valOverflow;
65 } else {
66 result = valUnderflow;
67 }
68 }
69 return result;
70}
71
82template <class Int_t, std::enable_if_t<std::is_integral_v<Int_t>, bool> = true>
83Int_t safeSub(const Int_t &a, const Int_t &b, const Int_t &valUnderflow = std::numeric_limits<Int_t>::min(),
84 const Int_t &valOverflow = std::numeric_limits<Int_t>::max()) {
85 Int_t result;
86 bool overflow = __builtin_sub_overflow(a, b, &result);
87 if (overflow) {
88 // underflow is only possible if we subtract a positive number. Everything else is an overflow.
89 if (b > 0) {
90 result = valUnderflow;
91 } else {
92 result = valOverflow;
93 }
94 }
95 return result;
96}
97
111template <class Float_t, std::enable_if_t<std::is_floating_point_v<Float_t>, bool> = true>
112Float_t safeSub(const Float_t &a, const Float_t &b, const Float_t &valUnderflow = -std::numeric_limits<Float_t>::max(),
113 const Float_t &valOverflow = std::numeric_limits<Float_t>::max()) {
114 Float_t result = a - b;
115 if (std::isinf(result)) {
116 if (result > 0) {
117 result = valOverflow;
118 } else {
119 result = valUnderflow;
120 }
121 }
122 return result;
123}
124
135template <class Int_t, std::enable_if_t<std::is_integral_v<Int_t>, bool> = true>
136Int_t safeMul(const Int_t &a, const Int_t &b, const Int_t &valUnderflow = std::numeric_limits<Int_t>::min(),
137 const Int_t &valOverflow = std::numeric_limits<Int_t>::max()) {
138 Int_t result;
139 bool overflow = __builtin_mul_overflow(a, b, &result);
140 if (overflow) {
141 // if exactly one arg is negative this is an underflow.
142 if ((a < 0) xor (b < 0)) {
143 result = valUnderflow;
144 } else {
145 result = valOverflow;
146 }
147 }
148 return result;
149}
150
164template <class Float_t, std::enable_if_t<std::is_floating_point_v<Float_t>, bool> = true>
165Float_t safeMul(const Float_t &a, const Float_t &b, const Float_t &valUnderflow = -std::numeric_limits<Float_t>::max(),
166 const Float_t &valOverflow = std::numeric_limits<Float_t>::max()) {
167 Float_t result = a * b;
168 if (std::isinf(result)) {
169 if (result > 0) {
170 result = valOverflow;
171 } else {
172 result = valUnderflow;
173 }
174 }
175 return result;
176}
177
185template <size_t exponent, class T>
186T pow(const T &base) {
187 if (exponent == 0) {
188 return 1;
189 }
190
191 T res = base;
192 // the compiler should unroll this loop
193 for (size_t i = 0; i < exponent - 1; ++i) {
194 res *= base;
195 }
196 return res;
197}
198
204double normalPDF(double x);
205
211double normalCDF(double x);
212
218double sigmoid(double x);
219
223constexpr double EPSILON_RELATIVE_EQUALITY = 1e-9;
224
232constexpr unsigned int MAX_ULP_DISTANCE = 4;
233
234namespace internal {
239template <typename T>
240constexpr size_t bit_size_v = sizeof(T) * 8;
241
248template <std::floating_point FloatType>
250 static_assert(bit_size_v<FloatType> == 32 || bit_size_v<FloatType> == 64,
251 "int_t only supports 32-bit and 64-bit floating-point types yet. Please extend to 128-bit types");
253 using type = std::conditional_t<bit_size_v<FloatType> == 32, std::int32_t, std::int64_t>;
254};
255} // namespace internal
256
260template <std::floating_point FloatType>
262
278template <std::floating_point FloatType>
279bool isInUlp(FloatType lhs, FloatType rhs, unsigned int ulpDistance = MAX_ULP_DISTANCE) {
280 // In case the floats are equal in their bitwise representation, return true
281 if (lhs == rhs) {
282 return true;
283 }
284
285 // In case the signs mismatch, return false
286 if (lhs < static_cast<FloatType>(0.0) && rhs > static_cast<FloatType>(0.0) ||
287 lhs > static_cast<FloatType>(0.0) && rhs < static_cast<FloatType>(0.0)) {
288 return false;
289 }
290
291 // Compute ULP distance by interpreting the floating point as an equivalent-sized integer
292 return reinterpret_cast<int_t<FloatType> &>(rhs) - reinterpret_cast<int_t<FloatType> &>(lhs) <= ulpDistance;
293}
294
303template <std::floating_point FloatType>
304bool isNearRel(FloatType a, FloatType b, double maxRelativeDifference = EPSILON_RELATIVE_EQUALITY) {
305 const auto greaterNumber = std::max(std::abs(a), std::abs(b));
306 const auto absoluteDifference = maxRelativeDifference * greaterNumber;
307 const auto diff = std::abs(a - b);
308 return diff <= absoluteDifference;
309}
310
318template <std::floating_point FloatType>
319bool isNearAbs(FloatType a, FloatType b, double maxAbsoluteDifference) {
320 return std::abs(a - b) <= maxAbsoluteDifference;
321}
322
329double roundFixed(double d, int fixedPrecision);
330
337double roundFloating(double d, int floatingPrecision);
338
344Eigen::VectorXd makeVectorXd(const std::vector<double> &elements);
345
351Eigen::VectorXi makeVectorXi(const std::vector<int> &elements);
352} // namespace autopas::utils::Math
Int_t safeAdd(const Int_t &a, const Int_t &b, const Int_t &valUnderflow=std::numeric_limits< Int_t >::min(), const Int_t &valOverflow=std::numeric_limits< Int_t >::max())
Addition function for integer types that is safe against over and underflow.
Definition: Math.h:30
bool isNearAbs(FloatType a, FloatType b, double maxAbsoluteDifference)
Determines if two doubles are near each other.
Definition: Math.h:319
Int_t safeSub(const Int_t &a, const Int_t &b, const Int_t &valUnderflow=std::numeric_limits< Int_t >::min(), const Int_t &valOverflow=std::numeric_limits< Int_t >::max())
Subtraction function for integer types that is safe against over and underflow.
Definition: Math.h:83
constexpr double EPSILON_RELATIVE_EQUALITY
This default relative EPSILON used for the isNearRel function.
Definition: Math.h:223
constexpr unsigned int MAX_ULP_DISTANCE
The default maximal allowed ULP (Units in the Last Place) distance utilized for FloatingPoint compari...
Definition: Math.h:232
constexpr size_t bit_size_v
Helper to find out the bit size of a given type.
Definition: Math.h:240
Int_t safeMul(const Int_t &a, const Int_t &b, const Int_t &valUnderflow=std::numeric_limits< Int_t >::min(), const Int_t &valOverflow=std::numeric_limits< Int_t >::max())
Multiplication function for integer types that is safe against over and underflow.
Definition: Math.h:136
T pow(const T &base)
No-overhead power function with exponent known at compile time.
Definition: Math.h:186
const double normalScale
Factor of PDF of standard normal distribution.
Definition: Math.h:17
typename internal::int_t_impl< FloatType >::type int_t
Returns the correspondingly sized integer type for a given float.
Definition: Math.h:261
Helper struct to get the correspondingly sized integer for a given floating type.
Definition: Math.h:249
std::conditional_t< bit_size_v< FloatType >==32, std::int32_t, std::int64_t > type
access the int data type
Definition: Math.h:253