185 lines
3.9 KiB
C
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));
|
|
}
|