From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1698) id 248233858433; Mon, 18 Oct 2021 15:54:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 248233858433 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Iain D Sandoe To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/users/iains/heads/d-for-darwin)] D, Math, IBM128 : Use GCC builtins for floor and exp. X-Act-Checkin: gcc X-Git-Author: Iain Sandoe X-Git-Refname: refs/users/iains/heads/d-for-darwin X-Git-Oldrev: 430d4329d9cd680a47c26e9b21c2183a06cf8e67 X-Git-Newrev: b860e07d422b2a5f2f29a8e4848d87fe6cabdc0e Message-Id: <20211018155458.248233858433@sourceware.org> Date: Mon, 18 Oct 2021 15:54:58 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 18 Oct 2021 15:54:58 -0000 https://gcc.gnu.org/g:b860e07d422b2a5f2f29a8e4848d87fe6cabdc0e commit b860e07d422b2a5f2f29a8e4848d87fe6cabdc0e Author: Iain Sandoe 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()"); } } }