diff --git a/src/core/math.d b/src/core/math.d
index ef09fc1be9..995da33dac 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 */
@@ -108,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
{
@@ -172,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 */
@@ -208,8 +192,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); }
}
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 )
{
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
{
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);
-}
-
-