summaryrefslogtreecommitdiff
path: root/sys/src/ape/lib/ap/plan9/frexp.c
diff options
context:
space:
mode:
authorTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
committerTaru Karttunen <taruti@taruti.net>2011-03-30 15:46:40 +0300
commite5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch)
treed8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/plan9/frexp.c
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/plan9/frexp.c')
-rwxr-xr-xsys/src/ape/lib/ap/plan9/frexp.c89
1 files changed, 89 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/plan9/frexp.c b/sys/src/ape/lib/ap/plan9/frexp.c
new file mode 100755
index 000000000..588f90cee
--- /dev/null
+++ b/sys/src/ape/lib/ap/plan9/frexp.c
@@ -0,0 +1,89 @@
+#include <math.h>
+#include <errno.h>
+#define _RESEARCH_SOURCE
+#include <float.h>
+
+#define MASK 0x7ffL
+#define SHIFT 20
+#define BIAS 1022L
+
+typedef union
+{
+ double d;
+ struct
+ {
+#ifdef IEEE_8087
+ long ls;
+ long ms;
+#else
+ long ms;
+ long ls;
+#endif
+ };
+} Cheat;
+
+double
+frexp(double d, int *ep)
+{
+ Cheat x;
+
+ if(d == 0) {
+ *ep = 0;
+ return 0;
+ }
+ x.d = d;
+ *ep = ((x.ms >> SHIFT) & MASK) - BIAS;
+ x.ms &= ~(MASK << SHIFT);
+ x.ms |= BIAS << SHIFT;
+ return x.d;
+}
+
+double
+ldexp(double d, int e)
+{
+ Cheat x;
+
+ if(d == 0)
+ return 0;
+ x.d = d;
+ e += (x.ms >> SHIFT) & MASK;
+ if(e <= 0)
+ return 0;
+ if(e >= MASK){
+ errno = ERANGE;
+ if(d < 0)
+ return -HUGE_VAL;
+ return HUGE_VAL;
+ }
+ x.ms &= ~(MASK << SHIFT);
+ x.ms |= (long)e << SHIFT;
+ return x.d;
+}
+
+double
+modf(double d, double *ip)
+{
+ double f;
+ Cheat x;
+ int e;
+
+ if(d < 1) {
+ if(d < 0) {
+ f = modf(-d, ip);
+ *ip = -*ip;
+ return -f;
+ }
+ *ip = 0;
+ return d;
+ }
+ x.d = d;
+ e = ((x.ms >> SHIFT) & MASK) - BIAS;
+ if(e <= SHIFT+1) {
+ x.ms &= ~(0x1fffffL >> e);
+ x.ls = 0;
+ } else
+ if(e <= SHIFT+33)
+ x.ls &= ~(0x7fffffffL >> (e-SHIFT-2));
+ *ip = x.d;
+ return d - x.d;
+}