зеркало из https://github.com/mozilla/gecko-dev.git
Bug 531915 - part 3 - add back needed rounding helpers and emulate freebsd internal double types ?tjr r=arai
Differential Revision: https://phabricator.services.mozilla.com/D119423
This commit is contained in:
Родитель
474a039e5c
Коммит
8dc9e8a52f
|
@ -1,46 +1,15 @@
|
|||
diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
|
||||
--- a/modules/fdlibm/src/math_private.h
|
||||
+++ b/modules/fdlibm/src/math_private.h
|
||||
@@ -586,126 +586,16 @@ CMPLXL(long double x, long double y)
|
||||
REALPART(z) = x;
|
||||
IMAGPART(z) = y;
|
||||
return (z.f);
|
||||
@@ -617,95 +617,32 @@ rnint(double x)
|
||||
* magic number would need to be variable. Assuming that the
|
||||
* rounding precision is always the default is too fragile. This
|
||||
* and many other complications will move when the default is
|
||||
* changed to FP_PE.
|
||||
*/
|
||||
return ((double)(x + 0x1.8p52) - 0x1.8p52);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _COMPLEX_H */
|
||||
|
||||
-/*
|
||||
- * The rnint() family rounds to the nearest integer for a restricted range
|
||||
- * range of args (up to about 2**MANT_DIG). We assume that the current
|
||||
- * rounding mode is FE_TONEAREST so that this can be done efficiently.
|
||||
- * Extra precision causes more problems in practice, and we only centralize
|
||||
- * this here to reduce those problems, and have not solved the efficiency
|
||||
- * problems. The exp2() family uses a more delicate version of this that
|
||||
- * requires extracting bits from the intermediate value, so it is not
|
||||
- * centralized here and should copy any solution of the efficiency problems.
|
||||
- */
|
||||
-
|
||||
-static inline double
|
||||
-rnint(__double_t x)
|
||||
-{
|
||||
- /*
|
||||
- * This casts to double to kill any extra precision. This depends
|
||||
- * on the cast being applied to a double_t to avoid compiler bugs
|
||||
- * (this is a cleaner version of STRICT_ASSIGN()). This is
|
||||
- * inefficient if there actually is extra precision, but is hard
|
||||
- * to improve on. We use double_t in the API to minimise conversions
|
||||
- * for just calling here. Note that we cannot easily change the
|
||||
- * magic number to the one that works directly with double_t, since
|
||||
- * the rounding precision is variable at runtime on x86 so the
|
||||
- * magic number would need to be variable. Assuming that the
|
||||
- * rounding precision is always the default is too fragile. This
|
||||
- * and many other complications will move when the default is
|
||||
- * changed to FP_PE.
|
||||
- */
|
||||
- return ((double)(x + 0x1.8p52) - 0x1.8p52);
|
||||
-}
|
||||
-
|
||||
-static inline float
|
||||
-rnintf(__float_t x)
|
||||
-{
|
||||
|
@ -71,22 +40,22 @@ diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private
|
|||
-}
|
||||
-#endif /* LDBL_MANT_DIG */
|
||||
-
|
||||
-/*
|
||||
- * irint() and i64rint() give the same result as casting to their integer
|
||||
- * return type provided their arg is a floating point integer. They can
|
||||
- * sometimes be more efficient because no rounding is required.
|
||||
- */
|
||||
-#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
|
||||
-#define irint(x) \
|
||||
- (sizeof(x) == sizeof(float) && \
|
||||
- sizeof(__float_t) == sizeof(long double) ? irintf(x) : \
|
||||
- sizeof(x) == sizeof(double) && \
|
||||
- sizeof(__double_t) == sizeof(long double) ? irintd(x) : \
|
||||
- sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x))
|
||||
-#else
|
||||
-#define irint(x) ((int)(x))
|
||||
-#endif
|
||||
-
|
||||
/*
|
||||
* irint() and i64rint() give the same result as casting to their integer
|
||||
* return type provided their arg is a floating point integer. They can
|
||||
* sometimes be more efficient because no rounding is required.
|
||||
*/
|
||||
#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
|
||||
#define irint(x) \
|
||||
(sizeof(x) == sizeof(float) && \
|
||||
sizeof(__float_t) == sizeof(long double) ? irintf(x) : \
|
||||
sizeof(x) == sizeof(double) && \
|
||||
sizeof(__double_t) == sizeof(long double) ? irintd(x) : \
|
||||
sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x))
|
||||
#else
|
||||
#define irint(x) ((int)(x))
|
||||
#endif
|
||||
|
||||
-#define i64rint(x) ((int64_t)(x)) /* only needed for ld128 so not opt. */
|
||||
-
|
||||
-#if defined(__i386__) && defined(__GNUCLIKE_ASM)
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
diff --git a/modules/fdlibm/src/math_private.h b/modules/fdlibm/src/math_private.h
|
||||
--- a/modules/fdlibm/src/math_private.h
|
||||
+++ b/modules/fdlibm/src/math_private.h
|
||||
@@ -21,16 +21,28 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "fdlibm.h"
|
||||
|
||||
#include "mozilla/EndianUtils.h"
|
||||
|
||||
/*
|
||||
+ * Emulate FreeBSD internal double types.
|
||||
+ * Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t
|
||||
+ */
|
||||
+
|
||||
+#if defined(__i386__)
|
||||
+typedef long double __double_t;
|
||||
+#else
|
||||
+typedef double __double_t;
|
||||
+#endif
|
||||
+typedef __double_t double_t;
|
||||
+
|
||||
+/*
|
||||
* The original fdlibm code used statements like:
|
||||
* n0 = ((*(int*)&one)>>29)^1; * index of high word *
|
||||
* ix0 = *(n0+(int*)&x); * high word of x *
|
||||
* ix1 = *((1-n0)+(int*)&x); * low word of x *
|
||||
* to dig two 32 bit words out of the 64 bit IEEE floating point
|
||||
* value. That is non-ANSI, and, moreover, the gcc instruction
|
||||
* scheduler gets it wrong. We instead use the following macros.
|
||||
* Unlike the original code, we determine the endianness at compile
|
|
@ -25,6 +25,18 @@
|
|||
|
||||
#include "mozilla/EndianUtils.h"
|
||||
|
||||
/*
|
||||
* Emulate FreeBSD internal double types.
|
||||
* Adapted from https://github.com/freebsd/freebsd-src/search?q=__double_t
|
||||
*/
|
||||
|
||||
#if defined(__i386__)
|
||||
typedef long double __double_t;
|
||||
#else
|
||||
typedef double __double_t;
|
||||
#endif
|
||||
typedef __double_t double_t;
|
||||
|
||||
/*
|
||||
* The original fdlibm code used statements like:
|
||||
* n0 = ((*(int*)&one)>>29)^1; * index of high word *
|
||||
|
@ -591,6 +603,53 @@ CMPLXL(long double x, long double y)
|
|||
|
||||
#endif /* _COMPLEX_H */
|
||||
|
||||
/*
|
||||
* The rnint() family rounds to the nearest integer for a restricted range
|
||||
* range of args (up to about 2**MANT_DIG). We assume that the current
|
||||
* rounding mode is FE_TONEAREST so that this can be done efficiently.
|
||||
* Extra precision causes more problems in practice, and we only centralize
|
||||
* this here to reduce those problems, and have not solved the efficiency
|
||||
* problems. The exp2() family uses a more delicate version of this that
|
||||
* requires extracting bits from the intermediate value, so it is not
|
||||
* centralized here and should copy any solution of the efficiency problems.
|
||||
*/
|
||||
|
||||
static inline double
|
||||
rnint(__double_t x)
|
||||
{
|
||||
/*
|
||||
* This casts to double to kill any extra precision. This depends
|
||||
* on the cast being applied to a double_t to avoid compiler bugs
|
||||
* (this is a cleaner version of STRICT_ASSIGN()). This is
|
||||
* inefficient if there actually is extra precision, but is hard
|
||||
* to improve on. We use double_t in the API to minimise conversions
|
||||
* for just calling here. Note that we cannot easily change the
|
||||
* magic number to the one that works directly with double_t, since
|
||||
* the rounding precision is variable at runtime on x86 so the
|
||||
* magic number would need to be variable. Assuming that the
|
||||
* rounding precision is always the default is too fragile. This
|
||||
* and many other complications will move when the default is
|
||||
* changed to FP_PE.
|
||||
*/
|
||||
return ((double)(x + 0x1.8p52) - 0x1.8p52);
|
||||
}
|
||||
|
||||
/*
|
||||
* irint() and i64rint() give the same result as casting to their integer
|
||||
* return type provided their arg is a floating point integer. They can
|
||||
* sometimes be more efficient because no rounding is required.
|
||||
*/
|
||||
#if (defined(amd64) || defined(__i386__)) && defined(__GNUCLIKE_ASM)
|
||||
#define irint(x) \
|
||||
(sizeof(x) == sizeof(float) && \
|
||||
sizeof(__float_t) == sizeof(long double) ? irintf(x) : \
|
||||
sizeof(x) == sizeof(double) && \
|
||||
sizeof(__double_t) == sizeof(long double) ? irintd(x) : \
|
||||
sizeof(x) == sizeof(long double) ? irintl(x) : (int)(x))
|
||||
#else
|
||||
#define irint(x) ((int)(x))
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#if defined(__amd64__) || defined(__i386__)
|
||||
#define breakpoint() asm("int $3")
|
||||
|
|
Загрузка…
Ссылка в новой задаче