From 3f84e92ce697e7ef62a9ad08f05efb1892559528 Mon Sep 17 00:00:00 2001 From: Nathan Sashihara <21227491+n8sh@users.noreply.github.com> Date: Fri, 5 Jun 2020 18:15:28 -0700 Subject: [PATCH] Fix Issue 20197 - Make std.math.isIdentical work in CTFE --- std/math.d | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/std/math.d b/std/math.d index f41de4dce4a..2d8099952f0 100644 --- a/std/math.d +++ b/std/math.d @@ -6382,6 +6382,27 @@ if (isFloatingPoint!(X)) */ bool isIdentical(real x, real y) @trusted pure nothrow @nogc { + if (__ctfe) + { + if (x !is y) return false; + if (x == x) return true; + static if (double.mant_dig != real.mant_dig) + { + // Works because we are in CTFE and there is no way in CTFE to set more + // bits of NaN payload than can fit in a double, and since 2.087 + // changed real.init to be non-signaling I *think* there is no way in + // CTFE for a real to be a signaling NaN unless real and double have + // the same representation so real's bits can be manipulated directly. + double d1 = x, d2 = y; + } + else + { + // Alias to avoid converting signaling to quiet. + alias d1 = x; + alias d2 = y; + } + return *cast(long*) &d1 == *cast(long*) &d2; + } // We're doing a bitwise comparison so the endianness is irrelevant. long* pxs = cast(long *)&x; long* pys = cast(long *)&y; @@ -6419,6 +6440,18 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc assert(!isIdentical(real.infinity, -real.infinity)); } +@safe @nogc pure nothrow unittest +{ + static assert( isIdentical(0.0, 0.0)); + static assert( isIdentical(1.0, 1.0)); + static assert( isIdentical(real.infinity, real.infinity)); + static assert( isIdentical(-real.infinity, -real.infinity)); + static assert( isIdentical(real.nan, real.nan)); + + static assert(!isIdentical(0.0, -0.0)); + static assert(!isIdentical(real.nan, -real.nan)); + static assert(!isIdentical(real.infinity, -real.infinity)); +} /********************************* * Return 1 if sign bit of e is set, 0 if not. */