pkgsrc/math/R/patches/patch-src_main_format.c
marino a7d93cac81 math/R: Expand NetBSD floorl patch to DragonFly
DragonFly has the same math limitations as NetBSD, so it needs the same fix.
2011-12-18 02:50:07 +00:00

71 lines
2 KiB
C

$NetBSD: patch-src_main_format.c,v 1.2 2011/12/18 02:50:08 marino Exp $
NetBSD does not have rintl() or floorl() so use the OpenBSD implementation
of rintl() in that case. The same case exists for DragonFly.
--- src/main/format.c.orig 2011-10-02 22:02:34.000000000 +0000
+++ src/main/format.c
@@ -130,6 +130,7 @@ void formatInteger(int *x, int n, int *f
# define R_nearbyintl rintl
# else
# define R_nearbyintl private_nearbyintl
+# if !defined(__NetBSD__) && !defined(__DragonFly__)
long double private_nearbyintl(long double x)
{
long double x1;
@@ -142,6 +143,55 @@ long double private_nearbyintl(long doub
if (x/2.0 == floorl(x/2.0)) return(x); else return(x1);
}
}
+# else
+#include <machine/ieee.h>
+
+#if LDBL_MAX_EXP != 0x4000
+/* We also require the usual bias, min exp and expsign packing. */
+#error "Unsupported long double format"
+#endif
+
+#define BIAS (LDBL_MAX_EXP - 1)
+
+static const float
+shift[2] = {
+#if LDBL_MANT_DIG == 64
+ 0x1.0p63, -0x1.0p63
+#elif LDBL_MANT_DIG == 113
+ 0x1.0p112, -0x1.0p112
+#else
+#error "Unsupported long double format"
+#endif
+};
+static const float zero[2] = { 0.0, -0.0 };
+
+long double private_nearbyintl(long double x)
+{
+ union {
+ long double e;
+ struct ieee_ext bits;
+ } u;
+ uint32_t expsign;
+ int ex, sign;
+ u.e = x;
+ expsign = (u.bits.ext_sign << 15) | u.bits.ext_exp;
+ ex = expsign & 0x7fff;
+
+ if (ex >= BIAS + LDBL_MANT_DIG - 1) {
+ if (ex == BIAS + LDBL_MAX_EXP)
+ return (x + x); /* Inf, NaN, or unsupported format */
+ return (x); /* finite and already an integer */
+ }
+ sign = expsign >> 15;
+ x += shift[sign];
+ x -= shift[sign];
+
+ if (ex < BIAS && x == 0.0L)
+ return (zero[sign]);
+
+ return (x);
+}
+# endif
# endif
# else /* no long double */
# ifdef HAVE_NEARBYINT