public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-04-10 17:02 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-04-10 17:02 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:21e01521b1ad706604f31e5c8210b883cd1b7461

commit 21e01521b1ad706604f31e5c8210b883cd1b7461
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] 8+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-09-17 14:35 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-09-17 14:35 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:fb06e91ebcc6e61f67518f481499f9e25eeb9b76

commit fb06e91ebcc6e61f67518f481499f9e25eeb9b76
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] 8+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-04-19 18:06 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-04-19 18:06 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:848073267d5aaf027a9843a76f24c115b9524d91

commit 848073267d5aaf027a9843a76f24c115b9524d91
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] 8+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-04-10 15:05 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-04-10 15:05 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:6a516c1da2d719f2c81451028fceaabfd2cfce46

commit 6a516c1da2d719f2c81451028fceaabfd2cfce46
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] 8+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-03-14 22:02 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-03-14 22:02 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9f1634e116a24f9646e8bc94c830ed9babb5f97b

commit 9f1634e116a24f9646e8bc94c830ed9babb5f97b
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 ff368b79f9d..ac4a93d313b 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] 8+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-03-07 17:03 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-03-07 17:03 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:0d0d4867ab314d41d5942f2bdae8b5032c95f966

commit 0d0d4867ab314d41d5942f2bdae8b5032c95f966
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 ff368b79f9d..ac4a93d313b 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] 8+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-01-30 19:10 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-01-30 19:10 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:baef82c664e10dae8958991d75a5d3bf46458df7

commit baef82c664e10dae8958991d75a5d3bf46458df7
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] 8+ messages in thread

* [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins  for floor and exp.
@ 2021-01-28 17:33 Iain Buclaw
  0 siblings, 0 replies; 8+ messages in thread
From: Iain Buclaw @ 2021-01-28 17:33 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:a52cfea0d525fa7f7889745a7dd3afe92f4ec958

commit a52cfea0d525fa7f7889745a7dd3afe92f4ec958
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] 8+ messages in thread

end of thread, other threads:[~2021-09-17 14:35 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-04-10 17:02 [gcc(refs/users/ibuclaw/heads/darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp Iain Buclaw
  -- strict thread matches above, loose matches on Subject: below --
2021-09-17 14:35 Iain Buclaw
2021-04-19 18:06 Iain Buclaw
2021-04-10 15:05 Iain Buclaw
2021-03-14 22:02 Iain Buclaw
2021-03-07 17:03 Iain Buclaw
2021-01-30 19:10 Iain Buclaw
2021-01-28 17:33 Iain Buclaw

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).