From aa78568f6d407c00f7fafcbe0a99c81457815625 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 18 Oct 2014 02:56:02 +0200 Subject: [PATCH 1/5] core.stdc.math: full support for MSVCRT 2013+ --- src/core/stdc/math.d | 331 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 324 insertions(+), 7 deletions(-) diff --git a/src/core/stdc/math.d b/src/core/stdc/math.d index 5ad4189bb0..ac0a02c610 100644 --- a/src/core/stdc/math.d +++ b/src/core/stdc/math.d @@ -187,8 +187,25 @@ version( DMC_RUNTIME ) } } } -else version( MSVC_RUNTIME ) +else version( MSVC_RUNTIME ) // requires MSVCRT >= 2013 { + enum + { + FP_SUBNORMAL = -2, + FP_NORMAL = -1, + FP_ZERO = 0, + FP_INFINITE = 1, + FP_NAN = 2, + } + + private short _fdclass(float x); + private short _dclass(double x); + + private int _fdsign(float x); + private int _dsign(double x); + + deprecated("Please use the standard C99 functions instead.") + { enum { _FPCLASS_SNAN = 1, @@ -206,7 +223,7 @@ else version( MSVC_RUNTIME ) float _copysignf(float x, float s); float _chgsignf(float x); int _finitef(float x); - int _isnanf(float x); + version(Win64) int _isnanf(float x); // not available in Win32? int _fpclassf(float x); double _copysign(double x, double s); @@ -214,13 +231,45 @@ else version( MSVC_RUNTIME ) int _finite(double x); int _isnan(double x); int _fpclass(double x); + } + + extern(D) + { + //int fpclassify(real-floating x); + int fpclassify(float x) { return _fdclass(x); } + int fpclassify(double x) { return _dclass(x); } + int fpclassify(real x) { static if (real.sizeof == double.sizeof) return _dclass(x); else assert(0); } + + //int isfinite(real-floating x); + int isfinite(float x) { return fpclassify(x) <= 0; } + int isfinite(double x) { return fpclassify(x) <= 0; } + int isfinite(real x) { return fpclassify(x) <= 0; } + + //int isinf(real-floating x); + int isinf(float x) { return fpclassify(x) == FP_INFINITE; } + int isinf(double x) { return fpclassify(x) == FP_INFINITE; } + int isinf(real x) { return fpclassify(x) == FP_INFINITE; } - extern(D) + //int isnan(real-floating x); + int isnan(float x) { return fpclassify(x) == FP_NAN; } + int isnan(double x) { return fpclassify(x) == FP_NAN; } + int isnan(real x) { return fpclassify(x) == FP_NAN; } + + //int isnormal(real-floating x); + int isnormal(float x) { return fpclassify(x) == FP_NORMAL; } + int isnormal(double x) { return fpclassify(x) == FP_NORMAL; } + int isnormal(real x) { return fpclassify(x) == FP_NORMAL; } + + //int signbit(real-floating x); + int signbit(float x) { return _fdsign(x); } + int signbit(double x) { return _dsign(x); } + int signbit(real x) { - int isnan(float x) { return _isnanf(x); } - int isnan(double x) { return _isnan(x); } - int isnan(real x) { return _isnan(x); } + return (real.sizeof == double.sizeof) + ? (cast(short*)&(x))[3] & 0x8000 + : (cast(short*)&(x))[4] & 0x8000; } + } } else version( linux ) { @@ -675,6 +724,274 @@ extern (D) int isunordered(real x, real y) { return isnan(x) || isnan(y); } } +/* MS define some functions inline. + * Additionally, their *l functions work with a 64-bit long double and are thus + * useless for 80-bit D reals. So we use our own wrapper implementations working + * internally with reduced 64-bit precision. + * This also enables relaxing real to 64-bit double. + */ +version( MSVC_RUNTIME ) // requires MSVCRT >= 2013 +{ + double acos (double x); + version(Win64) float acosf(float x); + version(Win32) float acosf(float x) { return cast(float) acos(x); } + extern(D) real acosl(real x) { return acos(cast(double) x); } + + double asin (double x); + version(Win64) float asinf(float x); + version(Win32) float asinf(float x) { return cast(float) asin(x); } + extern(D) real asinl(real x) { return asin(cast(double) x); } + + double atan (double x); + version(Win64) float atanf(float x); + version(Win32) float atanf(float x) { return cast(float) atan(x); } + extern(D) real atanl(real x) { return atan(cast(double) x); } + + double atan2 (double y, double x); + version(Win64) float atan2f(float y, float x); + version(Win32) float atan2f(float y, float x) { return cast(float) atan2(y, x); } + extern(D) real atan2l(real y, real x) { return atan2(cast(double) y, cast(double) x); } + + double cos (double x); + version(Win64) float cosf(float x); + version(Win32) float cosf(float x) { return cast(float) cos(x); } + extern(D) real cosl(real x) { return cos(cast(double) x); } + + double sin (double x); + version(Win64) float sinf(float x); + version(Win32) float sinf(float x) { return cast(float) sin(x); } + extern(D) real sinl(real x) { return sin(cast(double) x); } + + double tan (double x); + version(Win64) float tanf(float x); + version(Win32) float tanf(float x) { return cast(float) tan(x); } + extern(D) real tanl(real x) { return tan(cast(double) x); } + + double acosh (double x); + float acoshf(float x); + extern(D) real acoshl(real x) { return acosh(cast(double) x); } + + double asinh (double x); + float asinhf(float x); + extern(D) real asinhl(real x) { return asinh(cast(double) x); } + + double atanh (double x); + float atanhf(float x); + extern(D) real atanhl(real x) { return atanh(cast(double) x); } + + double cosh (double x); + version(Win64) float coshf(float x); + version(Win32) float coshf(float x) { return cast(float) cosh(x); } + extern(D) real coshl(real x) { return cosh(cast(double) x); } + + double sinh (double x); + version(Win64) float sinhf(float x); + version(Win32) float sinhf(float x) { return cast(float) sinh(x); } + extern(D) real sinhl(real x) { return sinh(cast(double) x); } + + double tanh (double x); + version(Win64) float tanhf(float x); + version(Win32) float tanhf(float x) { return cast(float) tanh(x); } + extern(D) real tanhl(real x) { return tanh(cast(double) x); } + + double exp (double x); + version(Win64) float expf(float x); + version(Win32) float expf(float x) { return cast(float) exp(x); } + extern(D) real expl(real x) { return exp(cast(double) x); } + + double exp2 (double x); + float exp2f(float x); + extern(D) real exp2l(real x) { return exp2(cast(double) x); } + + double expm1 (double x); + float expm1f(float x); + extern(D) real expm1l(real x) { return expm1(cast(double) x); } + + double frexp (double value, int* exp); + float frexpf(float value, int* exp) { return cast(float) frexp(value, exp); } + extern(D) real frexpl(real value, int* exp) { return frexp(cast(double) value, exp); } + + int ilogb (double x); + int ilogbf(float x); + extern(D) int ilogbl(real x) { return ilogb(cast(double) x); } + + double ldexp (double x, int exp); + float ldexpf(float x, int exp) { return cast(float) ldexp(x, exp); } + extern(D) real ldexpl(real x, int exp) { return ldexp(cast(double) x, exp); } + + double log (double x); + version(Win64) float logf(float x); + version(Win32) float logf(float x) { return cast(float) log(x); } + extern(D) real logl(real x) { return log(cast(double) x); } + + double log10 (double x); + version(Win64) float log10f(float x); + version(Win32) float log10f(float x) { return cast(float) log10(x); } + extern(D) real log10l(real x) { return log10(cast(double) x); } + + double log1p (double x); + float log1pf(float x); + extern(D) real log1pl(real x) { return log1p(cast(double) x); } + + double log2 (double x); + float log2f(float x); + extern(D) real log2l(real x) { return log2(cast(double) x); } + + double logb (double x); + float logbf(float x); + extern(D) real logbl(real x) { return logb(cast(double) x); } + + double modf (double value, double* iptr); + version(Win64) float modff(float value, float* iptr); + version(Win32) float modff(float value, float* iptr) + { + double i; + double r = modf(value, &i); + *iptr = cast(float) i; + return cast(float) r; + } + extern(D) real modfl(real value, real* iptr) + { + double i; + double r = modf(cast(double) value, &i); + *iptr = i; + return r; + } + + double scalbn (double x, int n); + float scalbnf(float x, int n); + extern(D) real scalbnl(real x, int n) { return scalbn(cast(double) x, n); } + + double scalbln (double x, c_long n); + float scalblnf(float x, c_long n); + extern(D) real scalblnl(real x, c_long n) { return scalbln(cast(double) x, n); } + + double cbrt (double x); + float cbrtf(float x); + extern(D) real cbrtl(real x) { return cbrt(cast(double) x); } + + double fabs (double x); + float fabsf(float x) { return cast(float) fabs(x); } + extern(D) real fabsl(real x) { return fabs(cast(double) x); } + + private float _hypotf(float x, float y); + double hypot (double x, double y); + float hypotf(float x, float y) { return _hypotf(x, y); } + extern(D) real hypotl(real x, real y) { return hypot(cast(double) x, cast(double) y); } + + double pow (double x, double y); + version(Win64) float powf(float x, float y); + version(Win32) float powf(float x, float y) { return cast(float) pow(x, y); } + extern(D) real powl(real x, real y) { return pow(cast(double) x, cast(double) y); } + + double sqrt (double x); + version(Win64) float sqrtf(float x); + version(Win32) float sqrtf(float x) { return cast(float) sqrt(x); } + extern(D) real sqrtl(real x) { return sqrt(cast(double) x); } + + double erf (double x); + float erff(float x); + extern(D) real erfl(real x) { return erf(cast(double) x); } + + double erfc (double x); + float erfcf(float x); + extern(D) real erfcl(real x) { return erfc(cast(double) x); } + + double lgamma (double x); + float lgammaf(float x); + extern(D) real lgammal(real x) { return lgamma(cast(double) x); } + + double tgamma (double x); + float tgammaf(float x); + extern(D) real tgammal(real x) { return tgamma(cast(double) x); } + + double ceil (double x); + version(Win64) float ceilf(float x); + version(Win32) float ceilf(float x) { return cast(float) ceil(x); } + extern(D) real ceill(real x) { return ceil(cast(double) x); } + + double floor (double x); + version(Win64) float floorf(float x); + version(Win32) float floorf(float x) { return cast(float) floor(x); } + extern(D) real floorl(real x) { return floor(cast(double) x); } + + double nearbyint (double x); + float nearbyintf(float x); + extern(D) real nearbyintl(real x) { return nearbyint(cast(double) x); } + + double rint (double x); + float rintf(float x); + extern(D) real rintl(real x) { return rint(cast(double) x); } + + c_long lrint (double x); + c_long lrintf(float x); + extern(D) c_long lrintl(real x) { return lrint(cast(double) x); } + + long llrint (double x); + long llrintf(float x); + extern(D) long llrintl(real x) { return llrint(cast(double) x); } + + double round (double x); + float roundf(float x); + extern(D) real roundl(real x) { return round(cast(double) x); } + + c_long lround (double x); + c_long lroundf(float x); + extern(D) c_long lroundl(real x) { return lround(cast(double) x); } + + long llround (double x); + long llroundf(float x); + extern(D) long llroundl(real x) { return llround(cast(double) x); } + + double trunc (double x); + float truncf(float x); + extern(D) real truncl(real x) { return trunc(cast(double) x); } + + double fmod (double x, double y); + version(Win64) float fmodf(float x, float y); + version(Win32) float fmodf(float x, float y) { return cast(float) fmod(x, y); } + extern(D) real fmodl(real x, real y) { return fmod(cast(double) x, cast(double) y); } + + double remainder (double x, double y); + float remainderf(float x, float y); + extern(D) real remainderl(real x, real y) { return remainder(cast(double) x, cast(double) y); } + + double remquo (double x, double y, int* quo); + float remquof(float x, float y, int* quo); + extern(D) real remquol(real x, real y, int* quo) { return remquo(cast(double) x, cast(double) y, quo); } + + double copysign (double x, double y); + float copysignf(float x, float y); + extern(D) real copysignl(real x, real y) { return copysign(cast(double) x, cast(double) y); } + + double nan (char* tagp); + float nanf(char* tagp); + extern(D) real nanl(char* tagp) { return nan(tagp); } + + double nextafter (double x, double y); + float nextafterf(float x, float y); + extern(D) real nextafterl(real x, real y) { return nextafter(cast(double) x, cast(double) y); } + + double nexttoward (double x, real y); + float nexttowardf(float x, real y); + extern(D) real nexttowardl(real x, real y) { return nexttoward(cast(double) x, cast(double) y); } + + double fdim (double x, double y); + float fdimf(float x, float y); + extern(D) real fdiml(real x, real y) { return fdim(cast(double) x, cast(double) y); } + + double fmax (double x, double y); + float fmaxf(float x, float y); + extern(D) real fmaxl(real x, real y) { return fmax(cast(double) x, cast(double) y); } + + double fmin (double x, double y); + float fminf(float x, float y); + extern(D) real fminl(real x, real y) { return fmin(cast(double) x, cast(double) y); } + + double fma (double x, double y, double z); + float fmaf(float x, float y, float z); + extern(D) real fmal(real x, real y, real z) { return fma(cast(double) x, cast(double) y, cast(double) z); } +} /* NOTE: freebsd < 8-CURRENT doesn't appear to support *l, but we can * approximate. * A lot of them were added in 8.0-RELEASE, and so a lot of these workarounds @@ -684,7 +1001,7 @@ extern (D) // acoshl, asinhl, atanhl, coshl, sinhl, tanhl, cbrtl, powl, expl, // expm1l, logl, log1pl, log10l, erfcl, erfl, lgammal, tgammal; // but we can approximate. -version( FreeBSD ) +else version( FreeBSD ) { version (none) // < 8-CURRENT { From d8fb7530f0795373a53c18d50273dee1d72c17e0 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 18 Oct 2014 16:24:42 +0200 Subject: [PATCH 2/5] Remove ldc.longdouble as it conflicts with MSVCRT 2013+ and is obsolete if real == double --- src/ldc/longdouble.d | 297 ------------------------------------------- 1 file changed, 297 deletions(-) delete mode 100644 src/ldc/longdouble.d diff --git a/src/ldc/longdouble.d b/src/ldc/longdouble.d deleted file mode 100644 index 163f43fd3c..0000000000 --- a/src/ldc/longdouble.d +++ /dev/null @@ -1,297 +0,0 @@ -module ldc.longdouble; - -/** -* Implementation of support routines for real data type on Windows 64. -* -* Copyright: Copyright The LDC Developers 2012 -* License: Boost License 1.0. -* Authors: Kai Nacke -*/ - -/* Copyright The LDC Developers 2012. -* Distributed under the Boost Software License, Version 1.0. -* (See accompanying file LICENSE or copy at -* http://www.boost.org/LICENSE_1_0.txt) -*/ - -version(Win64): -extern(C): - -import ldc.llvmasm; - - -private: - enum { - MASK_ROUNDING = 0xf3ffu, - } - - enum { - ROUND_TO_NEAREST = 0x0000u, - ROUND_TO_MINUS_INF = 0x0400u, - ROUND_TO_PLUS_INF = 0x0800u, - ROUND_TO_ZERO = 0x0C00u, - - EXC_PRECISION = 0x0020u, - } - -/* - * The C runtime environment of Visual C++ has no support for long double - * aka real datatype. This file adds the missing functions. - */ - -// Computes the cosine. -real cosl(real x) -{ - return __asm!(real)("fcos", "={st},{st}", x); -} - -// Computes the sine. -real sinl(real x) -{ - return __asm!(real)("fsin", "={st},{st}", x); -} - -unittest -{ - real v = 3.0L; - real s = sinl(v); - real c = cosl(v); - assert(s*s + c*c == 1.0L); -} - -// Computes the tangent. -real tanl(real x) -{ - return __asm!(real)("fptan", "={st},{st}", x); -} - -// Computes the square root. -real sqrtl(real x) -{ - return __asm!(real)("fsqrt", "={st},{st}", x); -} - -unittest -{ - assert(sqrtl(4.0L) == 2.0L); - assert(sqrtl(16.0L) == 4.0L); -} - -// Round to the nearest integer value. -long llroundl(real x) -{ - return 0; -} - -// Returns an unbiased exponent. -real ilogbl(real x) -{ - return 0.0; -} - -// Loads exponent of a floating-point number. -real ldexpl(real arg, int exp) -{ -// See http://llvm.org/bugs/show_bug.cgi?id=15773 -// return __asm!(real)("fscale", "={st},{st(1)},{st},~{st(1)}", exp, arg); - return __asm!(real)("fildl $2 ; fxch %st(1) ; fscale", "={st},{st},*m}", arg, &exp); -} - -// Computes the natural logarithm. -real logl(real x) -{ - // Computes log_e(x) = 1/(log_2 e) * log_2 x - return __asm!(real)("fldl2e; fld1 ; fdivp ; fxch %st(1); fyl2x", "={st},{st}", x); -} - -// Computes the base 10 logarithm. -real log10l(real x) -{ - return __asm!(real)("fldlg2 ; fxch %st(1) ; fyl2x", "={st},{st}", x); -} - -// Computes a natural logarithm. -real log1pl(real x) -{ - // Computes log_e(1.0 + x) = 1/(log_2 e) * log_2 (1.0 + x) - // FIXME: Check input rang of x and use fyl2x if not in range - return __asm!(real)("fldl2e; fld1 ; fdivp ; fxch %st(1); fyl2xp1", "={st},{st}", x); -} - -// Computes the base 2 logarithm. -real log2l(real x) -{ - return __asm!(real)("fld1 ; fxch %st(1) ; fyl2x", "={st},{st}", x); -} - -// Computes the radix-independent exponent. -real logbl(real x) -{ - return 0.0; -} - -// Computes the base-2 exponential of x (2^x). -real exp2l(real x) -{ - return 0.0; -} - -// Computes the base-2 exponential of x (2^x). -double exp2(double x) -{ - return 0.0; -} - -// Computes the base-2 exponential of x (2^x). -float exp2f(float x) -{ - return 0.0; -} - -// Computes the floating-point remainder value. -real fmodl(real arg1, real arg2) -{ - return 0.0; -} - -// Decomposes a floating-point number. -real modfl(real x, real *iptr) -{ - return 0.0; -} - -// Computes the cube root. -real cbrtl(real arg) -{ - return 0.0; -} - -// Determines the absolute value. -real fabsl(real x) -{ - return __asm!(real)("fabs", "={st},{st}", x); -} - -unittest -{ - assert(42.0L == fabsl(-42.0L)); - assert(42.0L == fabsl(42.0L)); -} - -// Compute the ceiling value. -real ceill(real x) -{ - // Store the current FPU control word. - uint fpuctl = void; - __asm!(void)("fstcw $0", "*m", &fpuctl); - // Load new FPU control word with rounding mode set toward +oo (bit 11/10 = 10b) - uint newctl = (fpuctl & MASK_ROUNDING) | ROUND_TO_PLUS_INF; - __asm!(void)("fldcw $0", "*m", &newctl); - // Round to integer - real res = __asm!(real)("frndint", "={st},{st}", x); - // Restore FPU control word - __asm!(void)("fldcw $0", "*m", &fpuctl); - return res; -} - -unittest -{ - assert(5.0L == ceill(4.1L)); - assert(-4.0L == ceill(-4.1L)); -} - -// Return the largest floating-point integer value that is not greater than the parameter. -real floorl(real x) -{ - // Store the current FPU control word. - uint fpuctl = void; - __asm!(void)("fstcw $0", "*m", &fpuctl); - // Load new FPU control word with rounding mode set toward -oo (bit 11/10 = 01b) - uint newctl = (fpuctl & MASK_ROUNDING) | ROUND_TO_MINUS_INF; - __asm!(void)("fldcw $0", "*m", &newctl); - // Round to integer - real res = __asm!(real)("frndint", "={st},{st}", x); - // Restore FPU control word - __asm!(void)("fldcw $0", "*m", &fpuctl); - return res; -} - -unittest -{ - assert(4.0L == floorl(4.1L)); - assert(-5.0L == floorl(-4.1L)); -} - -// Round argument to an integer value in floating-point format, using the current rounding -// direction and without raising the inexact floating-point exception. -real nearbyintl(real x) -{ - // Store the current FPU control word. - uint fpuctl = void; - __asm!(void)("fnstcw $0", "*m", &fpuctl); - // Load new FPU control word with precision exception = blocked (bit 5 set = 0x20) - uint newctl = fpuctl | EXC_PRECISION; - __asm!(void)("fldcw $0", "*m", &newctl); - // Round to integer - real res = __asm!(real)("frndint", "={st},{st}", x); - // Restore FPU control word - __asm!(void)("fldcw $0", "*m", &fpuctl); - return res; -} - -// Returns the integral value (represented as a floating-point number) nearest -// arg in the direction of the current rounding mode. -real rintl(real x) -{ - return __asm!(real)("frndint", "={st},{st}", x); -} - -// Round to the nearest integer value using current rounding direction. -long llrintl(real x) -{ - long res = void; - __asm!(void)("fistpl $0", "=*m,{st},~{st}", &res, x); - return res; -} - -// Rounds to the nearest integer value in a floating-point format. -real roundl(real arg) -{ - return 0.0; -} - -// Rounds to truncated integer value. -real truncl(real x) -{ - // Store the current FPU control word. - uint fpuctl = void; - __asm!(void)("fstcw $0", "*m", &fpuctl); - // Load new FPU control word with rounding mode set toward zero (bit 11/10 = 11b) - uint newctl = (fpuctl & MASK_ROUNDING) | ROUND_TO_ZERO; - __asm!(void)("fldcw $0", "*m", &newctl); - // Round to integer - real res = __asm!(real)("frndint", "={st},{st}", x); - // Restore FPU control word - __asm!(void)("fldcw $0", "*m", &fpuctl); - return res; -} - -// Returns the floating-point remainder. -real remainderl(real x, real y) -{ - return 0.0; -} - -// Computes power. -real powl(real x, real y) -{ - return 0.0; -} - -// Computes the exponent using FLT_RADIX=2. -real scalbnl (real x, int n) -{ - return __asm!(real)("fildl $2 ; fxch %st(1) ; fscale", "={st},{st},*m}", x, &n); -} - - From eec0d99bd1f4672dfa66cf7b1e79b11c3ce4d2b2 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 18 Oct 2014 16:32:29 +0200 Subject: [PATCH 3/5] core.stdc.fenv: get rid of linking error when using MSVC 2013+ --- src/core/stdc/fenv.d | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/stdc/fenv.d b/src/core/stdc/fenv.d index fb8c167816..bc8eaf0d20 100644 --- a/src/core/stdc/fenv.d +++ b/src/core/stdc/fenv.d @@ -195,8 +195,16 @@ enum version( Windows ) { + version( Win64 ) // requires MSVCRT >= 2013 + { + private extern __gshared fenv_t _Fenv0; + fenv_t* FE_DFL_ENV = &_Fenv0; + } + else + { private extern __gshared fenv_t _FE_DFL_ENV; fenv_t* FE_DFL_ENV = &_FE_DFL_ENV; + } } else version( linux ) { From 5b6283feec76a7d36a3507026dbb39d7a474a663 Mon Sep 17 00:00:00 2001 From: Martin Date: Sat, 18 Oct 2014 20:57:52 +0200 Subject: [PATCH 4/5] core.math: proper support for MSVCRT 2013+ --- src/core/math.d | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/core/math.d b/src/core/math.d index ef09fc1be9..549d2d7670 100644 --- a/src/core/math.d +++ b/src/core/math.d @@ -77,9 +77,7 @@ real sin(real x) @safe pure nothrow; /* intrinsic */ */ version (LDC) { - // FIXME: stdc.llroundl not available under Windows - version (Windows) long rndtol(real x) @safe pure nothrow { assert(0); } - else long rndtol(real x) @safe pure nothrow { return stdc.llroundl(x); } + long rndtol(real x) @safe pure nothrow { return stdc.llroundl(x); } } else long rndtol(real x) @safe pure nothrow; /* intrinsic */ @@ -208,8 +206,6 @@ version (LDC) version(HAS_INTRINSIC_RINT) real rint(real x) @safe pure nothrow { return llvm_rint(x); } - else version (Windows) // FIXME: stdc.rintl not available under Windows - real rint(real x) @safe pure nothrow { assert(0); } else real rint(real x) @safe pure nothrow { return stdc.rintl(x); } } From 566a55656e6718247a5483e30c6cf2d1ceba60fc Mon Sep 17 00:00:00 2001 From: Martin Date: Sun, 19 Oct 2014 02:10:51 +0200 Subject: [PATCH 5/5] core.math: use LLVM fabs intrinsic --- src/core/math.d | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/core/math.d b/src/core/math.d index 549d2d7670..995da33dac 100644 --- a/src/core/math.d +++ b/src/core/math.d @@ -106,9 +106,9 @@ extern (C) real rndtonl(real x); { version (LDC) { - extern(D) float sqrt(float x) { return llvm_sqrt(x); } + extern(D) float sqrt(float x) { return llvm_sqrt(x); } extern(D) double sqrt(double x) { return llvm_sqrt(x); } - extern(D) real sqrt(real x) { return llvm_sqrt(x); } + extern(D) real sqrt(real x) { return llvm_sqrt(x); } } else { @@ -170,21 +170,7 @@ unittest { */ version (LDC) { - @trusted pure nothrow real fabs(real x) - { - version (D_InlineAsm_X86) - { - asm - { - fld x; - fabs; - } - } - else - { - return stdc.fabsl(x); - } - } + real fabs(real x) @safe pure nothrow { return llvm_fabs(x); } } else real fabs(real x) @safe pure nothrow; /* intrinsic */