public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp.
@ 2021-10-13 8:31 Iain D Sandoe
0 siblings, 0 replies; 7+ messages in thread
From: Iain D Sandoe @ 2021-10-13 8:31 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:7502a35c74995a95ea63c82883b2f7adb43991ea
commit 7502a35c74995a95ea63c82883b2f7adb43991ea
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri Dec 11 00:59:19 2020 +0000
D, Math, IBM128 : Use GCC builtins for floor and exp.
This makes use of GCC's long double format builtins, which
in turn will call out to a libc implementation where needed.
Diff:
---
libphobos/src/std/math.d | 183 ++++++++++++++++++++++++++---------------------
1 file changed, 101 insertions(+), 82 deletions(-)
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 336c11a55e2..0aecbc42388 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -460,108 +460,118 @@ else
T floorImpl(T)(const T x) @trusted pure nothrow @nogc
{
alias F = floatTraits!(T);
- // Take care not to trigger library calls from the compiler,
- // while ensuring that we don't get defeated by some optimizers.
- union floatBits
- {
- T rv;
- ushort[T.sizeof/2] vu;
- // Other kinds of extractors for real formats.
- static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
- }
- floatBits y = void;
- y.rv = x;
-
- // Find the exponent (power of 2)
- // Do this by shifting the raw value so that the exponent lies in the low bits,
- // then mask out the sign bit, and subtract the bias.
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ibmExtended)
{
- int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ import gcc.builtins;
+ return __builtin_floorl(x);
}
- else static if (F.realFormat == RealFormat.ieeeDouble)
+ else
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+ // Take care not to trigger library calls from the compiler,
+ // while ensuring that we don't get defeated by some optimizers.
+ union floatBits
+ {
+ T rv;
+ ushort[T.sizeof/2] vu;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
- }
- else static if (F.realFormat == RealFormat.ieeeExtended ||
- F.realFormat == RealFormat.ieeeExtended53)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Other kinds of extractors for real formats.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ int vi;
+ }
+ floatBits y = void;
+ y.rv = x;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 4;
- }
- else static if (F.realFormat == RealFormat.ieeeQuadruple)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Find the exponent (power of 2)
+ // Do this by shifting the raw value so that the exponent lies in the
+ // low bits, then mask out the sign bit, and subtract the bias.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 7;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 3;
}
- else
- static assert(false, "Not implemented for this architecture");
+ else static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
- if (exp < 0)
- {
- if (x < 0.0)
- return -1.0;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 7;
+ }
else
- return 0.0;
- }
+ static assert(false, "Not implemented for this architecture");
- static if (F.realFormat == RealFormat.ieeeSingle)
- {
- if (exp < (T.mant_dig - 1))
+ if (exp < 0)
{
- // Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ if (x < 0.0)
+ return -1.0;
+ else
+ return 0.0;
+ }
- if ((y.vi & fraction_mask) != 0)
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ if (exp < (T.mant_dig - 1))
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
- y.vi &= ~fraction_mask;
+ // Clear all bits representing the fraction part.
+ const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+
+ if ((y.vi & fraction_mask) != 0)
+ {
+ // If 'x' is negative, then first substract 1.0 from
+ // the value.
+ if (y.vi < 0)
+ y.vi += 0x00800000 >> exp;
+ y.vi &= ~fraction_mask;
+ }
}
}
- }
- else
- {
- static if (F.realFormat == RealFormat.ieeeExtended53)
- exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- exp = (T.mant_dig - 1) - exp;
-
- // Zero 16 bits at a time.
- while (exp >= 16)
{
- version (LittleEndian)
- y.vu[pos++] = 0;
+ static if (F.realFormat == RealFormat.ieeeExtended53)
+ exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- y.vu[pos--] = 0;
- exp -= 16;
- }
+ exp = (T.mant_dig - 1) - exp;
+
+ // Zero 16 bits at a time.
+ while (exp >= 16)
+ {
+ version (LittleEndian)
+ y.vu[pos++] = 0;
+ else
+ y.vu[pos--] = 0;
+ exp -= 16;
+ }
- // Clear the remaining bits.
- if (exp > 0)
- y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
+ // Clear the remaining bits.
+ if (exp > 0)
+ y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
- if ((x < 0.0) && (x != y.rv))
- y.rv -= 1.0;
- }
+ if ((x < 0.0) && (x != y.rv))
+ y.rv -= 1.0;
+ }
- return y.rv;
+ return y.rv;
+ }
}
public:
@@ -1767,6 +1777,13 @@ real exp(real x) @trusted pure nothrow @nogc
else
{
alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ibmExtended)
+ {
+ import gcc.builtins;
+ return __builtin_expl(x);
+ }
+ else
+ {
static if (F.realFormat == RealFormat.ieeeDouble)
{
// Coefficients for exp(x)
@@ -1872,6 +1889,7 @@ real exp(real x) @trusted pure nothrow @nogc
return x;
}
+ }
}
/// ditto
@@ -3897,7 +3915,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max);
// Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal)
- static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4);
+ static assert((real.min_normal*real.max > 2 && real.min_normal*real.max <= 4)
+ || floatTraits!real.realFormat == RealFormat.ibmExtended);
real u = fabs(x);
real v = fabs(y);
@@ -4524,7 +4543,7 @@ long lrint(real x) @trusted pure nothrow @nogc
}
else
{
- static assert(false, "real type not supported by lrint()");
+ assert(false, "real type not supported by lrint()");
}
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp.
@ 2021-10-18 15:54 Iain D Sandoe
0 siblings, 0 replies; 7+ messages in thread
From: Iain D Sandoe @ 2021-10-18 15:54 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:b860e07d422b2a5f2f29a8e4848d87fe6cabdc0e
commit b860e07d422b2a5f2f29a8e4848d87fe6cabdc0e
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri Dec 11 00:59:19 2020 +0000
D, Math, IBM128 : Use GCC builtins for floor and exp.
This makes use of GCC's long double format builtins, which
in turn will call out to a libc implementation where needed.
Diff:
---
libphobos/src/std/math.d | 183 ++++++++++++++++++++++++++---------------------
1 file changed, 101 insertions(+), 82 deletions(-)
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 336c11a55e2..0aecbc42388 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -460,108 +460,118 @@ else
T floorImpl(T)(const T x) @trusted pure nothrow @nogc
{
alias F = floatTraits!(T);
- // Take care not to trigger library calls from the compiler,
- // while ensuring that we don't get defeated by some optimizers.
- union floatBits
- {
- T rv;
- ushort[T.sizeof/2] vu;
- // Other kinds of extractors for real formats.
- static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
- }
- floatBits y = void;
- y.rv = x;
-
- // Find the exponent (power of 2)
- // Do this by shifting the raw value so that the exponent lies in the low bits,
- // then mask out the sign bit, and subtract the bias.
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ibmExtended)
{
- int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ import gcc.builtins;
+ return __builtin_floorl(x);
}
- else static if (F.realFormat == RealFormat.ieeeDouble)
+ else
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+ // Take care not to trigger library calls from the compiler,
+ // while ensuring that we don't get defeated by some optimizers.
+ union floatBits
+ {
+ T rv;
+ ushort[T.sizeof/2] vu;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
- }
- else static if (F.realFormat == RealFormat.ieeeExtended ||
- F.realFormat == RealFormat.ieeeExtended53)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Other kinds of extractors for real formats.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ int vi;
+ }
+ floatBits y = void;
+ y.rv = x;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 4;
- }
- else static if (F.realFormat == RealFormat.ieeeQuadruple)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Find the exponent (power of 2)
+ // Do this by shifting the raw value so that the exponent lies in the
+ // low bits, then mask out the sign bit, and subtract the bias.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 7;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 3;
}
- else
- static assert(false, "Not implemented for this architecture");
+ else static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
- if (exp < 0)
- {
- if (x < 0.0)
- return -1.0;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 7;
+ }
else
- return 0.0;
- }
+ static assert(false, "Not implemented for this architecture");
- static if (F.realFormat == RealFormat.ieeeSingle)
- {
- if (exp < (T.mant_dig - 1))
+ if (exp < 0)
{
- // Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ if (x < 0.0)
+ return -1.0;
+ else
+ return 0.0;
+ }
- if ((y.vi & fraction_mask) != 0)
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ if (exp < (T.mant_dig - 1))
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
- y.vi &= ~fraction_mask;
+ // Clear all bits representing the fraction part.
+ const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+
+ if ((y.vi & fraction_mask) != 0)
+ {
+ // If 'x' is negative, then first substract 1.0 from
+ // the value.
+ if (y.vi < 0)
+ y.vi += 0x00800000 >> exp;
+ y.vi &= ~fraction_mask;
+ }
}
}
- }
- else
- {
- static if (F.realFormat == RealFormat.ieeeExtended53)
- exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- exp = (T.mant_dig - 1) - exp;
-
- // Zero 16 bits at a time.
- while (exp >= 16)
{
- version (LittleEndian)
- y.vu[pos++] = 0;
+ static if (F.realFormat == RealFormat.ieeeExtended53)
+ exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- y.vu[pos--] = 0;
- exp -= 16;
- }
+ exp = (T.mant_dig - 1) - exp;
+
+ // Zero 16 bits at a time.
+ while (exp >= 16)
+ {
+ version (LittleEndian)
+ y.vu[pos++] = 0;
+ else
+ y.vu[pos--] = 0;
+ exp -= 16;
+ }
- // Clear the remaining bits.
- if (exp > 0)
- y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
+ // Clear the remaining bits.
+ if (exp > 0)
+ y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
- if ((x < 0.0) && (x != y.rv))
- y.rv -= 1.0;
- }
+ if ((x < 0.0) && (x != y.rv))
+ y.rv -= 1.0;
+ }
- return y.rv;
+ return y.rv;
+ }
}
public:
@@ -1767,6 +1777,13 @@ real exp(real x) @trusted pure nothrow @nogc
else
{
alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ibmExtended)
+ {
+ import gcc.builtins;
+ return __builtin_expl(x);
+ }
+ else
+ {
static if (F.realFormat == RealFormat.ieeeDouble)
{
// Coefficients for exp(x)
@@ -1872,6 +1889,7 @@ real exp(real x) @trusted pure nothrow @nogc
return x;
}
+ }
}
/// ditto
@@ -3897,7 +3915,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max);
// Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal)
- static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4);
+ static assert((real.min_normal*real.max > 2 && real.min_normal*real.max <= 4)
+ || floatTraits!real.realFormat == RealFormat.ibmExtended);
real u = fabs(x);
real v = fabs(y);
@@ -4524,7 +4543,7 @@ long lrint(real x) @trusted pure nothrow @nogc
}
else
{
- static assert(false, "real type not supported by lrint()");
+ assert(false, "real type not supported by lrint()");
}
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp.
@ 2021-10-15 19:34 Iain D Sandoe
0 siblings, 0 replies; 7+ messages in thread
From: Iain D Sandoe @ 2021-10-15 19:34 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:6c1f29b6db062963417bd8d804cb6e5f68fc119c
commit 6c1f29b6db062963417bd8d804cb6e5f68fc119c
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri Dec 11 00:59:19 2020 +0000
D, Math, IBM128 : Use GCC builtins for floor and exp.
This makes use of GCC's long double format builtins, which
in turn will call out to a libc implementation where needed.
Diff:
---
libphobos/src/std/math.d | 183 ++++++++++++++++++++++++++---------------------
1 file changed, 101 insertions(+), 82 deletions(-)
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 336c11a55e2..0aecbc42388 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -460,108 +460,118 @@ else
T floorImpl(T)(const T x) @trusted pure nothrow @nogc
{
alias F = floatTraits!(T);
- // Take care not to trigger library calls from the compiler,
- // while ensuring that we don't get defeated by some optimizers.
- union floatBits
- {
- T rv;
- ushort[T.sizeof/2] vu;
- // Other kinds of extractors for real formats.
- static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
- }
- floatBits y = void;
- y.rv = x;
-
- // Find the exponent (power of 2)
- // Do this by shifting the raw value so that the exponent lies in the low bits,
- // then mask out the sign bit, and subtract the bias.
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ibmExtended)
{
- int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ import gcc.builtins;
+ return __builtin_floorl(x);
}
- else static if (F.realFormat == RealFormat.ieeeDouble)
+ else
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+ // Take care not to trigger library calls from the compiler,
+ // while ensuring that we don't get defeated by some optimizers.
+ union floatBits
+ {
+ T rv;
+ ushort[T.sizeof/2] vu;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
- }
- else static if (F.realFormat == RealFormat.ieeeExtended ||
- F.realFormat == RealFormat.ieeeExtended53)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Other kinds of extractors for real formats.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ int vi;
+ }
+ floatBits y = void;
+ y.rv = x;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 4;
- }
- else static if (F.realFormat == RealFormat.ieeeQuadruple)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Find the exponent (power of 2)
+ // Do this by shifting the raw value so that the exponent lies in the
+ // low bits, then mask out the sign bit, and subtract the bias.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 7;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 3;
}
- else
- static assert(false, "Not implemented for this architecture");
+ else static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
- if (exp < 0)
- {
- if (x < 0.0)
- return -1.0;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 7;
+ }
else
- return 0.0;
- }
+ static assert(false, "Not implemented for this architecture");
- static if (F.realFormat == RealFormat.ieeeSingle)
- {
- if (exp < (T.mant_dig - 1))
+ if (exp < 0)
{
- // Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ if (x < 0.0)
+ return -1.0;
+ else
+ return 0.0;
+ }
- if ((y.vi & fraction_mask) != 0)
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ if (exp < (T.mant_dig - 1))
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
- y.vi &= ~fraction_mask;
+ // Clear all bits representing the fraction part.
+ const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+
+ if ((y.vi & fraction_mask) != 0)
+ {
+ // If 'x' is negative, then first substract 1.0 from
+ // the value.
+ if (y.vi < 0)
+ y.vi += 0x00800000 >> exp;
+ y.vi &= ~fraction_mask;
+ }
}
}
- }
- else
- {
- static if (F.realFormat == RealFormat.ieeeExtended53)
- exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- exp = (T.mant_dig - 1) - exp;
-
- // Zero 16 bits at a time.
- while (exp >= 16)
{
- version (LittleEndian)
- y.vu[pos++] = 0;
+ static if (F.realFormat == RealFormat.ieeeExtended53)
+ exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- y.vu[pos--] = 0;
- exp -= 16;
- }
+ exp = (T.mant_dig - 1) - exp;
+
+ // Zero 16 bits at a time.
+ while (exp >= 16)
+ {
+ version (LittleEndian)
+ y.vu[pos++] = 0;
+ else
+ y.vu[pos--] = 0;
+ exp -= 16;
+ }
- // Clear the remaining bits.
- if (exp > 0)
- y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
+ // Clear the remaining bits.
+ if (exp > 0)
+ y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
- if ((x < 0.0) && (x != y.rv))
- y.rv -= 1.0;
- }
+ if ((x < 0.0) && (x != y.rv))
+ y.rv -= 1.0;
+ }
- return y.rv;
+ return y.rv;
+ }
}
public:
@@ -1767,6 +1777,13 @@ real exp(real x) @trusted pure nothrow @nogc
else
{
alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ibmExtended)
+ {
+ import gcc.builtins;
+ return __builtin_expl(x);
+ }
+ else
+ {
static if (F.realFormat == RealFormat.ieeeDouble)
{
// Coefficients for exp(x)
@@ -1872,6 +1889,7 @@ real exp(real x) @trusted pure nothrow @nogc
return x;
}
+ }
}
/// ditto
@@ -3897,7 +3915,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max);
// Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal)
- static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4);
+ static assert((real.min_normal*real.max > 2 && real.min_normal*real.max <= 4)
+ || floatTraits!real.realFormat == RealFormat.ibmExtended);
real u = fabs(x);
real v = fabs(y);
@@ -4524,7 +4543,7 @@ long lrint(real x) @trusted pure nothrow @nogc
}
else
{
- static assert(false, "real type not supported by lrint()");
+ assert(false, "real type not supported by lrint()");
}
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp.
@ 2021-10-11 20:35 Iain D Sandoe
0 siblings, 0 replies; 7+ messages in thread
From: Iain D Sandoe @ 2021-10-11 20:35 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:34ca0a4aa35b72f9d2b55280000d1e288dd29646
commit 34ca0a4aa35b72f9d2b55280000d1e288dd29646
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri Dec 11 00:59:19 2020 +0000
D, Math, IBM128 : Use GCC builtins for floor and exp.
This makes use of GCC's long double format builtins, which
in turn will call out to a libc implementation where needed.
Diff:
---
libphobos/src/std/math.d | 183 ++++++++++++++++++++++++++---------------------
1 file changed, 101 insertions(+), 82 deletions(-)
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 336c11a55e2..0aecbc42388 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -460,108 +460,118 @@ else
T floorImpl(T)(const T x) @trusted pure nothrow @nogc
{
alias F = floatTraits!(T);
- // Take care not to trigger library calls from the compiler,
- // while ensuring that we don't get defeated by some optimizers.
- union floatBits
- {
- T rv;
- ushort[T.sizeof/2] vu;
- // Other kinds of extractors for real formats.
- static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
- }
- floatBits y = void;
- y.rv = x;
-
- // Find the exponent (power of 2)
- // Do this by shifting the raw value so that the exponent lies in the low bits,
- // then mask out the sign bit, and subtract the bias.
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ibmExtended)
{
- int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ import gcc.builtins;
+ return __builtin_floorl(x);
}
- else static if (F.realFormat == RealFormat.ieeeDouble)
+ else
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+ // Take care not to trigger library calls from the compiler,
+ // while ensuring that we don't get defeated by some optimizers.
+ union floatBits
+ {
+ T rv;
+ ushort[T.sizeof/2] vu;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
- }
- else static if (F.realFormat == RealFormat.ieeeExtended ||
- F.realFormat == RealFormat.ieeeExtended53)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Other kinds of extractors for real formats.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ int vi;
+ }
+ floatBits y = void;
+ y.rv = x;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 4;
- }
- else static if (F.realFormat == RealFormat.ieeeQuadruple)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Find the exponent (power of 2)
+ // Do this by shifting the raw value so that the exponent lies in the
+ // low bits, then mask out the sign bit, and subtract the bias.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 7;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 3;
}
- else
- static assert(false, "Not implemented for this architecture");
+ else static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
- if (exp < 0)
- {
- if (x < 0.0)
- return -1.0;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 7;
+ }
else
- return 0.0;
- }
+ static assert(false, "Not implemented for this architecture");
- static if (F.realFormat == RealFormat.ieeeSingle)
- {
- if (exp < (T.mant_dig - 1))
+ if (exp < 0)
{
- // Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ if (x < 0.0)
+ return -1.0;
+ else
+ return 0.0;
+ }
- if ((y.vi & fraction_mask) != 0)
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ if (exp < (T.mant_dig - 1))
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
- y.vi &= ~fraction_mask;
+ // Clear all bits representing the fraction part.
+ const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+
+ if ((y.vi & fraction_mask) != 0)
+ {
+ // If 'x' is negative, then first substract 1.0 from
+ // the value.
+ if (y.vi < 0)
+ y.vi += 0x00800000 >> exp;
+ y.vi &= ~fraction_mask;
+ }
}
}
- }
- else
- {
- static if (F.realFormat == RealFormat.ieeeExtended53)
- exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- exp = (T.mant_dig - 1) - exp;
-
- // Zero 16 bits at a time.
- while (exp >= 16)
{
- version (LittleEndian)
- y.vu[pos++] = 0;
+ static if (F.realFormat == RealFormat.ieeeExtended53)
+ exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- y.vu[pos--] = 0;
- exp -= 16;
- }
+ exp = (T.mant_dig - 1) - exp;
+
+ // Zero 16 bits at a time.
+ while (exp >= 16)
+ {
+ version (LittleEndian)
+ y.vu[pos++] = 0;
+ else
+ y.vu[pos--] = 0;
+ exp -= 16;
+ }
- // Clear the remaining bits.
- if (exp > 0)
- y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
+ // Clear the remaining bits.
+ if (exp > 0)
+ y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
- if ((x < 0.0) && (x != y.rv))
- y.rv -= 1.0;
- }
+ if ((x < 0.0) && (x != y.rv))
+ y.rv -= 1.0;
+ }
- return y.rv;
+ return y.rv;
+ }
}
public:
@@ -1767,6 +1777,13 @@ real exp(real x) @trusted pure nothrow @nogc
else
{
alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ibmExtended)
+ {
+ import gcc.builtins;
+ return __builtin_expl(x);
+ }
+ else
+ {
static if (F.realFormat == RealFormat.ieeeDouble)
{
// Coefficients for exp(x)
@@ -1872,6 +1889,7 @@ real exp(real x) @trusted pure nothrow @nogc
return x;
}
+ }
}
/// ditto
@@ -3897,7 +3915,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max);
// Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal)
- static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4);
+ static assert((real.min_normal*real.max > 2 && real.min_normal*real.max <= 4)
+ || floatTraits!real.realFormat == RealFormat.ibmExtended);
real u = fabs(x);
real v = fabs(y);
@@ -4524,7 +4543,7 @@ long lrint(real x) @trusted pure nothrow @nogc
}
else
{
- static assert(false, "real type not supported by lrint()");
+ assert(false, "real type not supported by lrint()");
}
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp.
@ 2021-01-11 21:27 Iain D Sandoe
0 siblings, 0 replies; 7+ messages in thread
From: Iain D Sandoe @ 2021-01-11 21:27 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:4f20e1cd17cb5a521fc7e0f89a52a5a7c1c4a457
commit 4f20e1cd17cb5a521fc7e0f89a52a5a7c1c4a457
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri Dec 11 00:59:19 2020 +0000
D, Math, IBM128 : Use GCC builtins for floor and exp.
This makes use of GCC's long double format builtins, which
in turn will call out to a libc implementation where needed.
Diff:
---
libphobos/src/std/math.d | 183 ++++++++++++++++++++++++++---------------------
1 file changed, 101 insertions(+), 82 deletions(-)
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 3d18cfa528b..ca2905c3a93 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -465,108 +465,118 @@ else
T floorImpl(T)(const T x) @trusted pure nothrow @nogc
{
alias F = floatTraits!(T);
- // Take care not to trigger library calls from the compiler,
- // while ensuring that we don't get defeated by some optimizers.
- union floatBits
- {
- T rv;
- ushort[T.sizeof/2] vu;
- // Other kinds of extractors for real formats.
- static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
- }
- floatBits y = void;
- y.rv = x;
-
- // Find the exponent (power of 2)
- // Do this by shifting the raw value so that the exponent lies in the low bits,
- // then mask out the sign bit, and subtract the bias.
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ibmExtended)
{
- int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ import gcc.builtins;
+ return __builtin_floorl(x);
}
- else static if (F.realFormat == RealFormat.ieeeDouble)
+ else
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+ // Take care not to trigger library calls from the compiler,
+ // while ensuring that we don't get defeated by some optimizers.
+ union floatBits
+ {
+ T rv;
+ ushort[T.sizeof/2] vu;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
- }
- else static if (F.realFormat == RealFormat.ieeeExtended ||
- F.realFormat == RealFormat.ieeeExtended53)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Other kinds of extractors for real formats.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ int vi;
+ }
+ floatBits y = void;
+ y.rv = x;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 4;
- }
- else static if (F.realFormat == RealFormat.ieeeQuadruple)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Find the exponent (power of 2)
+ // Do this by shifting the raw value so that the exponent lies in the
+ // low bits, then mask out the sign bit, and subtract the bias.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 7;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 3;
}
- else
- static assert(false, "Not implemented for this architecture");
+ else static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
- if (exp < 0)
- {
- if (x < 0.0)
- return -1.0;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 7;
+ }
else
- return 0.0;
- }
+ static assert(false, "Not implemented for this architecture");
- static if (F.realFormat == RealFormat.ieeeSingle)
- {
- if (exp < (T.mant_dig - 1))
+ if (exp < 0)
{
- // Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ if (x < 0.0)
+ return -1.0;
+ else
+ return 0.0;
+ }
- if ((y.vi & fraction_mask) != 0)
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ if (exp < (T.mant_dig - 1))
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
- y.vi &= ~fraction_mask;
+ // Clear all bits representing the fraction part.
+ const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+
+ if ((y.vi & fraction_mask) != 0)
+ {
+ // If 'x' is negative, then first substract 1.0 from
+ // the value.
+ if (y.vi < 0)
+ y.vi += 0x00800000 >> exp;
+ y.vi &= ~fraction_mask;
+ }
}
}
- }
- else
- {
- static if (F.realFormat == RealFormat.ieeeExtended53)
- exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- exp = (T.mant_dig - 1) - exp;
-
- // Zero 16 bits at a time.
- while (exp >= 16)
{
- version (LittleEndian)
- y.vu[pos++] = 0;
+ static if (F.realFormat == RealFormat.ieeeExtended53)
+ exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- y.vu[pos--] = 0;
- exp -= 16;
- }
+ exp = (T.mant_dig - 1) - exp;
+
+ // Zero 16 bits at a time.
+ while (exp >= 16)
+ {
+ version (LittleEndian)
+ y.vu[pos++] = 0;
+ else
+ y.vu[pos--] = 0;
+ exp -= 16;
+ }
- // Clear the remaining bits.
- if (exp > 0)
- y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
+ // Clear the remaining bits.
+ if (exp > 0)
+ y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
- if ((x < 0.0) && (x != y.rv))
- y.rv -= 1.0;
- }
+ if ((x < 0.0) && (x != y.rv))
+ y.rv -= 1.0;
+ }
- return y.rv;
+ return y.rv;
+ }
}
public:
@@ -1772,6 +1782,13 @@ real exp(real x) @trusted pure nothrow @nogc
else
{
alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ibmExtended)
+ {
+ import gcc.builtins;
+ return __builtin_expl(x);
+ }
+ else
+ {
static if (F.realFormat == RealFormat.ieeeDouble)
{
// Coefficients for exp(x)
@@ -1877,6 +1894,7 @@ real exp(real x) @trusted pure nothrow @nogc
return x;
}
+ }
}
/// ditto
@@ -3902,7 +3920,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max);
// Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal)
- static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4);
+ static assert((real.min_normal*real.max > 2 && real.min_normal*real.max <= 4)
+ || floatTraits!real.realFormat == RealFormat.ibmExtended);
real u = fabs(x);
real v = fabs(y);
@@ -4529,7 +4548,7 @@ long lrint(real x) @trusted pure nothrow @nogc
}
else
{
- static assert(false, "real type not supported by lrint()");
+ assert(false, "real type not supported by lrint()");
}
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp.
@ 2020-12-21 20:38 Iain D Sandoe
0 siblings, 0 replies; 7+ messages in thread
From: Iain D Sandoe @ 2020-12-21 20:38 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:32ac6e9b4e0b583b47abb9233d45581a2cc34751
commit 32ac6e9b4e0b583b47abb9233d45581a2cc34751
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri Dec 11 00:59:19 2020 +0000
D, Math, IBM128 : Use GCC builtins for floor and exp.
This makes use of GCC's long double format builtins, which
in turn will call out to a libc implementation where needed.
Diff:
---
libphobos/src/std/math.d | 183 ++++++++++++++++++++++++++---------------------
1 file changed, 101 insertions(+), 82 deletions(-)
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 3d18cfa528b..ca2905c3a93 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -465,108 +465,118 @@ else
T floorImpl(T)(const T x) @trusted pure nothrow @nogc
{
alias F = floatTraits!(T);
- // Take care not to trigger library calls from the compiler,
- // while ensuring that we don't get defeated by some optimizers.
- union floatBits
- {
- T rv;
- ushort[T.sizeof/2] vu;
- // Other kinds of extractors for real formats.
- static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
- }
- floatBits y = void;
- y.rv = x;
-
- // Find the exponent (power of 2)
- // Do this by shifting the raw value so that the exponent lies in the low bits,
- // then mask out the sign bit, and subtract the bias.
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ibmExtended)
{
- int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ import gcc.builtins;
+ return __builtin_floorl(x);
}
- else static if (F.realFormat == RealFormat.ieeeDouble)
+ else
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+ // Take care not to trigger library calls from the compiler,
+ // while ensuring that we don't get defeated by some optimizers.
+ union floatBits
+ {
+ T rv;
+ ushort[T.sizeof/2] vu;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
- }
- else static if (F.realFormat == RealFormat.ieeeExtended ||
- F.realFormat == RealFormat.ieeeExtended53)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Other kinds of extractors for real formats.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ int vi;
+ }
+ floatBits y = void;
+ y.rv = x;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 4;
- }
- else static if (F.realFormat == RealFormat.ieeeQuadruple)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Find the exponent (power of 2)
+ // Do this by shifting the raw value so that the exponent lies in the
+ // low bits, then mask out the sign bit, and subtract the bias.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 7;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 3;
}
- else
- static assert(false, "Not implemented for this architecture");
+ else static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
- if (exp < 0)
- {
- if (x < 0.0)
- return -1.0;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 7;
+ }
else
- return 0.0;
- }
+ static assert(false, "Not implemented for this architecture");
- static if (F.realFormat == RealFormat.ieeeSingle)
- {
- if (exp < (T.mant_dig - 1))
+ if (exp < 0)
{
- // Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ if (x < 0.0)
+ return -1.0;
+ else
+ return 0.0;
+ }
- if ((y.vi & fraction_mask) != 0)
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ if (exp < (T.mant_dig - 1))
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
- y.vi &= ~fraction_mask;
+ // Clear all bits representing the fraction part.
+ const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+
+ if ((y.vi & fraction_mask) != 0)
+ {
+ // If 'x' is negative, then first substract 1.0 from
+ // the value.
+ if (y.vi < 0)
+ y.vi += 0x00800000 >> exp;
+ y.vi &= ~fraction_mask;
+ }
}
}
- }
- else
- {
- static if (F.realFormat == RealFormat.ieeeExtended53)
- exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- exp = (T.mant_dig - 1) - exp;
-
- // Zero 16 bits at a time.
- while (exp >= 16)
{
- version (LittleEndian)
- y.vu[pos++] = 0;
+ static if (F.realFormat == RealFormat.ieeeExtended53)
+ exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- y.vu[pos--] = 0;
- exp -= 16;
- }
+ exp = (T.mant_dig - 1) - exp;
+
+ // Zero 16 bits at a time.
+ while (exp >= 16)
+ {
+ version (LittleEndian)
+ y.vu[pos++] = 0;
+ else
+ y.vu[pos--] = 0;
+ exp -= 16;
+ }
- // Clear the remaining bits.
- if (exp > 0)
- y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
+ // Clear the remaining bits.
+ if (exp > 0)
+ y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
- if ((x < 0.0) && (x != y.rv))
- y.rv -= 1.0;
- }
+ if ((x < 0.0) && (x != y.rv))
+ y.rv -= 1.0;
+ }
- return y.rv;
+ return y.rv;
+ }
}
public:
@@ -1772,6 +1782,13 @@ real exp(real x) @trusted pure nothrow @nogc
else
{
alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ibmExtended)
+ {
+ import gcc.builtins;
+ return __builtin_expl(x);
+ }
+ else
+ {
static if (F.realFormat == RealFormat.ieeeDouble)
{
// Coefficients for exp(x)
@@ -1877,6 +1894,7 @@ real exp(real x) @trusted pure nothrow @nogc
return x;
}
+ }
}
/// ditto
@@ -3902,7 +3920,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max);
// Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal)
- static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4);
+ static assert((real.min_normal*real.max > 2 && real.min_normal*real.max <= 4)
+ || floatTraits!real.realFormat == RealFormat.ibmExtended);
real u = fabs(x);
real v = fabs(y);
@@ -4529,7 +4548,7 @@ long lrint(real x) @trusted pure nothrow @nogc
}
else
{
- static assert(false, "real type not supported by lrint()");
+ assert(false, "real type not supported by lrint()");
}
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
* [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp.
@ 2020-12-13 17:44 Iain D Sandoe
0 siblings, 0 replies; 7+ messages in thread
From: Iain D Sandoe @ 2020-12-13 17:44 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:697d471c4893019e0e1619785ec694ef0862c52e
commit 697d471c4893019e0e1619785ec694ef0862c52e
Author: Iain Sandoe <iain@sandoe.co.uk>
Date: Fri Dec 11 00:59:19 2020 +0000
D, Math, IBM128 : Use GCC builtins for floor and exp.
This makes use of GCC's long double format builtins, which
in turn will call out to a libc implementation where needed.
Diff:
---
libphobos/src/std/math.d | 183 ++++++++++++++++++++++++++---------------------
1 file changed, 101 insertions(+), 82 deletions(-)
diff --git a/libphobos/src/std/math.d b/libphobos/src/std/math.d
index 3d18cfa528b..ca2905c3a93 100644
--- a/libphobos/src/std/math.d
+++ b/libphobos/src/std/math.d
@@ -465,108 +465,118 @@ else
T floorImpl(T)(const T x) @trusted pure nothrow @nogc
{
alias F = floatTraits!(T);
- // Take care not to trigger library calls from the compiler,
- // while ensuring that we don't get defeated by some optimizers.
- union floatBits
- {
- T rv;
- ushort[T.sizeof/2] vu;
- // Other kinds of extractors for real formats.
- static if (F.realFormat == RealFormat.ieeeSingle)
- int vi;
- }
- floatBits y = void;
- y.rv = x;
-
- // Find the exponent (power of 2)
- // Do this by shifting the raw value so that the exponent lies in the low bits,
- // then mask out the sign bit, and subtract the bias.
- static if (F.realFormat == RealFormat.ieeeSingle)
+ static if (F.realFormat == RealFormat.ibmExtended)
{
- int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ import gcc.builtins;
+ return __builtin_floorl(x);
}
- else static if (F.realFormat == RealFormat.ieeeDouble)
+ else
{
- int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
+ // Take care not to trigger library calls from the compiler,
+ // while ensuring that we don't get defeated by some optimizers.
+ union floatBits
+ {
+ T rv;
+ ushort[T.sizeof/2] vu;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 3;
- }
- else static if (F.realFormat == RealFormat.ieeeExtended ||
- F.realFormat == RealFormat.ieeeExtended53)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Other kinds of extractors for real formats.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ int vi;
+ }
+ floatBits y = void;
+ y.rv = x;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 4;
- }
- else static if (F.realFormat == RealFormat.ieeeQuadruple)
- {
- int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+ // Find the exponent (power of 2)
+ // Do this by shifting the raw value so that the exponent lies in the
+ // low bits, then mask out the sign bit, and subtract the bias.
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ int exp = ((y.vi >> (T.mant_dig - 1)) & 0xff) - 0x7f;
+ }
+ else static if (F.realFormat == RealFormat.ieeeDouble)
+ {
+ int exp = ((y.vu[F.EXPPOS_SHORT] >> 4) & 0x7ff) - 0x3ff;
- version (LittleEndian)
- int pos = 0;
- else
- int pos = 7;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 3;
}
- else
- static assert(false, "Not implemented for this architecture");
+ else static if (F.realFormat == RealFormat.ieeeExtended ||
+ F.realFormat == RealFormat.ieeeExtended53)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
- if (exp < 0)
- {
- if (x < 0.0)
- return -1.0;
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 4;
+ }
+ else static if (F.realFormat == RealFormat.ieeeQuadruple)
+ {
+ int exp = (y.vu[F.EXPPOS_SHORT] & 0x7fff) - 0x3fff;
+
+ version (LittleEndian)
+ int pos = 0;
+ else
+ int pos = 7;
+ }
else
- return 0.0;
- }
+ static assert(false, "Not implemented for this architecture");
- static if (F.realFormat == RealFormat.ieeeSingle)
- {
- if (exp < (T.mant_dig - 1))
+ if (exp < 0)
{
- // Clear all bits representing the fraction part.
- const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+ if (x < 0.0)
+ return -1.0;
+ else
+ return 0.0;
+ }
- if ((y.vi & fraction_mask) != 0)
+ static if (F.realFormat == RealFormat.ieeeSingle)
+ {
+ if (exp < (T.mant_dig - 1))
{
- // If 'x' is negative, then first substract 1.0 from the value.
- if (y.vi < 0)
- y.vi += 0x00800000 >> exp;
- y.vi &= ~fraction_mask;
+ // Clear all bits representing the fraction part.
+ const uint fraction_mask = F.MANTISSAMASK_INT >> exp;
+
+ if ((y.vi & fraction_mask) != 0)
+ {
+ // If 'x' is negative, then first substract 1.0 from
+ // the value.
+ if (y.vi < 0)
+ y.vi += 0x00800000 >> exp;
+ y.vi &= ~fraction_mask;
+ }
}
}
- }
- else
- {
- static if (F.realFormat == RealFormat.ieeeExtended53)
- exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- exp = (T.mant_dig - 1) - exp;
-
- // Zero 16 bits at a time.
- while (exp >= 16)
{
- version (LittleEndian)
- y.vu[pos++] = 0;
+ static if (F.realFormat == RealFormat.ieeeExtended53)
+ exp = (T.mant_dig + 11 - 1) - exp; // mant_dig is really 64
else
- y.vu[pos--] = 0;
- exp -= 16;
- }
+ exp = (T.mant_dig - 1) - exp;
+
+ // Zero 16 bits at a time.
+ while (exp >= 16)
+ {
+ version (LittleEndian)
+ y.vu[pos++] = 0;
+ else
+ y.vu[pos--] = 0;
+ exp -= 16;
+ }
- // Clear the remaining bits.
- if (exp > 0)
- y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
+ // Clear the remaining bits.
+ if (exp > 0)
+ y.vu[pos] &= 0xffff ^ ((1 << exp) - 1);
- if ((x < 0.0) && (x != y.rv))
- y.rv -= 1.0;
- }
+ if ((x < 0.0) && (x != y.rv))
+ y.rv -= 1.0;
+ }
- return y.rv;
+ return y.rv;
+ }
}
public:
@@ -1772,6 +1782,13 @@ real exp(real x) @trusted pure nothrow @nogc
else
{
alias F = floatTraits!real;
+ static if (F.realFormat == RealFormat.ibmExtended)
+ {
+ import gcc.builtins;
+ return __builtin_expl(x);
+ }
+ else
+ {
static if (F.realFormat == RealFormat.ieeeDouble)
{
// Coefficients for exp(x)
@@ -1877,6 +1894,7 @@ real exp(real x) @trusted pure nothrow @nogc
return x;
}
+ }
}
/// ditto
@@ -3902,7 +3920,8 @@ real hypot(real x, real y) @safe pure nothrow @nogc
static assert(2*(SQRTMAX/2)*(SQRTMAX/2) <= real.max);
// Proves that sqrt(real.max) ~~ 0.5/sqrt(real.min_normal)
- static assert(real.min_normal*real.max > 2 && real.min_normal*real.max <= 4);
+ static assert((real.min_normal*real.max > 2 && real.min_normal*real.max <= 4)
+ || floatTraits!real.realFormat == RealFormat.ibmExtended);
real u = fabs(x);
real v = fabs(y);
@@ -4529,7 +4548,7 @@ long lrint(real x) @trusted pure nothrow @nogc
}
else
{
- static assert(false, "real type not supported by lrint()");
+ assert(false, "real type not supported by lrint()");
}
}
}
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-10-18 15:54 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-13 8:31 [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp Iain D Sandoe
-- strict thread matches above, loose matches on Subject: below --
2021-10-18 15:54 Iain D Sandoe
2021-10-15 19:34 Iain D Sandoe
2021-10-11 20:35 Iain D Sandoe
2021-01-11 21:27 Iain D Sandoe
2020-12-21 20:38 Iain D Sandoe
2020-12-13 17:44 Iain D Sandoe
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).