date and time created 92/07/07 11:49:04 by torek
authorChris Torek <torek@ucbvax.Berkeley.EDU>
Wed, 8 Jul 1992 02:49:04 +0000 (18:49 -0800)
committerChris Torek <torek@ucbvax.Berkeley.EDU>
Wed, 8 Jul 1992 02:49:04 +0000 (18:49 -0800)
SCCS-vsn: lib/libc/quad/fixunssfdi.c 5.1

usr/src/lib/libc/quad/fixunssfdi.c [new file with mode: 0644]

diff --git a/usr/src/lib/libc/quad/fixunssfdi.c b/usr/src/lib/libc/quad/fixunssfdi.c
new file mode 100644 (file)
index 0000000..2358597
--- /dev/null
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * %sccs.include.redist.c%
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fixunssfdi.c       5.1 (Berkeley) %G%";
+#endif /* LIBC_SCCS and not lint */
+
+#include "quad.h"
+
+#define        ONE_FOURTH      (1 << (LONG_BITS - 2))
+#define        ONE_HALF        (ONE_FOURTH * 2.0)
+#define        ONE             (ONE_FOURTH * 4.0)
+
+/*
+ * Convert float to (unsigned) quad.  We do most of our work in double,
+ * out of sheer paranoia.
+ *
+ * Not sure what to do with negative numbers---for now, anything out
+ * of range becomes UQUAD_MAX.
+ *
+ * N.B.: must use new ANSI syntax (sorry).
+ */
+u_quad_t
+__fixunssfdi(float f)
+{
+       double x, toppart;
+       union uu t;
+
+       if (f < 0)
+               return (UQUAD_MAX);     /* ??? should be 0?  ERANGE??? */
+       if (f >= UQUAD_MAX)
+               return (UQUAD_MAX);
+       x = f;
+       /*
+        * Get the upper part of the result.  Note that the divide
+        * may round up; we want to avoid this if possible, so we
+        * subtract `1/2' first.
+        */
+       toppart = (x - ONE_HALF) / ONE;
+       /*
+        * Now build a u_quad_t out of the top part.  The difference
+        * between x and this is the bottom part (this may introduce
+        * a few fuzzy bits, but what the heck).  With any luck this
+        * difference will be nonnegative: x should wind up in the
+        * range [0..ULONG_MAX].  For paranoia, we assume [LONG_MIN..
+        * 2*ULONG_MAX] instead.
+        */
+       t.ul[H] = (unsigned long)toppart;
+       t.ul[L] = 0;
+       x -= (double)t.uq;
+       if (x < 0) {
+               t.ul[H]--;
+               x += ULONG_MAX;
+       }
+       if (x > ULONG_MAX) {
+               t.ul[H]++;
+               x -= ULONG_MAX;
+       }
+       t.ul[L] = (u_long)x;
+       return (t.uq);
+}