summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibM
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2021-01-12 12:17:30 +0100
committerAndreas Kling <kling@serenityos.org>2021-01-12 12:17:46 +0100
commit13d7c09125f8eec703d0a43a9a87fc8aa08f7319 (patch)
tree70fd643c429cea5c1f9362c2674511d17a53f3b5 /Userland/Libraries/LibM
parentdc28c07fa526841e05e16161c74a6c23984f1dd5 (diff)
downloadserenity-13d7c09125f8eec703d0a43a9a87fc8aa08f7319.zip
Libraries: Move to Userland/Libraries/
Diffstat (limited to 'Userland/Libraries/LibM')
-rw-r--r--Userland/Libraries/LibM/CMakeLists.txt10
-rw-r--r--Userland/Libraries/LibM/TestMath.cpp114
-rw-r--r--Userland/Libraries/LibM/math.cpp566
-rw-r--r--Userland/Libraries/LibM/math.h137
4 files changed, 827 insertions, 0 deletions
diff --git a/Userland/Libraries/LibM/CMakeLists.txt b/Userland/Libraries/LibM/CMakeLists.txt
new file mode 100644
index 0000000000..bdb9baf78a
--- /dev/null
+++ b/Userland/Libraries/LibM/CMakeLists.txt
@@ -0,0 +1,10 @@
+set(SOURCES
+ math.cpp
+)
+
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -nostdlib")
+serenity_libc(LibM m)
+#target_link_libraries(LibM)
+#set_target_properties(LibM PROPERTIES OUTPUT_NAME m)
+#target_link_directories(LibM PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/Userland/Libraries/LibM/TestMath.cpp b/Userland/Libraries/LibM/TestMath.cpp
new file mode 100644
index 0000000000..1a5ce4e87a
--- /dev/null
+++ b/Userland/Libraries/LibM/TestMath.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/TestSuite.h>
+
+#include <math.h>
+
+#define EXPECT_CLOSE(a, b) \
+ { \
+ EXPECT(fabs(a - b) < 0.000001); \
+ }
+
+TEST_CASE(trig)
+{
+ EXPECT_CLOSE(sin(1234), 0.653316);
+ EXPECT_CLOSE(cos(1234), -0.830914);
+ EXPECT_CLOSE(tan(1234), -0.786262);
+ EXPECT_CLOSE(sqrt(1234), 35.128336)
+ EXPECT_CLOSE(sin(-1), -0.867955);
+ EXPECT_CLOSE(cos(-1), 0.594715);
+ EXPECT_CLOSE(tan(-1), -1.459446);
+ EXPECT(isnan(sqrt(-1)));
+ EXPECT(isnan(asin(1.1)));
+ EXPECT(isnan(asin(-1.1)));
+ EXPECT_CLOSE(asin(0), 0.0);
+ EXPECT_CLOSE(asin(0.01), 0.01);
+ EXPECT_CLOSE(asin(0.1), 0.100167);
+ EXPECT_CLOSE(asin(0.3), 0.304693);
+ EXPECT_CLOSE(asin(0.499), 0.522444);
+ EXPECT_CLOSE(asin(0.5), 0.523599);
+ EXPECT_CLOSE(asin(0.501), 0.524754);
+ EXPECT_CLOSE(asin(0.9), 1.119770);
+ EXPECT_CLOSE(asin(0.99), 1.429246);
+ EXPECT_CLOSE(asin(1.0), 1.570750);
+ EXPECT_CLOSE(atan(0), 0.0)
+ EXPECT_CLOSE(atan(0.5), 0.463648)
+ EXPECT_CLOSE(atan(-0.5), -0.463648)
+ EXPECT_CLOSE(atan(5.5), 1.390943)
+ EXPECT_CLOSE(atan(-5.5), -1.390943)
+ EXPECT_CLOSE(atan(555.5), 1.568996)
+}
+
+TEST_CASE(other)
+{
+ EXPECT_EQ(trunc(9999999999999.5), 9999999999999.0);
+ EXPECT_EQ(trunc(-9999999999999.5), -9999999999999.0);
+}
+
+TEST_CASE(exponents)
+{
+ struct values {
+ double x;
+ double exp;
+ double sinh;
+ double cosh;
+ double tanh;
+ };
+
+ values values[8] {
+ { 1.500000, 4.481626, 2.129246, 2.352379, 0.905148 },
+ { 20.990000, 1304956710.432035, 652478355.216017, 652478355.216017, 1.000000 },
+ { 20.010000, 490041186.687082, 245020593.343541, 245020593.343541, 1.000000 },
+ { 0.000000, 1.000000, 0.000000, 1.000000, 0.000000 },
+ { 0.010000, 1.010050, 0.010000, 1.000050, 0.010000 },
+ { -0.010000, 0.990050, -0.010000, 1.000050, -0.010000 },
+ { -1.000000, 0.367879, -1.175201, 1.543081, -0.761594 },
+ { -17.000000, 0.000000, -12077476.376788, 12077476.376788, -1.000000 },
+ };
+ for (auto& v : values) {
+ EXPECT_CLOSE(exp(v.x), v.exp);
+ EXPECT_CLOSE(sinh(v.x), v.sinh);
+ EXPECT_CLOSE(cosh(v.x), v.cosh);
+ EXPECT_CLOSE(tanh(v.x), v.tanh);
+ }
+ EXPECT_EQ(exp(1000), std::numeric_limits<double>::infinity());
+}
+
+TEST_CASE(logarithms)
+{
+ EXPECT(isnan(log(-1)));
+ EXPECT(log(0) < -1000000);
+ EXPECT_CLOSE(log(0.5), -0.693233)
+ EXPECT_CLOSE(log(1.1), 0.095310)
+ EXPECT_CLOSE(log(5), 1.609480)
+ EXPECT_CLOSE(log(5.5), 1.704842)
+ EXPECT_CLOSE(log(500), 6.214104)
+ EXPECT_CLOSE(log2(5), 2.321989)
+ EXPECT_CLOSE(log10(5), 0.698988)
+}
+
+TEST_MAIN(Math)
diff --git a/Userland/Libraries/LibM/math.cpp b/Userland/Libraries/LibM/math.cpp
new file mode 100644
index 0000000000..2c5c86bdcf
--- /dev/null
+++ b/Userland/Libraries/LibM/math.cpp
@@ -0,0 +1,566 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibC/assert.h>
+#include <math.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+template<size_t>
+constexpr double e_to_power();
+template<>
+constexpr double e_to_power<0>() { return 1; }
+template<size_t exponent>
+constexpr double e_to_power() { return M_E * e_to_power<exponent - 1>(); }
+
+template<size_t>
+constexpr size_t factorial();
+template<>
+constexpr size_t factorial<0>() { return 1; }
+template<size_t value>
+constexpr size_t factorial() { return value * factorial<value - 1>(); }
+
+template<size_t>
+constexpr size_t product_even();
+template<>
+constexpr size_t product_even<2>() { return 2; }
+template<size_t value>
+constexpr size_t product_even() { return value * product_even<value - 2>(); }
+
+template<size_t>
+constexpr size_t product_odd();
+template<>
+constexpr size_t product_odd<1>() { return 1; }
+template<size_t value>
+constexpr size_t product_odd() { return value * product_odd<value - 2>(); }
+
+extern "C" {
+
+double trunc(double x) NOEXCEPT
+{
+ return (int64_t)x;
+}
+
+double cos(double angle) NOEXCEPT
+{
+ return sin(angle + M_PI_2);
+}
+
+float cosf(float angle) NOEXCEPT
+{
+ return sinf(angle + M_PI_2);
+}
+
+// This can also be done with a taylor expansion, but for
+// now this works pretty well (and doesn't mess anything up
+// in quake in particular, which is very Floating-Point precision
+// heavy)
+double sin(double angle) NOEXCEPT
+{
+ double ret = 0.0;
+ __asm__(
+ "fsin"
+ : "=t"(ret)
+ : "0"(angle));
+
+ return ret;
+}
+
+float sinf(float angle) NOEXCEPT
+{
+ float ret = 0.0f;
+ __asm__(
+ "fsin"
+ : "=t"(ret)
+ : "0"(angle));
+ return ret;
+}
+
+double pow(double x, double y) NOEXCEPT
+{
+ // FIXME: Please fix me. I am naive.
+ if (isnan(y))
+ return y;
+ if (y == 0)
+ return 1;
+ if (x == 0)
+ return 0;
+ if (y == 1)
+ return x;
+ int y_as_int = (int)y;
+ if (y == (double)y_as_int) {
+ double result = x;
+ for (int i = 0; i < fabs(y) - 1; ++i)
+ result *= x;
+ if (y < 0)
+ result = 1.0 / result;
+ return result;
+ }
+ return exp2(y * log2(x));
+}
+
+float powf(float x, float y) NOEXCEPT
+{
+ return (float)pow(x, y);
+}
+
+double ldexp(double x, int exp) NOEXCEPT
+{
+ return x * exp2(exp);
+}
+
+float ldexpf(float x, int exp) NOEXCEPT
+{
+ return x * exp2f(exp);
+}
+
+double tanh(double x) NOEXCEPT
+{
+ if (x > 0) {
+ double exponentiated = exp(2 * x);
+ return (exponentiated - 1) / (exponentiated + 1);
+ }
+ double plusX = exp(x);
+ double minusX = 1 / plusX;
+ return (plusX - minusX) / (plusX + minusX);
+}
+
+static double ampsin(double angle) NOEXCEPT
+{
+ double looped_angle = fmod(M_PI + angle, M_TAU) - M_PI;
+ double looped_angle_squared = looped_angle * looped_angle;
+
+ double quadratic_term;
+ if (looped_angle > 0) {
+ quadratic_term = -looped_angle_squared;
+ } else {
+ quadratic_term = looped_angle_squared;
+ }
+
+ double linear_term = M_PI * looped_angle;
+
+ return quadratic_term + linear_term;
+}
+
+double tan(double angle) NOEXCEPT
+{
+ return ampsin(angle) / ampsin(M_PI_2 + angle);
+}
+
+double sqrt(double x) NOEXCEPT
+{
+ double res;
+ __asm__("fsqrt"
+ : "=t"(res)
+ : "0"(x));
+ return res;
+}
+
+float sqrtf(float x) NOEXCEPT
+{
+ float res;
+ __asm__("fsqrt"
+ : "=t"(res)
+ : "0"(x));
+ return res;
+}
+
+double sinh(double x) NOEXCEPT
+{
+ double exponentiated = exp(x);
+ if (x > 0)
+ return (exponentiated * exponentiated - 1) / 2 / exponentiated;
+ return (exponentiated - 1 / exponentiated) / 2;
+}
+
+double log10(double x) NOEXCEPT
+{
+ double ret = 0.0;
+ __asm__(
+ "fldlg2\n"
+ "fld %%st(1)\n"
+ "fyl2x\n"
+ "fstp %%st(1)"
+ : "=t"(ret)
+ : "0"(x));
+ return ret;
+}
+
+double log(double x) NOEXCEPT
+{
+ double ret = 0.0;
+ __asm__(
+ "fldln2\n"
+ "fld %%st(1)\n"
+ "fyl2x\n"
+ "fstp %%st(1)"
+ : "=t"(ret)
+ : "0"(x));
+ return ret;
+}
+
+float logf(float x) NOEXCEPT
+{
+ return (float)log(x);
+}
+
+double fmod(double index, double period) NOEXCEPT
+{
+ return index - trunc(index / period) * period;
+}
+
+float fmodf(float index, float period) NOEXCEPT
+{
+ return index - trunc(index / period) * period;
+}
+
+double exp(double exponent) NOEXCEPT
+{
+ double res = 0;
+ __asm__("fldl2e\n"
+ "fmulp\n"
+ "fld1\n"
+ "fld %%st(1)\n"
+ "fprem\n"
+ "f2xm1\n"
+ "faddp\n"
+ "fscale\n"
+ "fstp %%st(1)"
+ : "=t"(res)
+ : "0"(exponent));
+ return res;
+}
+
+float expf(float exponent) NOEXCEPT
+{
+ return (float)exp(exponent);
+}
+
+double exp2(double exponent) NOEXCEPT
+{
+ double res = 0;
+ __asm__("fld1\n"
+ "fld %%st(1)\n"
+ "fprem\n"
+ "f2xm1\n"
+ "faddp\n"
+ "fscale\n"
+ "fstp %%st(1)"
+ : "=t"(res)
+ : "0"(exponent));
+ return res;
+}
+
+float exp2f(float exponent) NOEXCEPT
+{
+ return (float)exp2(exponent);
+}
+
+double cosh(double x) NOEXCEPT
+{
+ double exponentiated = exp(-x);
+ if (x < 0)
+ return (1 + exponentiated * exponentiated) / 2 / exponentiated;
+ return (1 / exponentiated + exponentiated) / 2;
+}
+
+double atan2(double y, double x) NOEXCEPT
+{
+ if (x > 0)
+ return atan(y / x);
+ if (x == 0) {
+ if (y > 0)
+ return M_PI_2;
+ if (y < 0)
+ return -M_PI_2;
+ return 0;
+ }
+ if (y >= 0)
+ return atan(y / x) + M_PI;
+ return atan(y / x) - M_PI;
+}
+
+float atan2f(float y, float x) NOEXCEPT
+{
+ return (float)atan2(y, x);
+}
+
+double atan(double x) NOEXCEPT
+{
+ if (x < 0)
+ return -atan(-x);
+ if (x > 1)
+ return M_PI_2 - atan(1 / x);
+ double squared = x * x;
+ return x / (1 + 1 * 1 * squared / (3 + 2 * 2 * squared / (5 + 3 * 3 * squared / (7 + 4 * 4 * squared / (9 + 5 * 5 * squared / (11 + 6 * 6 * squared / (13 + 7 * 7 * squared)))))));
+}
+
+double asin(double x) NOEXCEPT
+{
+ if (x > 1 || x < -1)
+ return NAN;
+ if (x > 0.5 || x < -0.5)
+ return 2 * atan(x / (1 + sqrt(1 - x * x)));
+ double squared = x * x;
+ double value = x;
+ double i = x * squared;
+ value += i * product_odd<1>() / product_even<2>() / 3;
+ i *= squared;
+ value += i * product_odd<3>() / product_even<4>() / 5;
+ i *= squared;
+ value += i * product_odd<5>() / product_even<6>() / 7;
+ i *= squared;
+ value += i * product_odd<7>() / product_even<8>() / 9;
+ i *= squared;
+ value += i * product_odd<9>() / product_even<10>() / 11;
+ i *= squared;
+ value += i * product_odd<11>() / product_even<12>() / 13;
+ return value;
+}
+
+float asinf(float x) NOEXCEPT
+{
+ return (float)asin(x);
+}
+
+double acos(double x) NOEXCEPT
+{
+ return M_PI_2 - asin(x);
+}
+
+float acosf(float x) NOEXCEPT
+{
+ return M_PI_2 - asinf(x);
+}
+
+double fabs(double value) NOEXCEPT
+{
+ return value < 0 ? -value : value;
+}
+
+double log2(double x) NOEXCEPT
+{
+ double ret = 0.0;
+ __asm__(
+ "fld1\n"
+ "fld %%st(1)\n"
+ "fyl2x\n"
+ "fstp %%st(1)"
+ : "=t"(ret)
+ : "0"(x));
+ return ret;
+}
+
+float log2f(float x) NOEXCEPT
+{
+ return log2(x);
+}
+
+long double log2l(long double x) NOEXCEPT
+{
+ return log2(x);
+}
+
+double frexp(double, int*) NOEXCEPT
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+float frexpf(float, int*) NOEXCEPT
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+long double frexpl(long double, int*) NOEXCEPT
+{
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+double round(double value) NOEXCEPT
+{
+ // FIXME: Please fix me. I am naive.
+ if (value >= 0.0)
+ return (double)(int)(value + 0.5);
+ return (double)(int)(value - 0.5);
+}
+
+float roundf(float value) NOEXCEPT
+{
+ // FIXME: Please fix me. I am naive.
+ if (value >= 0.0f)
+ return (float)(int)(value + 0.5f);
+ return (float)(int)(value - 0.5f);
+}
+
+float floorf(float value) NOEXCEPT
+{
+ if (value >= 0)
+ return (int)value;
+ int intvalue = (int)value;
+ return ((float)intvalue == value) ? intvalue : intvalue - 1;
+}
+
+double floor(double value) NOEXCEPT
+{
+ if (value >= 0)
+ return (int)value;
+ int intvalue = (int)value;
+ return ((double)intvalue == value) ? intvalue : intvalue - 1;
+}
+
+double rint(double value) NOEXCEPT
+{
+ return (int)roundf(value);
+}
+
+float ceilf(float value) NOEXCEPT
+{
+ // FIXME: Please fix me. I am naive.
+ int as_int = (int)value;
+ if (value == (float)as_int)
+ return as_int;
+ if (value < 0) {
+ if (as_int == 0)
+ return -0;
+ return as_int;
+ }
+ return as_int + 1;
+}
+
+double ceil(double value) NOEXCEPT
+{
+ // FIXME: Please fix me. I am naive.
+ int as_int = (int)value;
+ if (value == (double)as_int)
+ return as_int;
+ if (value < 0) {
+ if (as_int == 0)
+ return -0;
+ return as_int;
+ }
+ return as_int + 1;
+}
+
+double modf(double x, double* intpart) NOEXCEPT
+{
+ *intpart = (double)((int)(x));
+ return x - (int)x;
+}
+
+double gamma(double x) NOEXCEPT
+{
+ // Stirling approximation
+ return sqrt(2.0 * M_PI / x) * pow(x / M_E, x);
+}
+
+double expm1(double x) NOEXCEPT
+{
+ return exp(x) - 1;
+}
+
+double cbrt(double x) NOEXCEPT
+{
+ if (isinf(x) || x == 0)
+ return x;
+ if (x < 0)
+ return -cbrt(-x);
+
+ double r = x;
+ double ex = 0;
+
+ while (r < 0.125) {
+ r *= 8;
+ ex--;
+ }
+ while (r > 1.0) {
+ r *= 0.125;
+ ex++;
+ }
+
+ r = (-0.46946116 * r + 1.072302) * r + 0.3812513;
+
+ while (ex < 0) {
+ r *= 0.5;
+ ex++;
+ }
+ while (ex > 0) {
+ r *= 2;
+ ex--;
+ }
+
+ r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
+ r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
+ r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
+ r = (2.0 / 3.0) * r + (1.0 / 3.0) * x / (r * r);
+
+ return r;
+}
+
+double log1p(double x) NOEXCEPT
+{
+ return log(1 + x);
+}
+
+double acosh(double x) NOEXCEPT
+{
+ return log(x + sqrt(x * x - 1));
+}
+
+double asinh(double x) NOEXCEPT
+{
+ return log(x + sqrt(x * x + 1));
+}
+
+double atanh(double x) NOEXCEPT
+{
+ return log((1 + x) / (1 - x)) / 2.0;
+}
+
+double hypot(double x, double y) NOEXCEPT
+{
+ return sqrt(x * x + y * y);
+}
+
+double erf(double x) NOEXCEPT
+{
+ // algorithm taken from Abramowitz and Stegun (no. 26.2.17)
+ double t = 1 / (1 + 0.47047 * fabs(x));
+ double poly = t * (0.3480242 + t * (-0.958798 + t * 0.7478556));
+ double answer = 1 - poly * exp(-x * x);
+ if (x < 0)
+ return -answer;
+
+ return answer;
+}
+
+double erfc(double x) NOEXCEPT
+{
+ return 1 - erf(x);
+}
+}
diff --git a/Userland/Libraries/LibM/math.h b/Userland/Libraries/LibM/math.h
new file mode 100644
index 0000000000..8d9b727ddc
--- /dev/null
+++ b/Userland/Libraries/LibM/math.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+
+#if __cplusplus >= 201103L
+# define NOEXCEPT noexcept
+#else
+# define NOEXCEPT
+#endif
+
+__BEGIN_DECLS
+
+#define HUGE_VAL 1e10000
+#define INFINITY __builtin_huge_val()
+#define NAN __builtin_nan("")
+#define M_E 2.718281828459045
+#define M_PI 3.141592653589793
+#define M_PI_2 1.570796326794896
+#define M_TAU 6.283185307179586
+#define M_DEG2RAD 0.017453292519943
+#define M_RAD2DEG 57.29577951308232
+#define M_LN2 0.69314718055995
+#define M_LN10 2.30258509299405
+#define M_SQRT2 1.4142135623730951
+#define M_SQRT1_2 0.7071067811865475
+
+#define FP_NAN 0
+#define FP_INFINITE 1
+#define FP_ZERO 2
+#define FP_SUBNORMAL 3
+#define FP_NORMAL 4
+#define fpclassify(x) __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_ZERO, FP_SUBNORMAL, FP_ZERO, x)
+
+#define signbit(x) __builtin_signbit(x)
+#define isnan(x) __builtin_isnan(x)
+#define isinf(x) __builtin_isinf_sign(x)
+#define isfinite(x) __builtin_isfinite(x)
+#define isnormal(x) __builtin_isnormal(x)
+
+#define DOUBLE_MAX ((double)0b0111111111101111111111111111111111111111111111111111111111111111)
+#define DOUBLE_MIN ((double)0b0000000000010000000000000000000000000000000000000000000000000000)
+
+double acos(double) NOEXCEPT;
+float acosf(float) NOEXCEPT;
+double asin(double) NOEXCEPT;
+float asinf(float) NOEXCEPT;
+double atan(double) NOEXCEPT;
+float atanf(float) NOEXCEPT;
+double atan2(double, double) NOEXCEPT;
+float atan2f(float, float) NOEXCEPT;
+double cos(double) NOEXCEPT;
+float cosf(float) NOEXCEPT;
+double cosh(double) NOEXCEPT;
+float coshf(float) NOEXCEPT;
+double sin(double) NOEXCEPT;
+float sinf(float) NOEXCEPT;
+double sinh(double) NOEXCEPT;
+float sinhf(float) NOEXCEPT;
+double tan(double) NOEXCEPT;
+float tanf(float) NOEXCEPT;
+double tanh(double) NOEXCEPT;
+float tanhf(float) NOEXCEPT;
+double ceil(double) NOEXCEPT;
+float ceilf(float) NOEXCEPT;
+double floor(double) NOEXCEPT;
+float floorf(float) NOEXCEPT;
+double round(double) NOEXCEPT;
+float roundf(float) NOEXCEPT;
+double fabs(double) NOEXCEPT;
+float fabsf(float) NOEXCEPT;
+double fmod(double, double) NOEXCEPT;
+float fmodf(float, float) NOEXCEPT;
+double exp(double) NOEXCEPT;
+float expf(float) NOEXCEPT;
+double exp2(double) NOEXCEPT;
+float exp2f(float) NOEXCEPT;
+double frexp(double, int* exp) NOEXCEPT;
+float frexpf(float, int* exp) NOEXCEPT;
+double log(double) NOEXCEPT;
+float logf(float) NOEXCEPT;
+double log10(double) NOEXCEPT;
+float log10f(float) NOEXCEPT;
+double sqrt(double) NOEXCEPT;
+float sqrtf(float) NOEXCEPT;
+double modf(double, double*) NOEXCEPT;
+float modff(float, float*) NOEXCEPT;
+double ldexp(double, int exp) NOEXCEPT;
+float ldexpf(float, int exp) NOEXCEPT;
+
+double pow(double x, double y) NOEXCEPT;
+float powf(float x, float y) NOEXCEPT;
+
+double log2(double) NOEXCEPT;
+float log2f(float) NOEXCEPT;
+long double log2l(long double) NOEXCEPT;
+double frexp(double, int*) NOEXCEPT;
+float frexpf(float, int*) NOEXCEPT;
+long double frexpl(long double, int*) NOEXCEPT;
+
+double gamma(double) NOEXCEPT;
+double expm1(double) NOEXCEPT;
+double cbrt(double) NOEXCEPT;
+double log1p(double) NOEXCEPT;
+double acosh(double) NOEXCEPT;
+double asinh(double) NOEXCEPT;
+double atanh(double) NOEXCEPT;
+double hypot(double, double) NOEXCEPT;
+double erf(double) NOEXCEPT;
+double erfc(double) NOEXCEPT;
+
+__END_DECLS