217 lines
3.9 KiB
C
217 lines
3.9 KiB
C
|
#include <stdlib.h>
|
||
|
#include <stdint.h>
|
||
|
#include <math.h>
|
||
|
#include "internal.h"
|
||
|
|
||
|
unsigned int _libc_rand_seed = 12345;
|
||
|
|
||
|
int rand() {
|
||
|
_libc_rand_seed ^= _libc_rand_seed << 13;
|
||
|
_libc_rand_seed ^= _libc_rand_seed >> 17;
|
||
|
_libc_rand_seed ^= _libc_rand_seed << 5;
|
||
|
return _libc_rand_seed % (RAND_MAX+1);
|
||
|
}
|
||
|
|
||
|
void srand(unsigned int r) {
|
||
|
if (r == 0) {
|
||
|
_libc_rand_seed = 1;
|
||
|
} else {
|
||
|
_libc_rand_seed = r;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double fabs(double n) {
|
||
|
if (n < 0) {
|
||
|
return 0.0 - n;
|
||
|
} else {
|
||
|
return n;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
double ldexp(double x, int exp) {
|
||
|
UNIMPLEMENTED();
|
||
|
}
|
||
|
|
||
|
double frexp(double x, int* expptr) {
|
||
|
// TODO: Check special cases?
|
||
|
uint64_t bits = *((uint64_t*)((void*)&x));
|
||
|
uint64_t exp = (bits>>52)&0x7FF;
|
||
|
*expptr = (int) exp - 1023;
|
||
|
bits &= 0x800FFFFFFFFFFFFFULL;
|
||
|
bits |= 1023ULL << 52;
|
||
|
return *((double*)((void*)&bits));
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
double _libc_factorial(int n) {
|
||
|
double x = 1.0;
|
||
|
for (int i = 1; i <= n; i++) {
|
||
|
x *= i;
|
||
|
}
|
||
|
return x;
|
||
|
}
|
||
|
|
||
|
// This implementation is very very dumb.
|
||
|
double pow(double x, double p) {
|
||
|
double result = x;
|
||
|
for (int i = 2; i < p; i++) {
|
||
|
result *= x;
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
#define EXP_EPSILON 0.0000000001
|
||
|
|
||
|
// NOTE: This function was written with the help of Qwen AI
|
||
|
double exp(double x) {
|
||
|
double r = 1.0;
|
||
|
double t = 1.0;
|
||
|
int n = 1;
|
||
|
|
||
|
while (fabs(t) < EXP_EPSILON) {
|
||
|
t = pow(x, n) / _libc_factorial(n);
|
||
|
r += t;
|
||
|
n++;
|
||
|
}
|
||
|
|
||
|
return r;
|
||
|
}
|
||
|
*/
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
// NOTE: OLD CODE taken from PDPC400's math.c ("public domain")
|
||
|
////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
#define HUGE_VAL 9.999999999999999999999E72
|
||
|
|
||
|
/*
|
||
|
|
||
|
Some constants to make life easier elsewhere
|
||
|
(These should I guess be in math.h)
|
||
|
|
||
|
*/
|
||
|
double _libc_pi = 3.1415926535897932384626433832795;
|
||
|
double _libc_ln10 = 2.3025850929940456840179914546844;
|
||
|
double _libc_ln2 = 0.69314718055994530941723212145818;
|
||
|
|
||
|
/*
|
||
|
|
||
|
exp(x) = 1 + x + x2/2 + x3/6 + x4/24 + x5/120 + ... + xn/n! + ...
|
||
|
|
||
|
*/
|
||
|
double exp (double x)
|
||
|
{
|
||
|
int i;
|
||
|
double term,answer,work;
|
||
|
|
||
|
i=2;
|
||
|
term=x;
|
||
|
answer=x;
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
work = i;
|
||
|
term = (term * x)/work;
|
||
|
if ( answer == (answer + term) )break;
|
||
|
answer = answer + (term);
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
answer=answer+1.0;
|
||
|
return(answer);
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
|
||
|
Calculate LOG using Taylor series.
|
||
|
|
||
|
log(1+ x) = x - x**2 + x**3 - x**4 + x**5
|
||
|
==== ==== ==== ==== .........
|
||
|
2 3 4 8
|
||
|
|
||
|
Note this only works for small x so we scale....
|
||
|
|
||
|
*/
|
||
|
double log (double x)
|
||
|
{
|
||
|
int i,scale;
|
||
|
double term,answer,work,xs;
|
||
|
|
||
|
if (x <= 0 )
|
||
|
{
|
||
|
/* need to set signal */
|
||
|
// TODO: Proper errno errno=EDOM;
|
||
|
return (HUGE_VAL);
|
||
|
}
|
||
|
if( x == 1.0)return(0.0);
|
||
|
|
||
|
/*
|
||
|
Scale arguments to be in range 1 < x <= 10
|
||
|
*/
|
||
|
|
||
|
/*
|
||
|
scale = 0;
|
||
|
xs = x;
|
||
|
while ( xs > 10.0 ) { scale ++; xs=xs/10.0;}
|
||
|
while ( xs < 1.0 ) { scale --; xs=xs*10.0;}
|
||
|
*/
|
||
|
xs = frexp(x,&scale);
|
||
|
xs = (1.0 * xs) - 1.0;
|
||
|
scale = scale - 0;
|
||
|
|
||
|
i=2;
|
||
|
term=answer=xs;
|
||
|
|
||
|
while (1)
|
||
|
{
|
||
|
work = i;
|
||
|
term = - (term * xs);
|
||
|
if ( answer == (answer + (term/work)) )break;
|
||
|
answer = answer + (term/work);
|
||
|
i++;
|
||
|
}
|
||
|
|
||
|
answer = answer + (double)scale * _libc_ln2;
|
||
|
return(answer);
|
||
|
}
|
||
|
|
||
|
|
||
|
double log10(double x)
|
||
|
{
|
||
|
return ( log(x) / _libc_ln10 );
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
|
||
|
This code uses log and exp to calculate x to the power y.
|
||
|
If
|
||
|
|
||
|
*/
|
||
|
|
||
|
double pow(double x,double y)
|
||
|
{
|
||
|
int j,neg;
|
||
|
double yy,xx;
|
||
|
neg=0;
|
||
|
j=y;
|
||
|
yy=j;
|
||
|
if( yy == y) {
|
||
|
xx = x;
|
||
|
if ( y < 0 ){neg = 1; j = -j;}
|
||
|
if ( y == 0) return (1.0);
|
||
|
--j;
|
||
|
while(j>0){ xx=xx * x; j--;}
|
||
|
if(neg)xx=1.0/xx;
|
||
|
return (xx);
|
||
|
}
|
||
|
if (x < 0.0)
|
||
|
{
|
||
|
// TODO: Proper errno errno=EDOM;
|
||
|
return(0.0);
|
||
|
}
|
||
|
if (y == 0.0) return (1.0);
|
||
|
|
||
|
return (exp(y*log(x)));
|
||
|
}
|