aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Mitchener <bruce.mitchener@gmail.com>2013-09-20 21:59:52 +0700
committerBruce Mitchener <bruce.mitchener@gmail.com>2014-01-14 02:21:11 +0700
commit3b62c6587c50400cf0899c60ee29fa2282efdd28 (patch)
tree8a9cd6b67bd66988969b5e545f878e1a25354630
parent75a6be63a37d68295c0e6da9f9e77d17c8cc7e91 (diff)
Add lots of math functions.
-rwxr-xr-xemcc11
-rw-r--r--src/library.js9
-rw-r--r--system/lib/libc/musl/src/math/ilogb.c26
-rw-r--r--system/lib/libc/musl/src/math/ilogbf.c26
-rw-r--r--system/lib/libc/musl/src/math/ilogbl.c55
-rw-r--r--system/lib/libc/musl/src/math/ldexp.c6
-rw-r--r--system/lib/libc/musl/src/math/ldexpf.c6
-rw-r--r--system/lib/libc/musl/src/math/ldexpl.c6
-rw-r--r--system/lib/libc/musl/src/math/logb.c17
-rw-r--r--system/lib/libc/musl/src/math/logbf.c10
-rw-r--r--system/lib/libc/musl/src/math/logbl.c16
-rw-r--r--system/lib/libc/musl/src/math/scalbn.c31
-rw-r--r--system/lib/libc/musl/src/math/scalbnf.c31
-rw-r--r--system/lib/libcextra.symbols11
14 files changed, 252 insertions, 9 deletions
diff --git a/emcc b/emcc
index 5c63a757..0a9c6556 100755
--- a/emcc
+++ b/emcc
@@ -1542,11 +1542,22 @@ try:
['math', [
'__cosdf.c',
'__sindf.c',
+ 'ilogb.c',
+ 'ilogbf.c',
+ 'ilogbl.c',
+ 'ldexp.c',
+ 'ldexpf.c',
+ 'ldexpl.c',
+ 'logb.c',
+ 'logbf.c',
+ 'logbl.c',
'lgamma.c',
'lgamma_r.c',
'lgammaf.c',
'lgammaf_r.c',
'lgammal.c',
+ 'scalbn.c',
+ 'scalbnf.c',
'signgam.c',
'tgamma.c',
'tgammaf.c',
diff --git a/src/library.js b/src/library.js
index 83a287be..9c515552 100644
--- a/src/library.js
+++ b/src/library.js
@@ -4827,15 +4827,6 @@ LibraryManager.library = {
llvm_log_f64: 'Math_log',
llvm_exp_f32: 'Math_exp',
llvm_exp_f64: 'Math_exp',
- ldexp: function(x, exp_) {
- return x * Math.pow(2, exp_);
- },
- ldexpf: 'ldexp',
- scalb: 'ldexp',
- scalbn: 'ldexp',
- scalbnf: 'ldexp',
- scalbln: 'ldexp',
- scalblnf: 'ldexp',
cbrt: function(x) {
return Math.pow(x, 1/3);
},
diff --git a/system/lib/libc/musl/src/math/ilogb.c b/system/lib/libc/musl/src/math/ilogb.c
new file mode 100644
index 00000000..64d40154
--- /dev/null
+++ b/system/lib/libc/musl/src/math/ilogb.c
@@ -0,0 +1,26 @@
+#include <limits.h>
+#include "libm.h"
+
+int ilogb(double x)
+{
+ #pragma STDC FENV_ACCESS ON
+ union {double f; uint64_t i;} u = {x};
+ uint64_t i = u.i;
+ int e = i>>52 & 0x7ff;
+
+ if (!e) {
+ i <<= 12;
+ if (i == 0) {
+ FORCE_EVAL(0/0.0f);
+ return FP_ILOGB0;
+ }
+ /* subnormal x */
+ for (e = -0x3ff; i>>63 == 0; e--, i<<=1);
+ return e;
+ }
+ if (e == 0x7ff) {
+ FORCE_EVAL(0/0.0f);
+ return i<<12 ? FP_ILOGBNAN : INT_MAX;
+ }
+ return e - 0x3ff;
+}
diff --git a/system/lib/libc/musl/src/math/ilogbf.c b/system/lib/libc/musl/src/math/ilogbf.c
new file mode 100644
index 00000000..e23ba209
--- /dev/null
+++ b/system/lib/libc/musl/src/math/ilogbf.c
@@ -0,0 +1,26 @@
+#include <limits.h>
+#include "libm.h"
+
+int ilogbf(float x)
+{
+ #pragma STDC FENV_ACCESS ON
+ union {float f; uint32_t i;} u = {x};
+ uint32_t i = u.i;
+ int e = i>>23 & 0xff;
+
+ if (!e) {
+ i <<= 9;
+ if (i == 0) {
+ FORCE_EVAL(0/0.0f);
+ return FP_ILOGB0;
+ }
+ /* subnormal x */
+ for (e = -0x7f; i>>31 == 0; e--, i<<=1);
+ return e;
+ }
+ if (e == 0xff) {
+ FORCE_EVAL(0/0.0f);
+ return i<<9 ? FP_ILOGBNAN : INT_MAX;
+ }
+ return e - 0x7f;
+}
diff --git a/system/lib/libc/musl/src/math/ilogbl.c b/system/lib/libc/musl/src/math/ilogbl.c
new file mode 100644
index 00000000..7b1a9cf8
--- /dev/null
+++ b/system/lib/libc/musl/src/math/ilogbl.c
@@ -0,0 +1,55 @@
+#include <limits.h>
+#include "libm.h"
+
+#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
+int ilogbl(long double x)
+{
+ return ilogb(x);
+}
+#elif LDBL_MANT_DIG == 64 && LDBL_MAX_EXP == 16384
+int ilogbl(long double x)
+{
+ #pragma STDC FENV_ACCESS ON
+ union ldshape u = {x};
+ uint64_t m = u.i.m;
+ int e = u.i.se & 0x7fff;
+
+ if (!e) {
+ if (m == 0) {
+ FORCE_EVAL(0/0.0f);
+ return FP_ILOGB0;
+ }
+ /* subnormal x */
+ for (e = -0x3fff+1; m>>63 == 0; e--, m<<=1);
+ return e;
+ }
+ if (e == 0x7fff) {
+ FORCE_EVAL(0/0.0f);
+ return m<<1 ? FP_ILOGBNAN : INT_MAX;
+ }
+ return e - 0x3fff;
+}
+#elif LDBL_MANT_DIG == 113 && LDBL_MAX_EXP == 16384
+int ilogbl(long double x)
+{
+ #pragma STDC FENV_ACCESS ON
+ union ldshape u = {x};
+ int e = u.i.se & 0x7fff;
+
+ if (!e) {
+ if (x == 0) {
+ FORCE_EVAL(0/0.0f);
+ return FP_ILOGB0;
+ }
+ /* subnormal x */
+ x *= 0x1p120;
+ return ilogbl(x) - 120;
+ }
+ if (e == 0x7fff) {
+ FORCE_EVAL(0/0.0f);
+ u.i.se = 0;
+ return u.f ? FP_ILOGBNAN : INT_MAX;
+ }
+ return e - 0x3fff;
+}
+#endif
diff --git a/system/lib/libc/musl/src/math/ldexp.c b/system/lib/libc/musl/src/math/ldexp.c
new file mode 100644
index 00000000..f4d1cd6a
--- /dev/null
+++ b/system/lib/libc/musl/src/math/ldexp.c
@@ -0,0 +1,6 @@
+#include <math.h>
+
+double ldexp(double x, int n)
+{
+ return scalbn(x, n);
+}
diff --git a/system/lib/libc/musl/src/math/ldexpf.c b/system/lib/libc/musl/src/math/ldexpf.c
new file mode 100644
index 00000000..3bad5f39
--- /dev/null
+++ b/system/lib/libc/musl/src/math/ldexpf.c
@@ -0,0 +1,6 @@
+#include <math.h>
+
+float ldexpf(float x, int n)
+{
+ return scalbnf(x, n);
+}
diff --git a/system/lib/libc/musl/src/math/ldexpl.c b/system/lib/libc/musl/src/math/ldexpl.c
new file mode 100644
index 00000000..fd145ccc
--- /dev/null
+++ b/system/lib/libc/musl/src/math/ldexpl.c
@@ -0,0 +1,6 @@
+#include <math.h>
+
+long double ldexpl(long double x, int n)
+{
+ return scalbnl(x, n);
+}
diff --git a/system/lib/libc/musl/src/math/logb.c b/system/lib/libc/musl/src/math/logb.c
new file mode 100644
index 00000000..7f8bdfae
--- /dev/null
+++ b/system/lib/libc/musl/src/math/logb.c
@@ -0,0 +1,17 @@
+#include <math.h>
+
+/*
+special cases:
+ logb(+-0) = -inf, and raise divbyzero
+ logb(+-inf) = +inf
+ logb(nan) = nan
+*/
+
+double logb(double x)
+{
+ if (!isfinite(x))
+ return x * x;
+ if (x == 0)
+ return -1/(x*x);
+ return ilogb(x);
+}
diff --git a/system/lib/libc/musl/src/math/logbf.c b/system/lib/libc/musl/src/math/logbf.c
new file mode 100644
index 00000000..a0a0b5ed
--- /dev/null
+++ b/system/lib/libc/musl/src/math/logbf.c
@@ -0,0 +1,10 @@
+#include <math.h>
+
+float logbf(float x)
+{
+ if (!isfinite(x))
+ return x * x;
+ if (x == 0)
+ return -1/(x*x);
+ return ilogbf(x);
+}
diff --git a/system/lib/libc/musl/src/math/logbl.c b/system/lib/libc/musl/src/math/logbl.c
new file mode 100644
index 00000000..962973a7
--- /dev/null
+++ b/system/lib/libc/musl/src/math/logbl.c
@@ -0,0 +1,16 @@
+#include <math.h>
+#if LDBL_MANT_DIG == 53 && LDBL_MAX_EXP == 1024
+long double logbl(long double x)
+{
+ return logb(x);
+}
+#else
+long double logbl(long double x)
+{
+ if (!isfinite(x))
+ return x * x;
+ if (x == 0)
+ return -1/(x*x);
+ return ilogbl(x);
+}
+#endif
diff --git a/system/lib/libc/musl/src/math/scalbn.c b/system/lib/libc/musl/src/math/scalbn.c
new file mode 100644
index 00000000..530e07c7
--- /dev/null
+++ b/system/lib/libc/musl/src/math/scalbn.c
@@ -0,0 +1,31 @@
+#include <math.h>
+#include <stdint.h>
+
+double scalbn(double x, int n)
+{
+ union {double f; uint64_t i;} u;
+ double_t y = x;
+
+ if (n > 1023) {
+ y *= 0x1p1023;
+ n -= 1023;
+ if (n > 1023) {
+ y *= 0x1p1023;
+ n -= 1023;
+ if (n > 1023)
+ n = 1023;
+ }
+ } else if (n < -1022) {
+ y *= 0x1p-1022;
+ n += 1022;
+ if (n < -1022) {
+ y *= 0x1p-1022;
+ n += 1022;
+ if (n < -1022)
+ n = -1022;
+ }
+ }
+ u.i = (uint64_t)(0x3ff+n)<<52;
+ x = y * u.f;
+ return x;
+}
diff --git a/system/lib/libc/musl/src/math/scalbnf.c b/system/lib/libc/musl/src/math/scalbnf.c
new file mode 100644
index 00000000..0b62c3c7
--- /dev/null
+++ b/system/lib/libc/musl/src/math/scalbnf.c
@@ -0,0 +1,31 @@
+#include <math.h>
+#include <stdint.h>
+
+float scalbnf(float x, int n)
+{
+ union {float f; uint32_t i;} u;
+ float_t y = x;
+
+ if (n > 127) {
+ y *= 0x1p127f;
+ n -= 127;
+ if (n > 127) {
+ y *= 0x1p127f;
+ n -= 127;
+ if (n > 127)
+ n = 127;
+ }
+ } else if (n < -126) {
+ y *= 0x1p-126f;
+ n += 126;
+ if (n < -126) {
+ y *= 0x1p-126f;
+ n += 126;
+ if (n < -126)
+ n = -126;
+ }
+ }
+ u.i = (uint32_t)(0x7f+n)<<23;
+ x = y * u.f;
+ return x;
+}
diff --git a/system/lib/libcextra.symbols b/system/lib/libcextra.symbols
index 8d22ec4f..db1d3dcd 100644
--- a/system/lib/libcextra.symbols
+++ b/system/lib/libcextra.symbols
@@ -24,6 +24,9 @@
T iconv
T iconv_close
T iconv_open
+ T ilogb
+ T ilogbf
+ T ilogbl
T iswalnum
T iswalnum_l
T iswalpha
@@ -50,12 +53,18 @@
T iswupper_l
T iswxdigit
T iswxdigit_l
+ T ldexp
+ T ldexpf
+ T ldexpl
T lgamma
W lgamma_r
T lgammaf
W lgammaf_r
T lgammal
W lgammal_r
+ T logb
+ T logbf
+ T logbl
T mblen
T mbrlen
T mbrtowc
@@ -72,6 +81,8 @@
T regerror
T regexec
T regfree
+ T scalbn
+ T scalbnf
D signgam
T strcasecmp_l
T strcasestr