From 239a3c9f7a8061e1a7de6c22b3123733ebb02379 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 1/4] Fix Issue 20197 - Make std.math.isIdentical work in CTFE --- std/math/traits.d | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/std/math/traits.d b/std/math/traits.d index 81ab1b789db..9b00da64165 100644 --- a/std/math/traits.d +++ b/std/math/traits.d @@ -466,8 +466,27 @@ if (isFloatingPoint!(X)) */ bool isIdentical(real x, real y) @trusted pure nothrow @nogc { - import std.math.traits : floatTraits, RealFormat; - + if (__ctfe) + { + if (x !is y) return false; + if (x == x) return true; // If not NaN `is` implies identical representation. + 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; @@ -491,7 +510,6 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc assert(0, "isIdentical not implemented"); } } - /// @safe @nogc pure nothrow unittest { @@ -504,7 +522,18 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc assert(!isIdentical(real.nan, -real.nan)); 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. */ From 266694d7b998f43753c2cc4614ff0e772ca4348a Mon Sep 17 00:00:00 2001 From: runiixx Date: Sat, 7 Dec 2024 10:40:31 +0200 Subject: [PATCH 2/4] Added tests for function isIdentical Signed-off-by: runiixx --- std/math/traits.d | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/std/math/traits.d b/std/math/traits.d index 9b00da64165..e4fbaee95de 100644 --- a/std/math/traits.d +++ b/std/math/traits.d @@ -21,6 +21,7 @@ module std.math.traits; import std.traits : isFloatingPoint, isIntegral, isNumeric, isSigned; + /********************************* * Determines if $(D_PARAM x) is NaN. * Params: @@ -513,27 +514,43 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc /// @safe @nogc pure nothrow unittest { + + // We're forcing the CTFE to run by assigning the result of the function to an enum + enum test1 = isIdentical(1.0,1.0); + enum test2 = isIdentical(real.nan,real.nan); + enum test3 = isIdentical(real.infinity, real.infinity); + enum test4 = isIdentical(real.infinity, real.infinity); + enum test5 = isIdentical(0.0, 0.0); + + assert(test1); + assert(test2); + assert(test3); + assert(test4); + assert(test5); + + enum test6 = !isIdentical(0.0, -0.0); + enum test7 = !isIdentical(real.nan, -real.nan); + enum test8 = !isIdentical(real.infinity, -real.infinity); + + assert(test6); + assert(test7); + assert(test8); + +} + +@safe @nogc pure nothrow unittest +{ + assert( !isIdentical(1.2,1.3)); assert( isIdentical(0.0, 0.0)); assert( isIdentical(1.0, 1.0)); assert( isIdentical(real.infinity, real.infinity)); assert( isIdentical(-real.infinity, -real.infinity)); + assert( isIdentical(real.nan, real.nan)); assert(!isIdentical(0.0, -0.0)); assert(!isIdentical(real.nan, -real.nan)); 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. */ From a20e43865672f56ea3a62f3e9dd240e80133891c Mon Sep 17 00:00:00 2001 From: runiixx Date: Sat, 7 Dec 2024 11:35:50 +0200 Subject: [PATCH 3/4] Fix Issue 10386 Signed-off-by: runiixx --- std/math/traits.d | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/std/math/traits.d b/std/math/traits.d index e4fbaee95de..53f15674fc4 100644 --- a/std/math/traits.d +++ b/std/math/traits.d @@ -534,8 +534,7 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc assert(test6); assert(test7); - assert(test8); - + assert(test8); } @safe @nogc pure nothrow unittest From 7341230808d71ad6cd7af4b52ab4a10fc10f2a72 Mon Sep 17 00:00:00 2001 From: runiixx Date: Sat, 7 Dec 2024 11:49:33 +0200 Subject: [PATCH 4/4] fixing style Signed-off-by: runiixx --- std/math/traits.d | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/std/math/traits.d b/std/math/traits.d index 53f15674fc4..8aba6a6b1c6 100644 --- a/std/math/traits.d +++ b/std/math/traits.d @@ -514,7 +514,6 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc /// @safe @nogc pure nothrow unittest { - // We're forcing the CTFE to run by assigning the result of the function to an enum enum test1 = isIdentical(1.0,1.0); enum test2 = isIdentical(real.nan,real.nan); @@ -534,7 +533,7 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc assert(test6); assert(test7); - assert(test8); + assert(test8); } @safe @nogc pure nothrow unittest