Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libm/src Add a long double version of trunc.



details:   https://anonhg.NetBSD.org/src/rev/1c3ec0ba3c8a
branches:  trunk
changeset: 780829:1c3ec0ba3c8a
user:      matt <matt%NetBSD.org@localhost>
date:      Wed Aug 08 16:57:24 2012 +0000

description:
Add a long double version of trunc.

diffstat:

 lib/libm/src/s_truncl.c |  133 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 133 insertions(+), 0 deletions(-)

diffs (137 lines):

diff -r b41efddc838f -r 1c3ec0ba3c8a lib/libm/src/s_truncl.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/libm/src/s_truncl.c   Wed Aug 08 16:57:24 2012 +0000
@@ -0,0 +1,133 @@
+/* @(#)s_floor.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("$FreeBSD: src/lib/msun/src/s_trunc.c,v 1.1 2004/06/20 09:25:43 das Exp $");
+#endif
+#if defined(LIBM_SCCS) && !defined(lint)
+__RCSID("$NetBSD: s_truncl.c,v 1.1 2012/08/08 16:57:24 matt Exp $");
+#endif
+
+/*
+ * trunc(x)
+ * Return x rounded toward 0 to integral value
+ * Method:
+ *     Bit twiddling.
+ * Exception:
+ *     Inexact flag raised if x was not equal to trunc(x).
+ */
+
+#include <machine/ieee.h>
+#include <float.h>
+#include "math.h"
+#include "math_private.h"
+
+#ifdef __HAVE_LONG_DOUBLE
+
+static const long double huge = LDBL_MAX;
+
+long double
+truncl(long double x)
+{
+       struct ieee_ext_u ux = { .extu_ld = x, };
+       int32_t exponent = ux.extu_exp - EXT_EXP_BIAS;
+#ifdef LDBL_MANT_DIG == EXT_FRACBITS
+       /*
+        * If there is no hidden bit, don't count it
+        */
+       const u_int frach_bits = EXT_FRACHBITS - 1;
+       const u_int frac_bits = EXT_FRACBITS - 1;
+#else
+       const u_int frach_bits = EXT_FRACHBITS;
+       const u_int frac_bits = EXT_FRACBITS;
+#endif
+
+       /*
+        * If this number is big enough to have no fractional digits...
+        * (or is an inf or nan).
+        */
+       if (exponent >= frac_bits) {
+               if (exponent == EXT_EXP_NAN - EXT_EXP_BIAS)
+                       return x+x;     /* x is inf or nan */
+               return x;               /* x is integral */
+       }
+
+       /*
+        * If this number is too small enough to have any integral digits...
+        */
+       if (exponent < 0 && (huge - x > 0.0 || true)) {
+               /* set inexact if x != 0 */
+               /* |x|<1, so return 0*sign(x) */
+               return ux.extu_sign ? -0.0 : 0.0;
+       }
+
+       uint32_t frach_mask = __BIT(frach_bits) - 1;
+#ifdef EXT_FRACHMBITS
+       uint32_t frachm_mask = __BIT(EXT_FRACHMBITS) - 1;
+#endif
+#ifdef EXT_FRACHMBITS
+       uint32_t frachl_mask = __BIT(EXT_FRACLMBITS) - 1;
+#endif
+       uint32_t fracl_mask = __BIT(EXT_FRACLBITS) - 1;
+
+       if (exponent < frach_bits) {
+               frach_mask >>= exponent;
+#ifdef EXT_FRACHMBITS
+       } else if (exponent < frach_bits + EXT_FRACHM_BITS) {
+               frach_mask = 0;         exponent -= frach_bits;
+               frachm_mask >>= exponent;
+#endif
+#ifdef EXT_FRACLMBITS
+       } else if (exponent < frach_bits + EXT_FRACHM_BITS + EXT_FRACLMBITS) {
+               frach_mask = 0;         exponent -= frach_bits;
+               frachm_mask = 0;        exponent -= EXT_FRACHMBITS;
+               fraclm_mask >>= exponent;
+#endif
+       } else {
+               frach_mask = 0;         exponent -= frach_bits;
+#ifdef EXT_FRACHMBITS
+               frachm_mask = 0;        exponent -= EXT_FRACHMBITS;
+#endif
+#ifdef EXT_FRACLMBITS
+               fraclm_mask = 0;        exponent -= EXT_FRACLMBITS;
+#endif
+               fraclm_mask >>= exponent;
+       }
+
+       if ((ux.extu_frach & frach_mask) == 0
+#ifdef EXT_FRACHMBITS
+           && (ux.extu_frachm & frachm_mask) == 0
+#endif
+#ifdef EXT_FRACLMBITS
+           && (ux.extu_fraclm & frachm_mask) == 0
+#endif
+           && (ux.extu_fracl & fracl_mask) == 0)
+               return x; /* x is integral */
+
+       if (huge - x > 0.0 || true) {           /* set inexact flag */
+               /*
+                * Clear any fractional bits...
+                */
+               ux.extu_frach &= ~frach_mask;
+#ifdef EXT_FRACHMBITS
+               ux.extu_frachm &= ~frachm_mask;
+#endif
+#ifdef EXT_FRACLMBITS
+               ux.extu_fraclm &= ~fraclm_mask;
+#endif
+               ux.extu_fracl &= ~fracl_mask;
+               return ux.extu_ld;
+       }
+}
+
+#endif /* __HAVE_LONG_DOUBLE */



Home | Main Index | Thread Index | Old Index