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-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-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-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-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-15 19:34 [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-13  8:31 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).