Files
MentOS/libc/src/math.c
T
Enrico Fraccaroli (Galfurian) 30e01ba560 Update version
2024-01-17 13:49:48 +01:00

185 lines
3.9 KiB
C

/// @file math.c
/// @brief
/// @copyright (c) 2014-2024 This file is distributed under the MIT License.
/// See LICENSE.md for details.
#include "math.h"
#include "stdint.h"
double round(double x)
{
double out;
__asm__ __volatile__("fldln2; fldl %1; frndint"
: "=t"(out)
: "m"(x));
return out;
}
double floor(double x)
{
if (x > -1.0 && x < 1.0) {
if (x >= 0) {
return 0.0;
}
return -1.0;
}
int i = (int)x;
if (x < 0) {
return (double)(i - 1);
}
return (double)i;
}
double ceil(double x)
{
if (x > -1.0 && x < 1.0) {
if (x <= 0) {
return 0.0;
}
return 1.0;
}
int i = (int)x;
if (x > 0) {
return (double)(i + 1);
}
return (double)i;
}
double pow(double base, double exponent)
{
double out;
__asm__ __volatile__("fyl2x;"
"fld %%st;"
"frndint;"
"fsub %%st,%%st(1);"
"fxch;"
"fchs;"
"f2xm1;"
"fld1;"
"faddp;"
"fxch;"
"fld1;"
"fscale;"
"fstp %%st(1);"
"fmulp;"
: "=t"(out)
: "0"(base), "u"(exponent)
: "st(1)");
return out;
}
double exp(double x)
{
return pow(M_E, x);
}
double fabs(double x)
{
double out;
__asm__ __volatile__("fldln2; fldl %1; fabs"
: "=t"(out)
: "m"(x));
return out;
}
float fabsf(float x)
{
float out;
__asm__ __volatile__("fldln2; fldl %1; fabs"
: "=t"(out)
: "m"(x));
return out;
}
double sqrt(double x)
{
double out;
__asm__ __volatile__("fldln2; fldl %1; fsqrt"
: "=t"(out)
: "m"(x));
return out;
}
float sqrtf(float x)
{
float out;
__asm__ __volatile__("fldln2; fldl %1; fsqrt"
: "=t"(out)
: "m"(x));
return out;
}
int isinf(double x)
{
union {
unsigned long long u;
double f;
} ieee754;
ieee754.f = x;
return ((unsigned)(ieee754.u >> 32U) & 0x7fffffffU) == 0x7ff00000U &&
((unsigned)ieee754.u == 0);
}
int isnan(double x)
{
union {
unsigned long long u;
double f;
} ieee754;
ieee754.f = x;
return ((unsigned)(ieee754.u >> 32) & 0x7fffffff) +
((unsigned)ieee754.u != 0) >
0x7ff00000;
}
double log10(double x)
{
return ln(x) / ln(10);
}
double ln(double x)
{
double out;
__asm__ __volatile__("fldln2; fldl %1; fyl2x"
: "=t"(out)
: "m"(x));
return out;
}
double logx(double x, double y)
{
// Base may not equal 1 or be negative.
if (y == 1.f || y < 0.f || ln(y) == 0.f) {
return 0.f;
}
return ln(x) / ln(y);
}
/// Max power for forward and reverse projections.
#define MAXPOWTWO 4.503599627370496000E+15
double modf(double x, double *intpart)
{
register double absvalue;
if ((absvalue = (x >= 0.0) ? x : -x) >= MAXPOWTWO) {
// It must be an integer.
(*intpart) = x;
} else {
// Shift fraction off right.
(*intpart) = absvalue + MAXPOWTWO;
// Shift back without fraction.
(*intpart) -= MAXPOWTWO;
// Above arithmetic might round.
while ((*intpart) > absvalue) {
// Test again just to be sure.
(*intpart) -= 1.0;
}
if (x < 0.0) {
(*intpart) = -(*intpart);
}
}
// Signed fractional part.
return (x - (*intpart));
}