EnderIce2 7e69b8f82a
feat(userspace/libc): support for linux target
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-17 23:18:54 +00:00

1721 lines
27 KiB
C

/*
This file is part of Fennix C Library.
Fennix C Library is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix C Library. If not, see <https://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <sys/types.h>
#include <float.h>
#include <errno.h>
#include <inttypes.h>
#include <bits/libc.h>
#include <fenv.h>
export int signgam;
export double acos(double x)
{
if (x < -1.0 || x > 1.0)
{
errno = EDOM;
return NAN;
}
return atan2(sqrt(1.0 - x * x), x);
}
export float acosf(float x)
{
if (x < -1.0f || x > 1.0f)
{
errno = EDOM;
return NAN;
}
return atan2f(sqrtf(1.0f - x * x), x);
}
export double acosh(double x)
{
if (x < 1.0)
{
errno = EDOM;
return NAN;
}
return log(x + sqrt(x * x - 1.0));
}
export float acoshf(float x)
{
if (x < 1.0f)
{
errno = EDOM;
return NAN;
}
return logf(x + sqrtf(x * x - 1.0f));
}
export long double acoshl(long double x)
{
if (x < 1.0L)
{
errno = EDOM;
return NAN;
}
return logl(x + sqrtl(x * x - 1.0L));
}
export long double acosl(long double x)
{
if (x < -1.0L || x > 1.0L)
{
errno = EDOM;
return NAN;
}
return atan2l(sqrtl(1.0L - x * x), x);
}
export double asin(double x)
{
if (x < -1.0 || x > 1.0)
{
errno = EDOM;
return NAN;
}
return atan2(x, sqrt(1.0 - x * x));
}
export float asinf(float x)
{
if (x < -1.0f || x > 1.0f)
{
errno = EDOM;
return NAN;
}
return atan2f(x, sqrtf(1.0f - x * x));
}
export double asinh(double x)
{
return log(x + sqrt(x * x + 1.0));
}
export float asinhf(float x)
{
return logf(x + sqrtf(x * x + 1.0f));
}
export long double asinhl(long double x)
{
return logl(x + sqrtl(x * x + 1.0L));
}
export long double asinl(long double x)
{
if (x < -1.0L || x > 1.0L)
{
errno = EDOM;
return NAN;
}
return atan2l(x, sqrtl(1.0L - x * x));
}
export double atan(double x)
{
return atan2(x, 1.0);
}
export double atan2(double y, double x)
{
if (x > 0.0)
{
return atan(y / x);
}
else if (x < 0.0 && y >= 0.0)
{
return atan(y / x) + M_PI;
}
else if (x < 0.0 && y < 0.0)
{
return atan(y / x) - M_PI;
}
else if (x == 0.0 && y > 0.0)
{
return M_PI_2;
}
else if (x == 0.0 && y < 0.0)
{
return -M_PI_2;
}
else
{
errno = EDOM;
return NAN;
}
}
export float atan2f(float y, float x)
{
if (x > 0.0f)
{
return atanf(y / x);
}
else if (x < 0.0f && y >= 0.0f)
{
return atanf(y / x) + (float)M_PI;
}
else if (x < 0.0f && y < 0.0f)
{
return atanf(y / x) - (float)M_PI;
}
else if (x == 0.0f && y > 0.0f)
{
return (float)M_PI_2;
}
else if (x == 0.0f && y < 0.0f)
{
return -(float)M_PI_2;
}
else
{
errno = EDOM;
return NAN;
}
}
export long double atan2l(long double y, long double x)
{
if (x > 0.0L)
{
return atanl(y / x);
}
else if (x < 0.0L && y >= 0.0L)
{
return atanl(y / x) + M_PIl;
}
else if (x < 0.0L && y < 0.0L)
{
return atanl(y / x) - M_PIl;
}
else if (x == 0.0L && y > 0.0L)
{
return M_PI_2l;
}
else if (x == 0.0L && y < 0.0L)
{
return -M_PI_2l;
}
else
{
errno = EDOM;
return NAN;
}
}
export float atanf(float x)
{
return atan2f(x, 1.0f);
}
export double atanh(double x)
{
if (x <= -1.0 || x >= 1.0)
{
errno = EDOM;
return NAN;
}
return 0.5 * log((1.0 + x) / (1.0 - x));
}
export float atanhf(float x)
{
if (x <= -1.0f || x >= 1.0f)
{
errno = EDOM;
return NAN;
}
return 0.5f * logf((1.0f + x) / (1.0f - x));
}
export long double atanhl(long double x)
{
if (x <= -1.0L || x >= 1.0L)
{
errno = EDOM;
return NAN;
}
return 0.5L * logl((1.0L + x) / (1.0L - x));
}
export long double atanl(long double x)
{
return atan2l(x, 1.0L);
}
export double cbrt(double x)
{
return pow(x, 1.0 / 3.0);
}
export float cbrtf(float x)
{
return powf(x, 1.0f / 3.0f);
}
export long double cbrtl(long double x)
{
return powl(x, 1.0L / 3.0L);
}
export double ceil(double x)
{
if (x == (double)((long)x))
{
return x;
}
return (x > 0.0) ? (double)((long)x + 1) : (double)((long)x);
}
export float ceilf(float x)
{
if (x == (float)((long)x))
{
return x;
}
return (x > 0.0f) ? (float)((long)x + 1) : (float)((long)x);
}
export long double ceill(long double x)
{
if (x == (long double)((long)x))
{
return x;
}
return (x > 0.0L) ? (long double)((long)x + 1) : (long double)((long)x);
}
export double copysign(double x, double y)
{
return (y < 0.0) ? -fabs(x) : fabs(x);
}
export float copysignf(float x, float y)
{
return (y < 0.0f) ? -fabsf(x) : fabsf(x);
}
export long double copysignl(long double x, long double y)
{
return (y < 0.0L) ? -fabsl(x) : fabsl(x);
}
export double cos(double x)
{
return sin(x + M_PI_2);
}
export float cosf(float x)
{
return sinf(x + (float)M_PI_2);
}
export double cosh(double x)
{
return (exp(x) + exp(-x)) / 2.0;
}
export float coshf(float x)
{
return (expf(x) + expf(-x)) / 2.0f;
}
export long double coshl(long double x)
{
return (expl(x) + expl(-x)) / 2.0L;
}
export long double cosl(long double x)
{
return sinl(x + M_PI_2l);
}
export double erf(double x)
{
double t = 1.0 / (1.0 + 0.5 * fabs(x));
double tau = t * exp(-x * x - 1.26551223 + t * (1.00002368 + t * (0.37409196 + t * (0.09678418 + t * (-0.18628806 + t * (0.27886807 + t * (-1.13520398 + t * (1.48851587 + t * (-0.82215223 + t * 0.17087277)))))))));
return (x >= 0.0) ? 1.0 - tau : tau - 1.0;
}
export double erfc(double x)
{
return 1.0 - erf(x);
}
export float erfcf(float x)
{
return 1.0f - erff(x);
}
export long double erfcl(long double x)
{
return 1.0L - erfl(x);
}
export float erff(float x)
{
float t = 1.0f / (1.0f + 0.5f * fabsf(x));
float tau = t * expf(-x * x - 1.26551223f + t * (1.00002368f + t * (0.37409196f + t * (0.09678418f + t * (-0.18628806f + t * (0.27886807f + t * (-1.13520398f + t * (1.48851587f + t * (-0.82215223f + t * 0.17087277f)))))))));
return (x >= 0.0f) ? 1.0f - tau : tau - 1.0f;
}
export long double erfl(long double x)
{
long double t = 1.0L / (1.0L + 0.5L * fabsl(x));
long double tau = t * expl(-x * x - 1.26551223L + t * (1.00002368L + t * (0.37409196L + t * (0.09678418L + t * (-0.18628806L + t * (0.27886807L + t * (-1.13520398L + t * (1.48851587L + t * (-0.82215223L + t * 0.17087277L)))))))));
return (x >= 0.0L) ? 1.0L - tau : tau - 1.0L;
}
export double exp(double x)
{
if (x == 0.0)
{
return 1.0;
}
if (x < 0.0)
{
return 1.0 / exp(-x);
}
double result = 1.0;
double term = 1.0;
for (int i = 1; term > DBL_EPSILON || term < -DBL_EPSILON; i++)
{
term *= x / i;
result += term;
}
return result;
}
export double exp2(double x)
{
if (x == 0.0)
{
return 1.0;
}
if (x < 0.0)
{
return 1.0 / exp2(-x);
}
double result = 1.0;
double term = 1.0;
for (int i = 1; term > DBL_EPSILON || term < -DBL_EPSILON; i++)
{
term *= x * log(2.0) / i;
result += term;
}
return result;
}
export float exp2f(float x)
{
if (x == 0.0f)
{
return 1.0f;
}
if (x < 0.0f)
{
return 1.0f / exp2f(-x);
}
float result = 1.0f;
float term = 1.0f;
for (int i = 1; term > FLT_EPSILON || term < -FLT_EPSILON; i++)
{
term *= x * logf(2.0f) / i;
result += term;
}
return result;
}
export long double exp2l(long double x)
{
return powl(2.0L, x);
}
export float expf(float x)
{
return powf(M_E, x);
}
export long double expl(long double x)
{
return powl(M_E, x);
}
export double expm1(double x)
{
return exp(x) - 1.0;
}
export float expm1f(float x)
{
return expf(x) - 1.0f;
}
export long double expm1l(long double x)
{
return expl(x) - 1.0L;
}
export double fabs(double x)
{
return (x < 0.0) ? -x : x;
}
export float fabsf(float x)
{
return (x < 0.0f) ? -x : x;
}
export long double fabsl(long double x)
{
return (x < 0.0L) ? -x : x;
}
export double fdim(double x, double y)
{
return (x > y) ? x - y : 0.0;
}
export float fdimf(float x, float y)
{
return (x > y) ? x - y : 0.0f;
}
export long double fdiml(long double x, long double y)
{
return (x > y) ? x - y : 0.0L;
}
export double floor(double x)
{
if (x == (double)((long)x))
{
return x;
}
return (x > 0.0) ? (double)((long)x) : (double)((long)x - 1);
}
export float floorf(float x)
{
if (x == (float)((long)x))
{
return x;
}
return (x > 0.0f) ? (float)((long)x) : (float)((long)x - 1);
}
export long double floorl(long double x)
{
if (x == (long double)((long)x))
{
return x;
}
return (x > 0.0L) ? (long double)((long)x) : (long double)((long)x - 1);
}
export double fma(double x, double y, double z)
{
return x * y + z;
}
export float fmaf(float x, float y, float z)
{
return x * y + z;
}
export long double fmal(long double x, long double y, long double z)
{
return x * y + z;
}
export double fmax(double x, double y)
{
return (x > y) ? x : y;
}
export float fmaxf(float x, float y)
{
return (x > y) ? x : y;
}
export long double fmaxl(long double x, long double y)
{
return (x > y) ? x : y;
}
export double fmin(double x, double y)
{
return (x < y) ? x : y;
}
export float fminf(float x, float y)
{
return (x < y) ? x : y;
}
export long double fminl(long double x, long double y)
{
return (x < y) ? x : y;
}
export double fmod(double x, double y)
{
if (y == 0.0)
{
errno = EDOM;
return NAN;
}
return x - y * floor(x / y);
}
export float fmodf(float x, float y)
{
if (y == 0.0f)
{
errno = EDOM;
return NAN;
}
return x - y * floorf(x / y);
}
export long double fmodl(long double x, long double y)
{
if (y == 0.0L)
{
errno = EDOM;
return NAN;
}
return x - y * floorl(x / y);
}
export double frexp(double num, int *exp)
{
if (num == 0.0)
{
*exp = 0;
return 0.0;
}
double abs_num = fabs(num);
*exp = (int)log2(abs_num) + 1;
double mantissa = abs_num / pow(2.0, *exp);
if (num < 0.0)
{
mantissa = -mantissa;
}
return mantissa;
}
export float frexpf(float num, int *exp)
{
if (num == 0.0f)
{
*exp = 0;
return 0.0f;
}
float abs_num = fabsf(num);
*exp = (int)log2f(abs_num) + 1;
float mantissa = abs_num / powf(2.0f, *exp);
if (num < 0.0f)
{
mantissa = -mantissa;
}
return mantissa;
}
export long double frexpl(long double num, int *exp)
{
if (num == 0.0L)
{
*exp = 0;
return 0.0L;
}
long double abs_num = fabsl(num);
*exp = (int)log2l(abs_num) + 1;
long double mantissa = abs_num / powl(2.0L, *exp);
if (num < 0.0L)
{
mantissa = -mantissa;
}
return mantissa;
}
export double hypot(double x, double y)
{
return sqrt(x * x + y * y);
}
export float hypotf(float x, float y)
{
return sqrtf(x * x + y * y);
}
export long double hypotl(long double x, long double y)
{
return sqrtl(x * x + y * y);
}
export int ilogb(double x)
{
if (x == 0.0)
{
errno = EDOM;
return FP_ILOGB0;
}
if (isnan(x))
{
errno = EDOM;
return FP_ILOGBNAN;
}
return (int)log2(fabs(x));
}
export int ilogbf(float x)
{
if (x == 0.0f)
{
errno = EDOM;
return FP_ILOGB0;
}
if (isnan(x))
{
errno = EDOM;
return FP_ILOGBNAN;
}
return (int)log2f(fabsf(x));
}
export int ilogbl(long double x)
{
if (x == 0.0L)
{
errno = EDOM;
return FP_ILOGB0;
}
if (isnan(x))
{
errno = EDOM;
return FP_ILOGBNAN;
}
return (int)log2l(fabsl(x));
}
export double j0(double x)
{
double ax = fabs(x);
if (ax < 8.0)
{
double y = x * x;
double ans1 = 57568490574.0 + y * (-13362590354.0 + y * (651619640.7 + y * (-11214424.18 + y * (77392.33017 + y * (-184.9052456)))));
double ans2 = 57568490411.0 + y * (1029532985.0 + y * (9494680.718 + y * (59272.64853 + y * (267.8532712 + y * 1.0))));
return ans1 / ans2;
}
else
{
double z = 8.0 / ax;
double y = z * z;
double xx = ax - 0.785398164;
double ans1 = 1.0 + y * (-0.1098628627e-2 + y * (0.2734510407e-4 + y * (-0.2073370639e-5 + y * 0.2093887211e-6)));
double ans2 = -0.1562499995e-1 + y * (0.1430488765e-3 + y * (-0.6911147651e-5 + y * (0.7621095161e-6 - y * 0.934935152e-7)));
return sqrt(0.636619772 / ax) * (cos(xx) * ans1 - z * sin(xx) * ans2);
}
}
export double j1(double x)
{
double ax = fabs(x);
if (ax < 8.0)
{
double y = x * x;
double ans1 = x * (72362614232.0 + y * (-7895059235.0 + y * (242396853.1 + y * (-2972611.439 + y * (15704.48260 + y * (-30.16036606))))));
double ans2 = 144725228442.0 + y * (2300535178.0 + y * (18583304.74 + y * (99447.43394 + y * (376.9991397 + y * 1.0))));
return ans1 / ans2;
}
else
{
double z = 8.0 / ax;
double y = z * z;
double xx = ax - 2.356194491;
double ans1 = 1.0 + y * (0.183105e-2 + y * (-0.3516396496e-4 + y * (0.2457520174e-5 + y * (-0.240337019e-6))));
double ans2 = 0.04687499995 + y * (-0.2002690873e-3 + y * (0.8449199096e-5 + y * (-0.88228987e-6 + y * 0.105787412e-6)));
double ans = sqrt(0.636619772 / ax) * (cos(xx) * ans1 - z * sin(xx) * ans2);
if (x < 0.0)
ans = -ans;
return ans;
}
}
#define BIGNO 1.0e10
#define BIGNI 1.0e-10
export double jn(int n, double x)
{
if (n == 0)
return j0(x);
if (n == 1)
return j1(x);
if (x == 0.0)
return 0.0;
double ax = fabs(x);
double tox = 2.0 / ax;
double bj, bjm, bjp, sum;
int j, m;
if (ax > (double)n)
{
bjm = j0(ax);
bj = j1(ax);
for (j = 1; j < n; j++)
{
bjp = j * tox * bj - bjm;
bjm = bj;
bj = bjp;
}
sum = bj;
}
else
{
#define ACC 40
m = 2 * ((n + (int)sqrt(ACC * n)) / 2);
bjp = sum = 0.0;
bj = 1.0;
for (j = m; j > 0; j--)
{
bjm = j * tox * bj - bjp;
bjp = bj;
bj = bjm;
if (fabs(bj) > BIGNO)
{
bj *= BIGNI;
bjp *= BIGNI;
sum *= BIGNI;
}
if (j == n)
sum = bjp;
}
sum *= j0(ax) / bj;
}
return (x < 0.0 && (n & 1)) ? -sum : sum;
}
export double ldexp(double x, int exp)
{
return x * pow(2.0, exp);
}
export float ldexpf(float x, int exp)
{
return x * powf(2.0f, exp);
}
export long double ldexpl(long double x, int exp)
{
return x * powl(2.0L, exp);
}
export double lgamma(double x)
{
if (x <= 0.0 && floor(x) == x)
{
errno = EDOM;
return NAN;
}
double result = 0.0;
if (x < 0.5)
{
result = log(M_PI) - log(sin(M_PI * x)) - lgamma(1.0 - x);
}
else
{
x -= 1.0;
double a = 0.99999999999980993;
double coefficients[] = {
676.5203681218851,
-1259.1392167224028,
771.32342877765313,
-176.61502916214059,
12.507343278686905,
-0.13857109526572012,
9.9843695780195716e-6,
1.5056327351493116e-7};
for (int i = 0; i < 8; i++)
{
a += coefficients[i] / (x + i + 1);
}
double t = x + 7.5;
result = log(2.5066282746310007 * a) - t + log(t) * (x + 0.5);
}
return result;
}
export float lgammaf(float x)
{
return (float)lgamma((double)x);
}
export long double lgammal(long double x)
{
return (long double)lgamma((double)x);
}
export long long llrint(double x)
{
return (long long)round(x);
}
export long long llrintf(float x)
{
return (long long)roundf(x);
}
export long long llrintl(long double x)
{
return (long long)roundl(x);
}
export long long llround(double x)
{
return (long long)round(x);
}
export long long llroundf(float x)
{
return (long long)roundf(x);
}
export long long llroundl(long double x)
{
return (long long)roundl(x);
}
export double log(double x)
{
if (x <= 0.0)
{
errno = EDOM;
return NAN;
}
double result = 0.0;
double y = (x - 1) / (x + 1);
double y2 = y * y;
double term = y;
for (int i = 1; term > DBL_EPSILON || term < -DBL_EPSILON; i += 2)
{
result += term / i;
term *= y2;
}
return 2 * result;
}
export double log10(double x)
{
return log(x) / log(10.0);
}
export float log10f(float x)
{
return (float)log10((double)x);
}
export long double log10l(long double x)
{
return (long double)log10((double)x);
}
export double log1p(double x)
{
if (x <= -1.0)
{
errno = EDOM;
return NAN;
}
double result = 0.0;
double term = x;
for (int i = 1; term > DBL_EPSILON || term < -DBL_EPSILON; i++)
{
result += term / i;
term *= -x;
}
return result;
}
export float log1pf(float x)
{
return (float)log1p((double)x);
}
export long double log1pl(long double x)
{
return (long double)log1p((double)x);
}
export double log2(double x)
{
return log(x) / log(2.0);
}
export float log2f(float x)
{
return (float)log2((double)x);
}
export long double log2l(long double x)
{
return (long double)log2((double)x);
}
export double logb(double x)
{
if (x == 0.0)
{
errno = ERANGE;
return -HUGE_VAL;
}
if (isnan(x))
{
errno = EDOM;
return NAN;
}
if (isinf(x))
{
return HUGE_VAL;
}
int exp;
frexp(x, &exp);
return (double)(exp - 1);
}
export float logbf(float x)
{
return (float)logb((double)x);
}
export long double logbl(long double x)
{
return (long double)logb((double)x);
}
export float logf(float x)
{
return (float)log((double)x);
}
export long double logl(long double x)
{
return (long double)log((double)x);
}
export long lrint(double x)
{
if (isnan(x) || isinf(x))
{
errno = EDOM;
return 0;
}
return (long)rint(x);
}
export long lrintf(float x)
{
if (isnan(x) || isinf(x))
{
errno = EDOM;
return 0;
}
return (long)rintf(x);
}
export long lrintl(long double x)
{
if (isnan(x) || isinf(x))
{
errno = EDOM;
return 0;
}
return (long)rintl(x);
}
export long lround(double x)
{
return (long)round(x);
}
export long lroundf(float x)
{
return (long)roundf(x);
}
export long lroundl(long double x)
{
return (long)roundl(x);
}
export double modf(double x, double *iptr)
{
*iptr = floor(x);
return x - *iptr;
}
export float modff(float value, float *iptr)
{
*iptr = floorf(value);
return value - *iptr;
}
export long double modfl(long double x, long double *iptr)
{
*iptr = floorl(x);
return x - *iptr;
}
export double nan(const char *tagp)
{
return NAN;
}
export float nanf(const char *tagp)
{
return NAN;
}
export long double nanl(const char *tagp)
{
return NAN;
}
export double nearbyint(double x)
{
return round(x);
}
export float nearbyintf(float x)
{
return roundf(x);
}
export long double nearbyintl(long double x)
{
return roundl(x);
}
export double nextafter(double x, double y)
{
if (isnan(x) || isnan(y))
{
return NAN;
}
if (x == y)
{
return y;
}
if (x == 0.0)
{
return (y > 0.0) ? DBL_MIN : -DBL_MIN;
}
union
{
double d;
uint64_t u;
} ux = {x};
if ((x > 0.0) == (y > x))
{
ux.u++;
}
else
{
ux.u--;
}
return ux.d;
}
export float nextafterf(float x, float y)
{
if (isnan(x) || isnan(y))
{
return NAN;
}
if (x == y)
{
return y;
}
if (x == 0.0f)
{
return (y > 0.0f) ? FLT_MIN : -FLT_MIN;
}
union
{
float f;
uint32_t u;
} ux = {x};
if ((x > 0.0f) == (y > x))
{
ux.u++;
}
else
{
ux.u--;
}
return ux.f;
}
export long double nextafterl(long double x, long double y)
{
if (isnan(x) || isnan(y))
{
return NAN;
}
if (x == y)
{
return y;
}
if (x == 0.0L)
{
return (y > 0.0L) ? LDBL_MIN : -LDBL_MIN;
}
union
{
long double ld;
uint64_t u[2];
} ux = {x};
if ((x > 0.0L) == (y > x))
{
ux.u[0]++;
if (ux.u[0] == 0)
{
ux.u[1]++;
}
}
else
{
if (ux.u[0] == 0)
{
ux.u[1]--;
}
ux.u[0]--;
}
return ux.ld;
}
export double nexttoward(double x, long double y)
{
return nextafterl(x, y);
}
export float nexttowardf(float x, long double y)
{
return nextafterl(x, y);
}
export long double nexttowardl(long double x, long double y)
{
return nextafterl(x, y);
}
export double pow(double x, double y)
{
if (x == 0.0 && y == 0.0)
{
errno = EDOM;
return NAN;
}
return exp(y * log(x));
}
export float powf(float x, float y)
{
return (float)pow((double)x, (double)y);
}
export long double powl(long double x, long double y)
{
return (long double)pow((double)x, (double)y);
}
export double remainder(double x, double y)
{
if (y == 0.0)
{
errno = EDOM;
return NAN;
}
return x - y * round(x / y);
}
export float remainderf(float x, float y)
{
return (float)remainder((double)x, (double)y);
}
export long double remainderl(long double x, long double y)
{
return (long double)remainder((double)x, (double)y);
}
export double remquo(double x, double y, int *quo)
{
if (y == 0.0)
{
errno = EDOM;
return NAN;
}
double result = remainder(x, y);
*quo = (int)((x - result) / y);
return result;
}
export float remquof(float x, float y, int *quo)
{
return (float)remquo((double)x, (double)y, quo);
}
export long double remquol(long double x, long double y, int *quo)
{
return (long double)remquo((double)x, (double)y, quo);
}
export double rint(double x)
{
int current_rounding_mode = fegetround();
double result;
switch (current_rounding_mode)
{
case FE_TONEAREST:
result = nearbyint(x);
break;
case FE_DOWNWARD:
result = floor(x);
break;
case FE_UPWARD:
result = ceil(x);
break;
case FE_TOWARDZERO:
result = trunc(x);
break;
default:
result = nearbyint(x);
break;
}
if (result != x)
{
feraiseexcept(FE_INEXACT);
}
return result;
}
export float rintf(float x)
{
int current_rounding_mode = fegetround();
float result;
switch (current_rounding_mode)
{
case FE_TONEAREST:
result = nearbyintf(x);
break;
case FE_DOWNWARD:
result = floorf(x);
break;
case FE_UPWARD:
result = ceilf(x);
break;
case FE_TOWARDZERO:
result = truncf(x);
break;
default:
result = nearbyintf(x);
break;
}
if (result != x)
{
feraiseexcept(FE_INEXACT);
}
return result;
}
export long double rintl(long double x)
{
int current_rounding_mode = fegetround();
long double result;
switch (current_rounding_mode)
{
case FE_TONEAREST:
result = nearbyintl(x);
break;
case FE_DOWNWARD:
result = floorl(x);
break;
case FE_UPWARD:
result = ceill(x);
break;
case FE_TOWARDZERO:
result = truncl(x);
break;
default:
result = nearbyintl(x);
break;
}
if (result != x)
{
feraiseexcept(FE_INEXACT);
}
return result;
}
export double round(double x)
{
return (x < 0.0) ? ceil(x - 0.5) : floor(x + 0.5);
}
export float roundf(float x)
{
return (x < 0.0f) ? ceilf(x - 0.5f) : floorf(x + 0.5f);
}
export long double roundl(long double x)
{
return (x < 0.0L) ? ceill(x - 0.5L) : floorl(x + 0.5L);
}
export double scalb(double x, double n)
{
if (isnan(x) || isnan(n))
{
return NAN;
}
if (n == 0.0)
{
return x;
}
if (isinf(x) && !isinf(n))
{
return x;
}
if (x == 0.0 && !isinf(n))
{
return x;
}
if (x == 0.0 && isinf(n))
{
errno = EDOM;
return NAN;
}
if (isinf(x) && isinf(n))
{
errno = EDOM;
return NAN;
}
if (isinf(n))
{
return (n > 0.0) ? HUGE_VAL : 0.0;
}
if (isinf(-n))
{
return (n < 0.0) ? -HUGE_VAL : 0.0;
}
int exp = (int)n;
double result = x;
if (exp > 0)
{
while (exp > 0)
{
result *= 2.0;
exp--;
}
}
else
{
while (exp < 0)
{
result /= 2.0;
exp++;
}
}
return result;
}
export double scalbln(double x, long n)
{
return x * pow(2.0, (double)n);
}
export float scalblnf(float x, long n)
{
return x * powf(2.0f, (float)n);
}
export long double scalblnl(long double x, long n)
{
return x * powl(2.0L, (long double)n);
}
export double scalbn(double x, int n)
{
return x * pow(2.0, (double)n);
}
export float scalbnf(float x, int n)
{
return x * powf(2.0f, (float)n);
}
export long double scalbnl(long double x, int n)
{
return x * powl(2.0L, (long double)n);
}
export double sin(double x)
{
double result = 0.0;
double term = x;
double x2 = x * x;
for (int i = 1; term > DBL_EPSILON || term < -DBL_EPSILON; i += 2)
{
result += term;
term *= -x2 / ((i + 1) * (i + 2));
}
return result;
}
export float sinf(float x)
{
return (float)sin((double)x);
}
export double sinh(double x)
{
return (exp(x) - exp(-x)) / 2.0;
}
export float sinhf(float x)
{
return (float)sinh((double)x);
}
export long double sinhl(long double x)
{
return (long double)sinh((double)x);
}
export long double sinl(long double x)
{
return (long double)sin((double)x);
}
export double sqrt(double x)
{
if (x < 0.0)
{
errno = EDOM;
return NAN;
}
double result = x;
double last_result;
do
{
last_result = result;
result = (result + x / result) / 2.0;
} while (fabs(result - last_result) > DBL_EPSILON);
return result;
}
export float sqrtf(float x)
{
return (float)sqrt((double)x);
}
export long double sqrtl(long double x)
{
return (long double)sqrt((double)x);
}
export double tan(double x)
{
return sin(x) / cos(x);
}
export float tanf(float x)
{
return (float)tan((double)x);
}
export double tanh(double x)
{
return (exp(x) - exp(-x)) / (exp(x) + exp(-x));
}
export float tanhf(float x)
{
return (float)tanh((double)x);
}
export long double tanhl(long double x)
{
return (long double)tanh((double)x);
}
export long double tanl(long double x)
{
return (long double)tan((double)x);
}
export double tgamma(double x)
{
if (x <= 0.0 && floor(x) == x)
{
errno = EDOM;
return NAN;
}
double result = 1.0;
if (x < 0.5)
{
return M_PI / (sin(M_PI * x) * tgamma(1.0 - x));
}
x -= 1.0;
double coefficients[] = {
1.000000000190015,
76.18009172947146,
-86.50532032941677,
24.01409824083091,
-1.231739572450155,
0.001208650973866179,
-0.000005395239384953};
double y = x + 5.5;
y -= (x + 0.5) * log(y);
for (int i = 0; i < 7; i++)
{
result += coefficients[i] / (x + i + 1);
}
return sqrt(2.0 * M_PI) * pow(x + 5.5, x + 0.5) * exp(-y) * result;
}
export float tgammaf(float x)
{
return (float)tgamma((double)x);
}
export long double tgammal(long double x)
{
return (long double)tgamma((double)x);
}
export double trunc(double x)
{
return (x < 0.0) ? ceil(x) : floor(x);
}
export float truncf(float x)
{
return (x < 0.0f) ? ceilf(x) : floorf(x);
}
export long double truncl(long double x)
{
return (x < 0.0L) ? ceill(x) : floorl(x);
}
export double y0(double x)
{
if (x < 8.0)
{
double y = x * x;
double ans1 = -2957821389.0 + y * (7062834065.0 + y * (-512359803.6 + y * (10879881.29 + y * (-86327.92757 + y * 228.4622733))));
double ans2 = 40076544269.0 + y * (745249964.8 + y * (7189466.438 + y * (47447.26470 + y * (226.1030244 + y * 1.0))));
return (ans1 / ans2) + 0.636619772 * j0(x) * log(x);
}
else
{
double z = 8.0 / x;
double y = z * z;
double xx = x - 0.785398164;
double ans1 = 1.0 + y * (-0.1098628627e-2 + y * (0.2734510407e-4 + y * (-0.2073370639e-5 + y * 0.2093887211e-6)));
double ans2 = -0.1562499995e-1 + y * (0.1430488765e-3 + y * (-0.6911147651e-5 + y * (0.7621095161e-6 - y * 0.934935152e-7)));
return sqrt(0.636619772 / x) * (sin(xx) * ans1 + z * cos(xx) * ans2);
}
}
export double y1(double x)
{
if (x < 8.0)
{
double y = x * x;
double ans1 = x * (-0.4900604943e13 + y * (0.1275274390e13 + y * (-0.5153438139e11 + y * (0.7349264551e9 + y * (-0.4237922726e7 + y * 0.8511937935e4)))));
double ans2 = 0.2499580570e14 + y * (0.4244419664e12 + y * (0.3733650367e10 + y * (0.2245904002e8 + y * (0.1020426050e6 + y * (0.3549632885e3 + y)))));
return (ans1 / ans2) + 0.636619772 * (j1(x) * log(x) - 1.0 / x);
}
else
{
double z = 8.0 / x;
double y = z * z;
double xx = x - 2.356194491;
double ans1 = 1.0 + y * (0.183105e-2 + y * (-0.3516396496e-4 + y * (0.2457520174e-5 + y * (-0.240337019e-6))));
double ans2 = 0.04687499995 + y * (-0.2002690873e-3 + y * (0.8449199096e-5 + y * (-0.88228987e-6 + y * 0.105787412e-6)));
return sqrt(0.636619772 / x) * (sin(xx) * ans1 + z * cos(xx) * ans2);
}
}
export double yn(int n, double x)
{
if (n == 0)
return y0(x);
if (n == 1)
return y1(x);
if (x == 0.0)
return -HUGE_VAL;
if (x < 0.0)
return NAN;
double tox = 2.0 / x;
double by, bym, byp;
int j;
bym = y0(x);
by = y1(x);
for (j = 1; j < n; j++)
{
byp = j * tox * by - bym;
bym = by;
by = byp;
}
return by;
}
void sincos(double x, double *s, double *c)
{
*s = sin(x);
*c = cos(x);
}
void sincosf(float x, float *s, float *c)
{
*s = sinf(x);
*c = cosf(x);
}
void sincosl(long double x, long double *s, long double *c)
{
*s = sinl(x);
*c = cosl(x);
}