---
myst:
html_meta:
"description": "Reference for SafeMath.h guarded arithmetic utilities in eOn."
"keywords": "eOn SafeMath, floating-point exceptions, SIGFPE, guarded division, numerical safety"
---
# SafeMath utilities
`client/SafeMath.h` provides lightweight guarded arithmetic to prevent
floating-point exceptions (SIGFPE) in numerical code. All functions live in
`eonc::safemath`.
## Scalar functions
All are `inline constexpr` or `inline` (for `` calls), and marked
`[[nodiscard]]`. Guard branches use `[[unlikely]]` to hint the branch
predictor.
| Function | Signature | Behavior |
|----------|-----------|----------|
| `safe_div` | `(double num, double denom, double fallback=0.0)` | Returns `fallback` when `abs(denom) < eps` |
| `safe_recip` | `(double x, double fallback=0.0)` | `safe_div(1.0, x, fallback)` |
| `safe_acos` | `(double x)` | `std::acos(std::clamp(x, -1.0, 1.0))` |
| `safe_sqrt` | `(double x)` | `std::sqrt(std::max(0.0, x))` |
| `safe_atan_ratio` | `(double num, double denom, double fallback=0.0)` | Guarded `std::atan(num/denom)` |
The epsilon (`1e-300`) is well below any physically meaningful value but above
the FPE trap threshold.
## Eigen templates
Available only when `Eigen/Core` is already included (guarded by
`#if defined(EIGEN_CORE_H) || defined(EIGEN_CORE_MODULE_H)` — Eigen 5 renamed
the Core guard). Always include Eigen headers before `SafeMath.h`.
| Function | Signature | Behavior |
|----------|-----------|----------|
| `safe_normalized` | `(Eigen::MatrixBase const& v, double min_norm=eps)` | Returns zero matrix/vector when `v.norm() < min_norm` |
| `safe_normalize_inplace` | `(Eigen::MatrixBase& v, double min_norm=eps)` | Sets `v` to zero when `v.norm() < min_norm`, else normalizes in place |
### Choosing between normalize variants
- **`safe_normalized(v)`**: Returns a copy. Use for expressions like
`tau = safe_normalized(tau * cos(a) + theta * sin(a))`.
- **`safe_normalize_inplace(v)`**: Modifies in place. Use to replace bare
`.normalize()` calls like `direction.normalize()`.
- **Bare `.normalize()` / `.normalized()`**: Only safe when preceded by an
explicit norm check or when the vector is guaranteed nonzero.
## Design principles
- **Fallback values match existing control flow.** Each call site chooses a
fallback that triggers the same branch the code would take for degenerate
input (reset, skip, clamp, etc.). Valid inputs produce bit-identical results.
- **No overhead on the hot path.** The guard is a single `abs(x) < eps`
comparison with `[[unlikely]]`, which the branch predictor will learn is
almost never taken.
- **Header-only, no link dependencies.** Just `#include "SafeMath.h"` after
your Eigen includes (if using `safe_normalized` or `safe_normalize_inplace`).