From patchwork Fri Nov 27 20:28:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Iain Buclaw X-Patchwork-Id: 1407412 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=ng2URO2f; dkim-atps=neutral Received: from sourceware.org (unknown [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4CjR6q5JhFz9s1l for ; Sat, 28 Nov 2020 07:29:07 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9B5F43982412; Fri, 27 Nov 2020 20:29:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9B5F43982412 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1606508944; bh=bqaOnv0SSQiN7PtaBIiw4jGKGNHT/cM1EWS9PPhVrbk=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=ng2URO2f1Tu5X/6MOeYZP2MUdftrhsX9AMkcp/XvgU/wai3Bm6dYEBlXkMz7KpQG6 blYCGqFGeWssgZMn9zIXp734+vOa1umsc1POI/vGY00NPCYUOAi+Gi41xRU23vrP9B dSMbxWb1bPkD/fyR8+V7MBc+H2v2e5qoL/jXao+8= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mout-p-101.mailbox.org (mout-p-101.mailbox.org [80.241.56.151]) by sourceware.org (Postfix) with ESMTPS id E7BD2385802B for ; Fri, 27 Nov 2020 20:28:59 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org E7BD2385802B Received: from smtp1.mailbox.org (smtp1.mailbox.org [80.241.60.240]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-101.mailbox.org (Postfix) with ESMTPS id 4CjR6f5RgYzQlF0; Fri, 27 Nov 2020 21:28:58 +0100 (CET) X-Virus-Scanned: amavisd-new at heinlein-support.de Received: from smtp1.mailbox.org ([80.241.60.240]) by spamfilter04.heinlein-hosting.de (spamfilter04.heinlein-hosting.de [80.241.56.122]) (amavisd-new, port 10030) with ESMTP id JxO8MGRGZCgz; Fri, 27 Nov 2020 21:28:55 +0100 (CET) To: gcc-patches@gcc.gnu.org Subject: [committed] d: Add float and double overloads for all core.math intrinsics Date: Fri, 27 Nov 2020 21:28:52 +0100 Message-Id: <20201127202852.46858-1-ibuclaw@gdcproject.org> MIME-Version: 1.0 X-MBO-SPAM-Probability: X-Rspamd-Score: -4.37 / 15.00 / 15.00 X-Rspamd-Queue-Id: B9E5E1843 X-Rspamd-UID: d27bb4 X-Spam-Status: No, score=-6.1 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP, UNWANTED_LANGUAGE_BODY autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Buclaw via Gcc-patches From: Iain Buclaw Reply-To: Iain Buclaw Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Hi, For the math intrinsics: cos, fabs, ldexp, rint, rndtol, and sin, new overloads have been added to the core.math module for matching float and double types. These have been implemented in the compiler. A recent change to dump_function_to_file started triggering some scan-tree-dump tests to FAIL, these have been adjusted as well when updating the test. Bootstrapped and regression tested on x86_64-linux-gnu with -mx32/-m32, committed to mainline. Regards Iain. --- gcc/d/ChangeLog: * intrinsics.cc (maybe_expand_intrinsic): Handle new intrinsics. * intrinsics.def (INTRINSIC_COS): Add float and double overloads. (INTRINSIC_FABS): Likewise. (INTRINSIC_LDEXP): Likewise. (INTRINSIC_RINT): Likewise. (INTRINSIC_RNDTOL): Likewise. (INTRINSIC_SIN): Likewise. (INTRINSIC_TOPREC): Adjust signature. libphobos/ChangeLog: * libdruntime/MERGE: Merge upstream druntime 5e4492c4. gcc/testsuite/ChangeLog: * gdc.dg/intrinsics.d: Adjust patterns in scan-tree-dump. --- gcc/d/intrinsics.cc | 12 ++++ gcc/d/intrinsics.def | 20 ++++-- gcc/testsuite/gdc.dg/intrinsics.d | 92 +++++++++++++++--------- libphobos/libdruntime/MERGE | 2 +- libphobos/libdruntime/core/math.d | 113 +++++++++++++++++------------- 5 files changed, 151 insertions(+), 88 deletions(-) diff --git a/gcc/d/intrinsics.cc b/gcc/d/intrinsics.cc index a7de91019a4..4196ed3c552 100644 --- a/gcc/d/intrinsics.cc +++ b/gcc/d/intrinsics.cc @@ -814,10 +814,14 @@ maybe_expand_intrinsic (tree callexp) case INTRINSIC_CEIL: case INTRINSIC_CEILF: case INTRINSIC_CEILL: + case INTRINSIC_COS: + case INTRINSIC_COSF: case INTRINSIC_COSL: case INTRINSIC_EXP: case INTRINSIC_EXP2: case INTRINSIC_EXPM1: + case INTRINSIC_FABS: + case INTRINSIC_FABSF: case INTRINSIC_FABSL: case INTRINSIC_FLOOR: case INTRINSIC_FLOORF: @@ -828,9 +832,15 @@ maybe_expand_intrinsic (tree callexp) case INTRINSIC_LOG: case INTRINSIC_LOG10: case INTRINSIC_LOG2: + case INTRINSIC_RINT: + case INTRINSIC_RINTF: case INTRINSIC_RINTL: + case INTRINSIC_RNDTOL: + case INTRINSIC_RNDTOLF: case INTRINSIC_RNDTOLL: case INTRINSIC_ROUND: + case INTRINSIC_SIN: + case INTRINSIC_SINF: case INTRINSIC_SINL: case INTRINSIC_SQRT: case INTRINSIC_SQRTF: @@ -844,6 +854,8 @@ maybe_expand_intrinsic (tree callexp) case INTRINSIC_FMAX: case INTRINSIC_FMIN: + case INTRINSIC_LDEXP: + case INTRINSIC_LDEXPF: case INTRINSIC_LDEXPL: code = intrinsic_decls[intrinsic].built_in; gcc_assert (code != BUILT_IN_NONE); diff --git a/gcc/d/intrinsics.def b/gcc/d/intrinsics.def index 5b8cb712264..c05a6662865 100644 --- a/gcc/d/intrinsics.def +++ b/gcc/d/intrinsics.def @@ -93,22 +93,34 @@ DEF_D_BUILTIN (NEGSL, NONE, "negs", "core.checkedint", "FNaNbNiNflKbZl") /* core.math intrinsics. */ +DEF_D_BUILTIN (COSF, COSF, "cos", "core.math", "FNaNbNiNffZf") +DEF_D_BUILTIN (COS, COS, "cos", "core.math", "FNaNbNiNfdZd") DEF_D_BUILTIN (COSL, COSL, "cos", "core.math", "FNaNbNiNfeZe") +DEF_D_BUILTIN (FABSF, FABSL, "fabs", "core.math", "FNaNbNiNffZf") +DEF_D_BUILTIN (FABS, FABS, "fabs", "core.math", "FNaNbNiNfdZd") DEF_D_BUILTIN (FABSL, FABSL, "fabs", "core.math", "FNaNbNiNfeZe") +DEF_D_BUILTIN (LDEXPF, LDEXPF, "ldexp", "core.math", "FNaNbNiNffiZf") +DEF_D_BUILTIN (LDEXP, LDEXP, "ldexp", "core.math", "FNaNbNiNfdiZd") DEF_D_BUILTIN (LDEXPL, LDEXPL, "ldexp", "core.math", "FNaNbNiNfeiZe") +DEF_D_BUILTIN (RINTF, RINTF, "rint", "core.math", "FNaNbNiNffZf") +DEF_D_BUILTIN (RINT, RINT, "rint", "core.math", "FNaNbNiNfdZd") DEF_D_BUILTIN (RINTL, RINTL, "rint", "core.math", "FNaNbNiNfeZe") -/* Not sure if `llroundl' stands as a good replacement for the expected +/* Not sure if `llround{f,l}' stands as a good replacement for the expected behavior of `rndtol()'. */ +DEF_D_BUILTIN (RNDTOLF, LLROUNDF, "rndtol", "core.math", "FNaNbNiNffZl") +DEF_D_BUILTIN (RNDTOL, LLROUND, "rndtol", "core.math", "FNaNbNiNfdZl") DEF_D_BUILTIN (RNDTOLL, LLROUNDL, "rndtol", "core.math", "FNaNbNiNfeZl") +DEF_D_BUILTIN (SINF, SINF, "sin", "core.math", "FNaNbNiNffZf") +DEF_D_BUILTIN (SIN, SIN, "sin", "core.math", "FNaNbNiNfdZd") DEF_D_BUILTIN (SINL, SINL, "sin", "core.math", "FNaNbNiNfeZe") DEF_D_BUILTIN (SQRTF, SQRTF, "sqrt", "core.math", "FNaNbNiNffZf") DEF_D_BUILTIN (SQRT, SQRT, "sqrt", "core.math", "FNaNbNiNfdZd") DEF_D_BUILTIN (SQRTL, SQRTL, "sqrt", "core.math", "FNaNbNiNfeZe") -DEF_D_BUILTIN (TOPRECF, NONE, "toPrec", "core.math", "FNaNbNffZI1T") -DEF_D_BUILTIN (TOPREC, NONE, "toPrec", "core.math", "FNaNbNfdZI1T") -DEF_D_BUILTIN (TOPRECL, NONE, "toPrec", "core.math", "FNaNbNfeZI1T") +DEF_D_BUILTIN (TOPRECF, NONE, "toPrec", "core.math", "FfZI1T") +DEF_D_BUILTIN (TOPREC, NONE, "toPrec", "core.math", "FdZI1T") +DEF_D_BUILTIN (TOPRECL, NONE, "toPrec", "core.math", "FeZI1T") /* std.math intrinsics. */ diff --git a/gcc/testsuite/gdc.dg/intrinsics.d b/gcc/testsuite/gdc.dg/intrinsics.d index 5888361a438..a7752370582 100644 --- a/gcc/testsuite/gdc.dg/intrinsics.d +++ b/gcc/testsuite/gdc.dg/intrinsics.d @@ -8,65 +8,77 @@ import core.stdc.stdarg; ////////////////////////////////////////////////////// // core.bitop -// { dg-final { scan-tree-dump-not " bsf " "original" } } +// { dg-final { scan-tree-dump " __builtin_ctz " "original" } } int test_bsf(uint a) { return bsf(a); } +// { dg-final { scan-tree-dump " __builtin_ctz(l|ll) " "original" } } int test_bsf(ulong a) { return bsf(a); } -// { dg-final { scan-tree-dump-not " bsr " "original" } } +// { dg-final { scan-tree-dump " __builtin_clz " "original" } } int test_bsr(uint a) { return bsr(a); } +// { dg-final { scan-tree-dump " __builtin_clz(l|ll) " "original" } } int test_bsr(ulong a) { return bsr(a); } -// { dg-final { scan-tree-dump-not " bt " "original" } } +// { dg-final { scan-tree-dump-not " = bt " "original" } } int test_bt(size_t *a, size_t b) { return bt(a, b); } -// { dg-final { scan-tree-dump-not " btc " "original" } } +// { dg-final { scan-tree-dump-not " = btc " "original" } } int test_btc(size_t *a, size_t b) { return btc(a, b); } -// { dg-final { scan-tree-dump-not " btr " "original" } } +// { dg-final { scan-tree-dump-not " = btr " "original" } } int test_btr(size_t *a, size_t b) { return btr(a, b); } -// { dg-final { scan-tree-dump-not " bts " "original" } } +// { dg-final { scan-tree-dump-not " = bts " "original" } } int test_bts(size_t *a, size_t b) { return bts(a, b); } -// { dg-final { scan-tree-dump-not " bswap " "original" } } +// { dg-final { scan-tree-dump " __builtin_bswap32 " "original" } } uint test_bswap(uint a) { return bswap(a); } +// { dg-final { scan-tree-dump " __builtin_bswap64 " "original" } } ulong test_bswap(ulong a) { return bswap(a); } -// { dg-final { scan-tree-dump-not " popcnt " "original" } } +// { dg-final { scan-tree-dump " __builtin_popcount " "original" } } int test_popcnt(uint a) { return popcnt(a); } +// { dg-final { scan-tree-dump " __builtin_popcount(l|ll) " "original" } } int test_popcnt(ulong a) { return popcnt(a); } -// { dg-final { scan-tree-dump-not " volatileLoad " "original" } } +// { dg-final { scan-tree-dump "\\(volatile ubyte \\*\\) a;" "original" } } ubyte test_volatileLoad(ubyte *a) { return volatileLoad(a); } +// { dg-final { scan-tree-dump "\\(volatile ushort \\*\\) a;" "original" } } ushort test_volatileLoad(ushort *a) { return volatileLoad(a); } +// { dg-final { scan-tree-dump "\\(volatile uint \\*\\) a;" "original" } } uint test_volatileLoad(uint *a) { return volatileLoad(a); } +// { dg-final { scan-tree-dump "\\(volatile ulong \\*\\) a;" "original" } } ulong test_volatileLoad(ulong *a) { return volatileLoad(a); } -// { dg-final { scan-tree-dump-not " volatileStore " "original" } } +// { dg-final { scan-tree-dump "\\(volatile ubyte \\*\\) a = b" "original" } } void test_volatileStore(ubyte *a, ubyte b) { return volatileStore(a, b); } +// { dg-final { scan-tree-dump "\\(volatile ushort \\*\\) a = b" "original" } } void test_volatileStore(ushort *a, ushort b) { return volatileStore(a, b); } +// { dg-final { scan-tree-dump "\\(volatile uint \\*\\) a = b" "original" } } void test_volatileStore(uint *a, uint b) { return volatileStore(a, b); } +// { dg-final { scan-tree-dump "\\(volatile ulong \\*\\) a = b" "original" } } void test_volatileStore(ulong *a, ulong b) { return volatileStore(a, b); } -// { dg-final { scan-tree-dump-not " rol " "original" } } +// { dg-final { scan-tree-dump " a r<< b;" "original" } } ubyte test_rol(ubyte a, uint b) { return rol!ubyte(a, b); } +// { dg-final { scan-tree-dump " a r>> 31;" "original" } } uint test_rol(uint a) { return rol!(1, uint)(a); } -// { dg-final { scan-tree-dump-not " ror " "original" } } +// { dg-final { scan-tree-dump " a r>> b;" "original" } } ushort test_ror(ushort a, uint b) { return ror!ushort(a, b); } +// { dg-final { scan-tree-dump " a r>> 1;" "original" } } ulong test_ror(ulong a) { return ror!(1, ulong)(a); } ////////////////////////////////////////////////////// // core.checkedint -// { dg-final { scan-tree-dump-not " adds " "original" } } +// { dg-final { scan-tree-dump-not " = adds " "original" } } int test_adds(int a, int b, ref bool c) { return adds(a, b, c); } long test_adds(long a, long b, ref bool c) { return adds(a, b, c); } -// { dg-final { scan-tree-dump-not " addu " "original" } } +// { dg-final { scan-tree-dump-not " = addu " "original" } } uint test_addu(uint a, uint b, ref bool c) { return addu(a, b, c); } ulong test_addu(ulong a, ulong b, ref bool c) { return addu(a, b, c); } -// { dg-final { scan-tree-dump-not " subs " "original" } } +// { dg-final { scan-tree-dump-not " = subs " "original" } } int test_subs(int a, int b, ref bool c) { return subs(a, b, c); } long test_subs(long a, long b, ref bool c) { return subs(a, b, c); } -// { dg-final { scan-tree-dump-not " subu " "original" } } +// { dg-final { scan-tree-dump-not " = subu " "original" } } uint test_subu(uint a, uint b, ref bool c) { return subu(a, b, c); } ulong test_subu(ulong a, ulong b, ref bool c) { return subu(a, b, c); } -// { dg-final { scan-tree-dump-not " negs " "original" } } +// { dg-final { scan-tree-dump-not " = negs " "original" } } int test_negs(int a, ref bool b) { return negs(a, b); } long test_negs(long a, ref bool b) { return negs(a, b); } -// { dg-final { scan-tree-dump-not " muls " "original" } } +// { dg-final { scan-tree-dump-not " = muls " "original" } } int test_muls(int a, int b, ref bool c) { return muls(a, b, c); } long test_muls(long a, long b, ref bool c) { return muls(a, b, c); } -// { dg-final { scan-tree-dump-not " mulu " "original" } } +// { dg-final { scan-tree-dump-not " = mulu " "original" } } uint test_mulu(uint a, uint b, ref bool c) { return mulu(a, b, c); } ulong test_mulu(ulong a, uint b, ref bool c) { return mulu(a, b, c); } ulong test_mulu(ulong a, ulong b, ref bool c) { return mulu(a, b, c); } @@ -74,50 +86,62 @@ ulong test_mulu(ulong a, ulong b, ref bool c) { return mulu(a, b, c); } ////////////////////////////////////////////////////// // core.math -// { dg-final { scan-tree-dump-not " cos " "original" } } +// { dg-final { scan-tree-dump " __builtin_cosf " "original" } } float test_cos(float a) { return cos(a); } +// { dg-final { scan-tree-dump " __builtin_cos " "original" } } double test_cos(double a) { return cos(a); } +// { dg-final { scan-tree-dump " __builtin_cosl " "original" } } real test_cos(real a) { return cos(a); } -// { dg-final { scan-tree-dump-not " sin " "original" } } +// { dg-final { scan-tree-dump " __builtin_sinf " "original" } } float test_sin(float a) { return sin(a); } +// { dg-final { scan-tree-dump " __builtin_sin " "original" } } double test_sin(double a) { return sin(a); } +// { dg-final { scan-tree-dump " __builtin_sinl " "original" } } real test_sin(real a) { return sin(a); } -// { dg-final { scan-tree-dump-not " rndtol " "original" } } +// { dg-final { scan-tree-dump " __builtin_llroundf " "original" } } long test_rndtol(float a) { return rndtol(a); } +// { dg-final { scan-tree-dump " __builtin_llround " "original" } } long test_rndtol(double a) { return rndtol(a); } +// { dg-final { scan-tree-dump " __builtin_llroundl " "original" } } long test_rndtol(real a) { return rndtol(a); } -// { dg-final { scan-tree-dump-not " sqrt " "original" } } +// { dg-final { scan-tree-dump " __builtin_sqrtf " "original" } } float test_sqrt(float a) { return sqrt(a); } +// { dg-final { scan-tree-dump " __builtin_sqrt " "original" } } double test_sqrt(double a) { return sqrt(a); } +// { dg-final { scan-tree-dump " __builtin_sqrtl " "original" } } real test_sqrt(real a) { return sqrt(a); } -// { dg-final { scan-tree-dump-not " ldexp " "original" } } +// { dg-final { scan-tree-dump " __builtin_ldexpf " "original" } } float test_ldexp(float a, int b) { return ldexp(a, b); } +// { dg-final { scan-tree-dump " __builtin_ldexp " "original" } } double test_ldexp(double a, int b) { return ldexp(a, b); } +// { dg-final { scan-tree-dump " __builtin_ldexpl " "original" } } real test_ldexp(real a, int b) { return ldexp(a, b); } -// { dg-final { scan-tree-dump-not " fabs " "original" } } +// { dg-final { scan-tree-dump-not " = fabs " "original" } } float test_fabs(float a) { return fabs(a); } double test_fabs(double a) { return fabs(a); } real test_fabs(real a) { return fabs(a); } -// { dg-final { scan-tree-dump-not " rint " "original" } } +// { dg-final { scan-tree-dump " __builtin_rintf " "original" } } float test_rint(float a) { return rint(a); } +// { dg-final { scan-tree-dump " __builtin_rint " "original" } } double test_rint(double a) { return rint(a); } +// { dg-final { scan-tree-dump " __builtin_rintl " "original" } } real test_rint(real a) { return rint(a); } -// { dg-final { scan-tree-dump-not " toPrec " "original" } } -float test_toPrec(float a) { return toPrec!float(a); } -float test_toPrec(double a) { return toPrec!float(a); } -float test_toPrec(real a) { return toPrec!float(a); } +// { dg-final { scan-tree-dump-not " = toPrec " "original" } } +float test_toPrecf(float a) { return toPrec!float(a); } +float test_toPrecf(double a) { return toPrec!float(a); } +float test_toPrecf(real a) { return toPrec!float(a); } double test_toPrec(float a) { return toPrec!double(a); } double test_toPrec(double a) { return toPrec!double(a); } double test_toPrec(real a) { return toPrec!double(a); } -real test_toPrec(float a) { return toPrec!real(a); } -real test_toPrec(double a) { return toPrec!real(a); } -real test_toPrec(real a) { return toPrec!real(a); } +real test_toPrecl(float a) { return toPrec!real(a); } +real test_toPrecl(double a) { return toPrec!real(a); } +real test_toPrecl(real a) { return toPrec!real(a); } ////////////////////////////////////////////////////// // core.stdc.stdarg // { dg-final { scan-tree-dump-not " va_arg " "original" } } -void test_va_arg(...) { int a; return va_arg!int(_argptr, a); } +void test_va_argc(...) { int a; return va_arg!int(_argptr, a); } int test_va_arg(...) { return va_arg!int(_argptr); } // { dg-final { scan-tree-dump-not " va_start " "original" } } void test_va_start(int a, ...) { return va_start(_argptr, a); } diff --git a/libphobos/libdruntime/MERGE b/libphobos/libdruntime/MERGE index 485f8e999d6..91154eebdc9 100644 --- a/libphobos/libdruntime/MERGE +++ b/libphobos/libdruntime/MERGE @@ -1,4 +1,4 @@ -58560d5163381b0f1c893bd0d035b7a0a1631f92 +5e4492c45172110b035591f5961b9f9f5adf6f13 The first line of this file holds the git revision number of the last merge done from the dlang/druntime repository. diff --git a/libphobos/libdruntime/core/math.d b/libphobos/libdruntime/core/math.d index 219b4263ff2..4d46b67d2a3 100644 --- a/libphobos/libdruntime/core/math.d +++ b/libphobos/libdruntime/core/math.d @@ -1,4 +1,4 @@ -// Written in the D programming language. +// Written in the D programming language. /** * Builtin mathematical intrinsics @@ -19,15 +19,26 @@ * GT = > * * Copyright: Copyright Digital Mars 2000 - 2011. - * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0). - * Authors: $(WEB digitalmars.com, Walter Bright), + * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). + * Authors: $(HTTP digitalmars.com, Walter Bright), * Don Clugston */ module core.math; public: @nogc: +nothrow: +@safe: +/***************************************** + * Returns x rounded to a long value using the FE_TONEAREST rounding mode. + * If the integer value of x is + * greater than long.max, the result is + * indeterminate. + */ +extern (C) real rndtonl(real x); + +pure: /*********************************** * Returns cosine of x. x is in radians. * @@ -40,7 +51,9 @@ public: * Results are undefined if |x| >= $(POWER 2,64). */ -real cos(real x) @safe pure nothrow; /* intrinsic */ +float cos(float x); /* intrinsic */ +double cos(double x); /* intrinsic */ /// ditto +real cos(real x); /* intrinsic */ /// ditto /*********************************** * Returns sine of x. x is in radians. @@ -55,7 +68,9 @@ real cos(real x) @safe pure nothrow; /* intrinsic */ * Results are undefined if |x| >= $(POWER 2,64). */ -real sin(real x) @safe pure nothrow; /* intrinsic */ +float sin(float x); /* intrinsic */ +double sin(double x); /* intrinsic */ /// ditto +real sin(real x); /* intrinsic */ /// ditto /***************************************** * Returns x rounded to a long value using the current rounding mode. @@ -63,16 +78,10 @@ real sin(real x) @safe pure nothrow; /* intrinsic */ * greater than long.max, the result is * indeterminate. */ -long rndtol(real x) @safe pure nothrow; /* intrinsic */ - -/***************************************** - * Returns x rounded to a long value using the FE_TONEAREST rounding mode. - * If the integer value of x is - * greater than long.max, the result is - * indeterminate. - */ -extern (C) real rndtonl(real x); +long rndtol(float x); /* intrinsic */ +long rndtol(double x); /* intrinsic */ /// ditto +long rndtol(real x); /* intrinsic */ /// ditto /*************************************** * Compute square root of x. @@ -85,57 +94,65 @@ extern (C) real rndtonl(real x); * ) */ -@safe pure nothrow -{ - float sqrt(float x); /* intrinsic */ - double sqrt(double x); /* intrinsic */ /// ditto - real sqrt(real x); /* intrinsic */ /// ditto -} +float sqrt(float x); /* intrinsic */ +double sqrt(double x); /* intrinsic */ /// ditto +real sqrt(real x); /* intrinsic */ /// ditto /******************************************* * Compute n * 2$(SUPERSCRIPT exp) * References: frexp */ -real ldexp(real n, int exp) @safe pure nothrow; /* intrinsic */ +float ldexp(float n, int exp); /* intrinsic */ +double ldexp(double n, int exp); /* intrinsic */ /// ditto +real ldexp(real n, int exp); /* intrinsic */ /// ditto unittest { static if (real.mant_dig == 113) { - assert(ldexp(1, -16384) == 0x1p-16384L); - assert(ldexp(1, -16382) == 0x1p-16382L); + assert(ldexp(1.0L, -16384) == 0x1p-16384L); + assert(ldexp(1.0L, -16382) == 0x1p-16382L); } else static if (real.mant_dig == 106) { - assert(ldexp(1, 1023) == 0x1p1023L); - assert(ldexp(1, -1022) == 0x1p-1022L); - assert(ldexp(1, -1021) == 0x1p-1021L); + assert(ldexp(1.0L, 1023) == 0x1p1023L); + assert(ldexp(1.0L, -1022) == 0x1p-1022L); + assert(ldexp(1.0L, -1021) == 0x1p-1021L); } else static if (real.mant_dig == 64) { - assert(ldexp(1, -16384) == 0x1p-16384L); - assert(ldexp(1, -16382) == 0x1p-16382L); + assert(ldexp(1.0L, -16384) == 0x1p-16384L); + assert(ldexp(1.0L, -16382) == 0x1p-16382L); } else static if (real.mant_dig == 53) { - assert(ldexp(1, 1023) == 0x1p1023L); - assert(ldexp(1, -1022) == 0x1p-1022L); - assert(ldexp(1, -1021) == 0x1p-1021L); + assert(ldexp(1.0L, 1023) == 0x1p1023L); + assert(ldexp(1.0L, -1022) == 0x1p-1022L); + assert(ldexp(1.0L, -1021) == 0x1p-1021L); } else assert(false, "Only 128bit, 80bit and 64bit reals expected here"); } /******************************* - * Returns |x| - * + * Compute the absolute value. * $(TABLE_SV * $(TR $(TH x) $(TH fabs(x))) * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) ) * $(TR $(TD $(PLUSMN)$(INFIN)) $(TD +$(INFIN)) ) * ) + * It is implemented as a compiler intrinsic. + * Params: + * x = floating point value + * Returns: |x| + * References: equivalent to `std.math.fabs` */ -real fabs(real x) @safe pure nothrow; /* intrinsic */ +@safe pure nothrow @nogc +{ + float fabs(float x); + double fabs(double x); /// ditto + real fabs(real x); /// ditto +} /********************************** * Rounds x to the nearest integer value, using the current rounding @@ -145,22 +162,29 @@ real fabs(real x) @safe pure nothrow; /* intrinsic */ * $(B nearbyint) performs * the same operation, but does not set the FE_INEXACT exception. */ -real rint(real x) @safe pure nothrow; /* intrinsic */ +float rint(float x); /* intrinsic */ +double rint(double x); /* intrinsic */ /// ditto +real rint(real x); /* intrinsic */ /// ditto /*********************************** * Building block functions, they * translate to a single x87 instruction. */ - -real yl2x(real x, real y) @safe pure nothrow; // y * log2(x) -real yl2xp1(real x, real y) @safe pure nothrow; // y * log2(x + 1) +// y * log2(x) +float yl2x(float x, float y); /* intrinsic */ +double yl2x(double x, double y); /* intrinsic */ /// ditto +real yl2x(real x, real y); /* intrinsic */ /// ditto +// y * log2(x +1) +float yl2xp1(float x, float y); /* intrinsic */ +double yl2xp1(double x, double y); /* intrinsic */ /// ditto +real yl2xp1(real x, real y); /* intrinsic */ /// ditto unittest { version (INLINE_YL2X) { - assert(yl2x(1024, 1) == 10); - assert(yl2xp1(1023, 1) == 10); + assert(yl2x(1024.0L, 1) == 10); + assert(yl2xp1(1023.0L, 1) == 10); } } @@ -179,31 +203,22 @@ unittest * Returns: * f in precision of type `T` */ -@safe pure nothrow T toPrec(T:float)(float f) { pragma(inline, false); return f; } /// ditto -@safe pure nothrow T toPrec(T:float)(double f) { pragma(inline, false); return cast(T) f; } /// ditto -@safe pure nothrow T toPrec(T:float)(real f) { pragma(inline, false); return cast(T) f; } /// ditto -@safe pure nothrow T toPrec(T:double)(float f) { pragma(inline, false); return f; } /// ditto -@safe pure nothrow T toPrec(T:double)(double f) { pragma(inline, false); return f; } /// ditto -@safe pure nothrow T toPrec(T:double)(real f) { pragma(inline, false); return cast(T) f; } /// ditto -@safe pure nothrow T toPrec(T:real)(float f) { pragma(inline, false); return f; } /// ditto -@safe pure nothrow T toPrec(T:real)(double f) { pragma(inline, false); return f; } /// ditto -@safe pure nothrow T toPrec(T:real)(real f) { pragma(inline, false); return f; } @safe unittest