Loading...
Searching...
No Matches
SafeMath.h
Go to the documentation of this file.
1/*
2** This file is part of eOn.
3**
4** SPDX-License-Identifier: BSD-3-Clause
5**
6** Copyright (c) 2010--present, eOn Development Team
7** All rights reserved.
8**
9** Repo:
10** https://github.com/TheochemUI/eOn
11*/
12#pragma once
13
14#include <algorithm>
15#include <cmath>
16
17namespace eonc::safemath {
18
19inline constexpr double eps = 1e-300;
20
21[[nodiscard]] inline constexpr double safe_div(double num, double denom,
22 double fallback = 0.0) {
23 if ((denom < 0.0 ? -denom : denom) < eps) [[unlikely]] {
24 return fallback;
25 }
26 return num / denom;
27}
28
29[[nodiscard]] inline constexpr double safe_recip(double x,
30 double fallback = 0.0) {
31 return safe_div(1.0, x, fallback);
32}
33
34[[nodiscard]] inline double safe_acos(double x) {
35 return std::acos(std::clamp(x, -1.0, 1.0));
36}
37
38[[nodiscard]] inline double safe_sqrt(double x) {
39 return std::sqrt(std::max(0.0, x));
40}
41
42[[nodiscard]] inline double safe_atan_ratio(double num, double denom,
43 double fallback = 0.0) {
44 if ((denom < 0.0 ? -denom : denom) < eps) [[unlikely]] {
45 return fallback;
46 }
47 return std::atan(num / denom);
48}
49
50} // namespace eonc::safemath
51
52// Eigen-dependent utilities, available only when Eigen is already included.
53// Include order: Eigen headers first, then SafeMath.h.
54// Eigen < 5 guards Eigen/Core with EIGEN_CORE_H; Eigen >= 5 renamed the
55// guard to EIGEN_CORE_MODULE_H. Accept either, or safe_normalized silently
56// disappears and every consumer fails to compile against Eigen 5.
57#if defined(EIGEN_CORE_H) || defined(EIGEN_CORE_MODULE_H)
58namespace eonc::safemath {
59
60template <typename Derived>
61[[nodiscard]] auto safe_normalized(const Eigen::MatrixBase<Derived> &v,
62 double min_norm = eps) {
63 using ResultType = typename Derived::PlainObject;
64 double n = v.norm();
65 if (n < min_norm) [[unlikely]] {
66 return ResultType::Zero(v.rows(), v.cols()).eval();
67 }
68 return (v / n).eval();
69}
70
71template <typename Derived>
72void safe_normalize_inplace(Eigen::MatrixBase<Derived> &v,
73 double min_norm = eps) {
74 double n = v.norm();
75 if (n < min_norm) [[unlikely]] {
76 v.derived().setZero();
77 } else {
78 v.derived() /= n;
79 }
80}
81
82} // namespace eonc::safemath
83#endif
constexpr double safe_div(double num, double denom, double fallback=0.0)
Definition SafeMath.h:21
double safe_acos(double x)
Definition SafeMath.h:34
constexpr double eps
Definition SafeMath.h:19
constexpr double safe_recip(double x, double fallback=0.0)
Definition SafeMath.h:29
double safe_sqrt(double x)
Definition SafeMath.h:38
double safe_atan_ratio(double num, double denom, double fallback=0.0)
Definition SafeMath.h:42