Library: add round.c to the maths library
authorAlan Cox <alan@linux.intel.com>
Sat, 30 Sep 2017 18:35:24 +0000 (19:35 +0100)
committerAlan Cox <alan@linux.intel.com>
Sat, 30 Sep 2017 18:35:24 +0000 (19:35 +0100)
Library/libs/Makefile.z80
Library/libs/round.c [new file with mode: 0644]

index 03c3bcd..25ab657 100644 (file)
@@ -81,7 +81,7 @@ SRC_LM += hypotf.c ilogbf.c j0f.c j1f.c jnf.c
 SRC_LM += ldexpf.c lgammaf.c lgammaf_r.c logf.c log2f.c log10f.c logbf.c
 SRC_LM += lrintf.c lroundf.c
 SRC_LM += modff.c nearbyintf.c nextafterf.c powf.c
-SRC_LM += remainderf.c remquof.c rintf.c
+SRC_LM += remainderf.c remquof.c rintf.c round.c
 SRC_LM += scalbnf.c scalbinf.c
 SRC_LM += sinf.c sincosf.c sinhf.c
 SRC_LM += sqrtf.c tgammaf.c
diff --git a/Library/libs/round.c b/Library/libs/round.c
new file mode 100644 (file)
index 0000000..9087566
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ * ====================================================
+ * 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 "libm.h"
+
+double round(double x)
+{
+       /* Most significant word, least significant word. */
+       __int32_t msw, exponent_less_1023;
+       __uint32_t lsw;
+
+       EXTRACT_WORDS(msw, lsw, x);
+
+       /* Extract exponent field. */
+       exponent_less_1023 = ((msw & 0x7ff00000) >> 20) - 1023;
+
+       if (exponent_less_1023 < 20) {
+               if (exponent_less_1023 < 0) {
+                       msw &= 0x80000000;
+                       if (exponent_less_1023 == -1)
+                               /* Result is +1.0 or -1.0. */
+                               msw |= (1023 << 20);
+                       lsw = 0;
+               } else {
+                       __uint32_t exponent_mask = 0x000fffff >> exponent_less_1023;
+                       if ((msw & exponent_mask) == 0 && lsw == 0)
+                               /* x in an integral value. */
+                               return x;
+
+                       msw += 0x00080000 >> exponent_less_1023;
+                       msw &= ~exponent_mask;
+                       lsw = 0;
+               }
+       } else if (exponent_less_1023 > 51) {
+               if (exponent_less_1023 == 1024)
+                       /* x is NaN or infinite. */
+                       return x + x;
+               else
+                       return x;
+       } else {
+               __uint32_t exponent_mask = 0xffffffff >> (exponent_less_1023 - 20);
+               __uint32_t tmp;
+
+               if ((lsw & exponent_mask) == 0)
+                       /* x is an integral value. */
+                       return x;
+
+               tmp = lsw + (1 << (51 - exponent_less_1023));
+               if (tmp < lsw)
+                       msw += 1;
+               lsw = tmp;
+
+               lsw &= ~exponent_mask;
+       }
+       INSERT_WORDS(x, msw, lsw);
+
+       return x;
+}