Implemented math.h

This commit is contained in:
2024-10-24 12:00:36 +02:00
parent f163659f0c
commit a797d4366a
13 changed files with 423 additions and 44 deletions
+61 -8
View File
@@ -2,15 +2,68 @@
#define _MATH_H
// Constants
#define PI 3.141592653589 // Should be good enough
#define E 2.718281828459
#define M_E 2.71828182845904523536 // e
#define M_LOG2E 1.44269504088896340736 // log_2 e
#define M_LOG10E 0.43429448190325182765 // log_10 e
#define M_LN2 0.69314718055994530941 // ln(2)
#define M_LN10 2.30258509299404568402 // ln(10)
#define M_PI 3.14159265358979323846 // pi
#define M_PI_2 1.57079632679489661923 // pi/2
#define M_PI_4 0.78539816339744830961 // pi/4
#define M_1_PI 0.31830988618379067153 // 1/pi
#define M_2_PI 0.63661977236758134307 // 2/pi
#define M_SQRT2 1.41421356237309504880 // sqrt(2)
#define M_SQRT1_2 0.70710678118654752440 // 1/sqrt(2)
// Macros
#define abs(x) ( (x) > 0 ? (x) : -(x) )
#define sign(x) ( (x) == 0 ? 0 : ((x) < 0 ? -1 : 1 ) )
// TODO:
#define NAN (__builtin_inff())
#define INFINITY (__builtin_nanf(""))
#define floor(x) ( (int)(x) ) // C floors floats when converting to ints
#define round(x) ( (int)((x) + 0.5) ) // Normal rounding
#define ceil(x) ( (int)((x) + 1) ) // Always rounds up
// Absolute value
int abs(int n);
double fabs(double n);
// Exponential & logarithmic
double exp(double x);
double exp2(double x);
double log(double x);
double log2(double x);
double log10(double x);
double logn(double x, double n);
// Power
double sqrt(double x);
double cbrt(double x);
double hypot(double x, double y);
double pow(double base, double expn);
// Trigonometric
double sin(double x);
double cos(double x);
double tan(double x);
double asin(double x);
double acos(double x);
double atan(double x);
double atan2(double y, double x);
// Hyperbolic
double sinh(double x);
double cosh(double x);
double tanh(double x);
// Rounding & remainder
double floor(double x);
double ceil(double x);
double round(double x);
double trunc(double x);
double fmod(double x, double y);
double modf(double x, double* iptr);
// Error handling
double nan(const char* tagp);
double inf();
int isfinite(double x);
int isinf(double x);
int isnan(double x);
#endif
+3 -3
View File
@@ -6,15 +6,15 @@
#define MAX_SYSCALLS 9
typedef enum {
SYS_RESERVED,
SYS_SLEEP,
SYS_EXIT,
SYS_READ,
SYS_WRITE,
SYS_OPEN,
SYS_CLOSE,
SYS_SEEK,
SYS_MALLOC,
SYS_FREE,
SYS_SEEK,
SYS_SLEEP,
} SYSCALL_NUMBERS;
typedef enum {
+10
View File
@@ -0,0 +1,10 @@
#include <math.h>
int abs(int n) {
return (n < 0) ? -n : n;
}
double fabs(double x) {
return (x < 0.0) ? -x : x;
}
+43
View File
@@ -0,0 +1,43 @@
#include <math.h>
double nan(const char* tagp) {
(void)tagp;
// Create a NaN bit pattern in IEEE 754
uint64_t nanBits = 0x7ff8000000000000ULL;
double result;
memcpy(&result, &nanBits, sizeof(result));
return result;
}
double inf() {
// Create an infinity bit pattern in IEEE 754
uint64_t infBits = 0x7ff0000000000000ULL;
double result;
memcpy(&result, &infBits, sizeof(result));
return result;
}
int isfinite(double x) {
uint64_t bits;
memcpy(&bits, &x, sizeof(bits));
uint64_t exponent = (bits >> 52) & 0x7ff;
return exponent != 0x7ff;
}
int isinf(double x) {
uint64_t bits;
memcpy(&bits, &x, sizeof(bits));
uint64_t exponent = (bits >> 52) & 0x7ff;
uint64_t mantissa = bits & 0xfffffffffffff;
return (exponent == 0x7ff && mantissa == 0);
}
int isnan(double x) {
uint64_t bits;
memcpy(&bits, &x, sizeof(bits));
uint64_t exponent = (bits >> 52) & 0x7ff;
uint64_t mantissa = bits & 0xfffffffffffff;
return (exponent == 0x7ff && mantissa != 0);
}
+46
View File
@@ -0,0 +1,46 @@
#include <math.h>
#define _EXP_TAYLOR_TERMS 10
#define _EXP2_TAYLOR_TERMS 5
double exp(double x) {
if (x == 0.0) return 1.0;
if (x < 0.0) return 1.0 / exp(-x);
double sum = 1.0; // Result
double term = 1.0; // Curent term in the series
/*
Calculate the Taylor series:
e^x = 1 + x + x^2/2! + x^3/3! + ...
*/
for (int i = 1; i < _EXP_TAYLOR_TERMS; i++) {
term *= x / (double)i;
sum += term;
}
return sum;
}
double exp2(double x) {
if (x == 0.0) return 1.0;
if (x < 0.0) return 1.0 / exp2(-x);
int n = (int)x; // Integer part
double frac = x - n;// Fractional part
// Integer power of 2
double result = (double)(1 << n); // 2^n is just 1 << n
// Approximate the fractional part
double sum = 1.0;
double term = frac;
for (int i = 1; i < _EXP2_TAYLOR_TERMS; i++) {
sum += term;
term *= frac / (i+1);
}
return result * sum;
}
+16
View File
@@ -0,0 +1,16 @@
#include <math.h>
double sinh(double x) {
return (exp(x) - exp(-x)) / 2.0;
}
double cosh(double x) {
return (exp(x) + exp(-x)) / 2.0;
}
double tanh(double x) {
double ex = exp(x);
double emx = exp(-x);
return (ex - exp) / (ex + exp);
}
+35
View File
@@ -0,0 +1,35 @@
#include <math.h>
#define _LOG_TERMS 20
double log(double x) {
if (x <= 0.0) return -INFINITY;
double result = 0.0;
double term = (x - 1.0) / (x + 1.0);
double termSquared = term*term;
double numerator = term;
for (int i = 1; i < _LOG_TERMS; i++) {
result += numerator / (double)i;
numerator *= termSquared;
}
return 2.0 * result;
}
double log2(double x) {
if (x <= 0.0) return -INFINITY;
return log(x) / M_LN2;
}
double log10(double x) {
if (x <= 0.0) return -INFINITY;
return log(x) / M_LN10;
}
double logn(double x, double n) {
if (x <= 0.0) return -INFINITY;
return log(x) / log(n);
}
+42
View File
@@ -0,0 +1,42 @@
#include <math.h>
#define _POW_LOOP_MAX 60
double sqrt(double x) {
if (x < 0.0) return -NAN;
double result = x;
double oldResult = 0.0;
while (result != oldResult) {
oldResult = result;
result = 0.5 * (result + x/result);
}
return result;
}
double cbrt(double x) {
double result = x;
double oldResult = 0.0;
while (result != oldResult) {
oldResult = result;
result = (2.0 * result + x/(result * result)) / 3.0;
}
return result;
}
double hypot(double x, double y) {
return sqrt(x*x + y*y);
}
double pow(double base, double expn) { // exp is a function so we have to use expn
if (base == 0.0 && expn == 0.0) return NAN;
if (base == 0.0) return 0.0;
if (expn == 0.0) return 1.0;
return exp(expn * log(base));
}
+46
View File
@@ -0,0 +1,46 @@
#include <math.h>
double round(double x) {
double res;
__asm__ volatile (
"fldl %1\n" // Load x to the FPU stack
"frndint\n" // Round to nearest integer
"fstpl %0" // Store result
: "=m"(res)
: "m"(x)
);
if ((x - res) == 0.5 || (x - res) == -0.5) {
// Halfway cases: round away from zero
res += (x > 0) ? 1.0 : -1.0;
}
return res;
}
double floor(double x) {
double res = round(x);
if (res > x) { res -= 1.0; }
return res;
}
double ceil(double x){
double res = round(x);
if (res < x) { res += 1.0; }
return res;
}
double trunc(double x) {
double res = round(x);
if (x < 0 && x != res) { res -= 1.0; }
return res;
}
double fmod(double x, double y) {
return x - y * floor(x / y);
}
double modf(double x, double* iptr) {
double whole = trunc(x);
*iptr = whole;
return x - whole;
}
+61
View File
@@ -0,0 +1,61 @@
#include <math.h>
double sin(double x) {
double res;
__asm__ volatile (
"fldl %1\n" // Load x to the FPU stack
"fsin\n" // Compute sin(x)
"fstpl %0" // Store result
: "=m"(res) : "m"(x)
);
return res;
}
double cos(double x) {
double res;
__asm__ volatile (
"fldl %1\n" // Load x to the FPU stack
"fcos\n" // Compute cos(x)
"fstpl %0" // Store result
: "=m"(res) : "m"(x)
);
return res;
}
double tan(double x) {
return sin(x) / cos(x);
}
double asin(double x) {
return atan2(x, sqrt(1 - x*x));
}
double acos(double x) {
return M_PI_2 - asin(x);
}
double atan(double x) {
double res;
__asm__ volatile (
"fld1\n" // Load 1.0 to the FPU stack
"fldl %1\n" // Load x to the FPU stack
"fpatan\n" // Compute atan(x)
"fstpl %0" // Store result
: "=m"(res) : "m"(x)
);
return res;
}
double atan2(double y, double x) {
double res;
__asm__ volatile (
"fldl %2\n" // Load x to the FPU stack
"fldl %1\n" // Load y to the FPU stack
"fpatan\n" // Compute atan2(y, x)
"fstpl %0" // Store the result
: "=m"(res) : "m"(y), "m"(x)
);
return res;
}