From 1eff36b757b6c3befdaf8438d00f69fcb0328d17 Mon Sep 17 00:00:00 2001 From: Jonah Miller Date: Fri, 10 Apr 2026 12:37:59 -0400 Subject: [PATCH 1/4] fix robust utils --- singularity-eos/base/robust_utils.hpp | 9 +++- test/CMakeLists.txt | 1 + test/test_robust_utils.cpp | 77 +++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 test/test_robust_utils.cpp diff --git a/singularity-eos/base/robust_utils.hpp b/singularity-eos/base/robust_utils.hpp index 23b8dcc6e48..2f361b9e8d5 100644 --- a/singularity-eos/base/robust_utils.hpp +++ b/singularity-eos/base/robust_utils.hpp @@ -18,6 +18,7 @@ #include #include #include +#include namespace singularity { namespace robust { @@ -53,8 +54,12 @@ Real make_bounded(const Real val, const Real vmin, const Real vmax) { } template -PORTABLE_FORCEINLINE_FUNCTION int sgn(const T &val) { - return (T(0) <= val) - (val < T(0)); +PORTABLE_FORCEINLINE_FUNCTION auto sgn(const T &val) { + if constexpr (std::is_unsigned_v) { + return 1; + } else { + return (T(0) <= val) - (val < T(0)); + } } template diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 30d7c303266..d4e65ab60f4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -37,6 +37,7 @@ add_executable( test_eos_modifiers_minimal.cpp test_eos_vector.cpp test_math_utils.cpp + test_robust_utils.cpp test_modifier_floored_energy.cpp test_variadic_utils.cpp test_bounds.cpp diff --git a/test/test_robust_utils.cpp b/test/test_robust_utils.cpp new file mode 100644 index 00000000000..90ca6b8d3a0 --- /dev/null +++ b/test/test_robust_utils.cpp @@ -0,0 +1,77 @@ +//------------------------------------------------------------------------------ +// © 2021-2026. Triad National Security, LLC. All rights reserved. This +// program was produced under U.S. Government contract 89233218CNA000001 +// for Los Alamos National Laboratory (LANL), which is operated by Triad +// National Security, LLC for the U.S. Department of Energy/National +// Nuclear Security Administration. All rights in the program are +// reserved by Triad National Security, LLC, and the U.S. Department of +// Energy/National Nuclear Security Administration. The Government is +// granted for itself and others acting on its behalf a nonexclusive, +// paid-up, irrevocable worldwide license in this material to reproduce, +// prepare derivative works, distribute copies to the public, perform +// publicly and display publicly, and to permit others to do so. +//------------------------------------------------------------------------------ + +// This file is made in part with generative AI + +#include +#include + +#include + +#ifndef CATCH_CONFIG_FAST_COMPILE +#define CATCH_CONFIG_FAST_COMPILE +#include +#include +#endif + +namespace robust = singularity::robust; + +SCENARIO("Robust utilities expose scaled floating-point limits", "[RobustUtils]") { + REQUIRE(robust::SMALL() == 10 * std::numeric_limits::min()); + REQUIRE(robust::EPS() == 10 * std::numeric_limits::epsilon()); + REQUIRE(robust::min_exp_arg() == + Catch::Approx((std::numeric_limits::min_exponent - 1) * M_LN2)); + REQUIRE(robust::max_exp_arg() == + Catch::Approx(std::numeric_limits::max_exponent * M_LN2)); +} + +SCENARIO("Robust utilities bound scalar values away from unsafe regions", + "[RobustUtils]") { + constexpr Real vmin = 0.0; + constexpr Real vmax = 1.0; + + REQUIRE(robust::make_positive(-1.0) == robust::EPS()); + REQUIRE(robust::make_positive(2.5) == Catch::Approx(2.5)); + + REQUIRE(robust::make_bounded(-1.0, vmin, vmax) == Catch::Approx(vmin + robust::EPS())); + REQUIRE(robust::make_bounded(0.5, vmin, vmax) == Catch::Approx(0.5)); + REQUIRE(robust::make_bounded(2.0, vmin, vmax) == + Catch::Approx(vmax * (1.0 - robust::EPS()))); +} + +SCENARIO("Robust utilities preserve sign information and regularize ratios", + "[RobustUtils]") { + REQUIRE(robust::sgn(-3.0) == -1); + REQUIRE(robust::sgn(0.0) == 1); + REQUIRE(robust::sgn(4.0) == 1); + REQUIRE(robust::sgn(-3) == -1); + REQUIRE(robust::sgn(0) == 1); + REQUIRE(robust::sgn(4) == 1); + REQUIRE(robust::sgn(0u) == 1); + REQUIRE(robust::sgn(4u) == 1); + + REQUIRE(robust::ratio(12.0, 3.0) == Catch::Approx(4.0)); + REQUIRE(robust::ratio(12.0, -3.0) == Catch::Approx(-4.0)); + + const Real ratio_with_zero = robust::ratio(1.0, 0.0); + REQUIRE(std::isfinite(ratio_with_zero)); + REQUIRE(ratio_with_zero == Catch::Approx(1.0 / robust::SMALL())); +} + +SCENARIO("Robust utilities clamp exponential evaluation to a safe range", + "[RobustUtils]") { + REQUIRE(robust::safe_arg_exp(1.5) == Catch::Approx(std::exp(1.5))); + REQUIRE(robust::safe_arg_exp(robust::min_exp_arg() - 1.0) == 0.0); + REQUIRE(std::isinf(robust::safe_arg_exp(robust::max_exp_arg() + 1.0))); +} From 5acabf423a9e7b58d724fe1520696b4c5db2f5a0 Mon Sep 17 00:00:00 2001 From: Jonah Miller Date: Fri, 10 Apr 2026 12:39:12 -0400 Subject: [PATCH 2/4] might as well make signature an int --- singularity-eos/base/robust_utils.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singularity-eos/base/robust_utils.hpp b/singularity-eos/base/robust_utils.hpp index 2f361b9e8d5..faefd0feda2 100644 --- a/singularity-eos/base/robust_utils.hpp +++ b/singularity-eos/base/robust_utils.hpp @@ -54,7 +54,7 @@ Real make_bounded(const Real val, const Real vmin, const Real vmax) { } template -PORTABLE_FORCEINLINE_FUNCTION auto sgn(const T &val) { +PORTABLE_FORCEINLINE_FUNCTION int sgn(const T &val) { if constexpr (std::is_unsigned_v) { return 1; } else { From e0ad1f0c2bd49cb8434f6236beb91435b86abf14 Mon Sep 17 00:00:00 2001 From: Jonah Miller Date: Fri, 10 Apr 2026 12:42:11 -0400 Subject: [PATCH 3/4] CC --- singularity-eos/base/robust_utils.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/singularity-eos/base/robust_utils.hpp b/singularity-eos/base/robust_utils.hpp index faefd0feda2..6c51d89abbd 100644 --- a/singularity-eos/base/robust_utils.hpp +++ b/singularity-eos/base/robust_utils.hpp @@ -1,5 +1,5 @@ //------------------------------------------------------------------------------ -// © 2021-2023. Triad National Security, LLC. All rights reserved. This +// © 2021-2026. Triad National Security, LLC. All rights reserved. This // program was produced under U.S. Government contract 89233218CNA000001 // for Los Alamos National Laboratory (LANL), which is operated by Triad // National Security, LLC for the U.S. Department of Energy/National From d9b0c48d003471de66027926b02e76bf1b709a95 Mon Sep 17 00:00:00 2001 From: Jonah Miller Date: Fri, 10 Apr 2026 12:42:57 -0400 Subject: [PATCH 4/4] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26b18cce83a..dfe8385a87a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Changed (changing behavior/API/variables/...) ### Infrastructure (changes irrelevant to downstream codes) +- [[PR633]](https://github.com/lanl/singularity-eos/pull/633) Make robust::sgn handle unsigned properly - [[PR629]](https://github.com/lanl/singularity-eos/pull/629) Use macros and eos_base and eos_variant to reduce boiler plate - [[PR626]](https://github.com/lanl/singularity-eos/pull/626) Fix C++20 warnings related to lambdas