From e8a5010c0338357c08c740de121b660aa933d5f4 Mon Sep 17 00:00:00 2001 From: Peter Klausler <35819229+klausler@users.noreply.github.com> Date: Thu, 25 Jan 2024 15:24:54 -0800 Subject: [PATCH] [flang][runtime] Use std::fmod for most MOD/MODULO (#78745) The new accurate algorithm for real MOD and MODULO in the runtime is not as fast as std::fmod(), which is also accurate. So use std::fmod() for those floating-point types that it supports. Fixes https://github.com/llvm/llvm-project/issues/78641. --- flang/runtime/numeric.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp index 3f6f553e7bb554..df73502bee5fed 100644 --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -144,6 +144,21 @@ inline RT_API_ATTRS T RealMod( return std::numeric_limits::quiet_NaN(); } else if (std::isinf(p)) { return a; + } else if constexpr (std::is_same_v || std::is_same_v || + std::is_same_v) { + // std::fmod() semantics on signed operands seems to match + // the requirements of MOD(). MODULO() needs adjustment. + T result{std::fmod(a, p)}; + if constexpr (IS_MODULO) { + if ((a < 0) != (p < 0)) { + if (result == 0.) { + result = -result; + } else { + result += p; + } + } + } + return result; } else { // The standard defines MOD(a,p)=a-AINT(a/p)*p and // MODULO(a,p)=a-FLOOR(a/p)*p, but those definitions lose