Skip to content

Commit

Permalink
Merge pull request #7179 from n8sh/issue-20202
Browse files Browse the repository at this point in the history
Fix issues 20202 & 20203 - Make std.math.signbit and copysign work in CTFE
merged-on-behalf-of: Nicholas Wilson <thewilsonator@users.noreply.github.com>
  • Loading branch information
dlang-bot committed Sep 10, 2019
2 parents cb4f35d + e45ac91 commit 4719aa1
Showing 1 changed file with 60 additions and 0 deletions.
60 changes: 60 additions & 0 deletions std/math.d
Expand Up @@ -6877,6 +6877,12 @@ bool isIdentical(real x, real y) @trusted pure nothrow @nogc
*/
int signbit(X)(X x) @nogc @trusted pure nothrow
{
if (__ctfe)
{
double dval = cast(double) x; // Precision can increase or decrease but sign won't change (even NaN).
return 0 > *cast(long*) &dval;
}

alias F = floatTraits!(X);
return ((cast(ubyte *)&x)[F.SIGNPOS_BYTE] & 0x80) != 0;
}
Expand Down Expand Up @@ -6912,6 +6918,36 @@ int signbit(X)(X x) @nogc @trusted pure nothrow
assert(!signbit(real.max));
}

@nogc @safe pure nothrow unittest
{
// CTFE
static assert(!signbit(float.nan));
static assert(signbit(-float.nan));
static assert(!signbit(168.1234f));
static assert(signbit(-168.1234f));
static assert(!signbit(0.0f));
static assert(signbit(-0.0f));
static assert(signbit(-float.max));
static assert(!signbit(float.max));

static assert(!signbit(double.nan));
static assert(signbit(-double.nan));
static assert(!signbit(168.1234));
static assert(signbit(-168.1234));
static assert(!signbit(0.0));
static assert(signbit(-0.0));
static assert(signbit(-double.max));
static assert(!signbit(double.max));

static assert(!signbit(real.nan));
static assert(signbit(-real.nan));
static assert(!signbit(168.1234L));
static assert(signbit(-168.1234L));
static assert(!signbit(0.0L));
static assert(signbit(-0.0L));
static assert(signbit(-real.max));
static assert(!signbit(real.max));
}

/**
Params:
Expand All @@ -6923,6 +6959,10 @@ Returns:
R copysign(R, X)(R to, X from) @trusted pure nothrow @nogc
if (isFloatingPoint!(R) && isFloatingPoint!(X))
{
if (__ctfe)
{
return signbit(to) == signbit(from) ? to : -to;
}
ubyte* pto = cast(ubyte *)&to;
const ubyte* pfrom = cast(ubyte *)&from;

Expand Down Expand Up @@ -6988,6 +7028,26 @@ if (isIntegral!(X) && isFloatingPoint!(R))
}
}}
}
// CTFE
static foreach (X; AliasSeq!(float, double, real, int, long))
{
static foreach (Y; AliasSeq!(float, double, real))
{{
enum X x = 21;
enum Y y = 23.8;

assert(21.0 == copysign(x, y));
assert(21.0 == copysign(-x, y));
assert(-21.0 == copysign(x, -y));
assert(-21.0 == copysign(-x, -y));

static if (isFloatingPoint!X)
{
static assert(isNaN(copysign(X.nan, y)) && !signbit(copysign(X.nan, y)));
assert(isNaN(copysign(X.nan, -y)) && signbit(copysign(X.nan, -y)));
}
}}
}
}

/*********************************
Expand Down

0 comments on commit 4719aa1

Please sign in to comment.