math generic exp function

This commit is contained in:
bumbread 2022-06-16 21:51:55 +11:00
parent 9df9a57b67
commit cca63462fc
7 changed files with 84 additions and 10 deletions

View File

@ -51,5 +51,5 @@ del build\*.obj
:skip_crt_compilation :skip_crt_compilation
echo Compiling test.. echo Compiling test..
clang -fno-builtin test\test_wctype.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS% clang -fno-builtin test\test_math.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS%
::cl test\test_math.c /Iinc -D_CRT_SECURE_NO_WARNINGS /Z7 /link ciabatta.lib kernel32.lib user32.lib shell32.lib -nostdlib -nodefaultlibs ::cl test\test_math.c /Iinc -D_CRT_SECURE_NO_WARNINGS /Z7 /link ciabatta.lib kernel32.lib user32.lib shell32.lib -nostdlib -nodefaultlibs

View File

@ -1,8 +0,0 @@
#include <math.h>
#include <stdint.h>
#include <float.h>
#include <fenv.h>
#define rln2 1.4426950408889634073599246810018921374266459541529859341354494069

25
code/math/generic.c Normal file
View File

@ -0,0 +1,25 @@
#include <math.h>
#include <fenv.h>
#include <errno.h>
#include <stdint.h>
#define ln2 0.69314718055994530941723212145817
#define ftype float
#define suffix(name) name ## f
#include "generic.h"
#undef ftype
#undef suffix
#define ftype double
#define suffix(name) name
#include "generic.h"
#undef ftype
#undef suffix
#define ftype long double
#define suffix(name) name ## l
#include "generic.h"
#undef ftype
#undef suffix

42
code/math/generic.h Normal file
View File

@ -0,0 +1,42 @@
ftype suffix(exp)(ftype x) {
if(isnan(x)) return NAN;
if(x > 0 && isinf(x)) return +INFINITY;
if(x < 0 && isinf(x)) return +0.0;
if(x == 0) return 1.0;
if(x > 709.8) {
#if math_errhandling & MATH_ERREXCEPT
feraiseexcept(FE_OVERFLOW);
#endif
#if math_errhandling & MATH_ERRNO
errno = ERANGE;
#endif
return +INFINITY;
}
if(x < -708.4) {
#if math_errhandling & MATH_ERREXCEPT
feraiseexcept(FE_OVERFLOW);
#endif
#if math_errhandling & MATH_ERRNO
errno = ERANGE;
#endif
return 0;
}
ftype e = 1.0;
ftype xp = 1.0;
ftype f = 1;
for(uint64_t i = 1; i != 10; ++i) {
f *= i;
xp *= x;
e += xp / f;
}
return e;
}
ftype suffix(exp2)(ftype x) {
return suffix(exp)(x * ln2);
}
ftype suffix(expm1)(ftype x) {
return suffix(exp)(x) - 1.0;
}

View File

@ -4,6 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include <limits.h> #include <limits.h>
#include <string.h> #include <string.h>
#include <math.h>
// This stuff is kinda related to what's going on in this file, so I left it // This stuff is kinda related to what's going on in this file, so I left it
// in a rather ugly manner here. // in a rather ugly manner here.

View File

@ -20,7 +20,7 @@ typedef double double_t;
#define MATH_ERRNO 1 #define MATH_ERRNO 1
#define MATH_ERREXCEPT 2 #define MATH_ERREXCEPT 2
#define math_errhandling MATH_ERRNO #define math_errhandling MATH_ERRNO | MATH_ERREXCEPT
// Classification // Classification
#define FP_INFINITE 0 #define FP_INFINITE 0

View File

@ -4,6 +4,7 @@
#include <float.h> #include <float.h>
#include <fenv.h> #include <fenv.h>
#include <inttypes.h> #include <inttypes.h>
#include <errno.h>
const char *show_classification(double x) { const char *show_classification(double x) {
switch(fpclassify(x)) { switch(fpclassify(x)) {
@ -103,5 +104,18 @@ int main() {
printf("lround(LONG_MAX+1.5) = %ld\n", lround(LONG_MAX+1.5)); printf("lround(LONG_MAX+1.5) = %ld\n", lround(LONG_MAX+1.5));
if(fetestexcept(FE_INVALID)) printf(" FE_INVALID was raised\n"); if(fetestexcept(FE_INVALID)) printf(" FE_INVALID was raised\n");
printf("\n\n=== exp === \n");
printf("exp(1) = %f\n", exp(1));
printf("FV of $100, continuously compounded at 3%% for 1 year = %f\n",
100*exp(0.03));
// special values
printf("exp(-0) = %f\n", exp(-0.0));
printf("exp(-Inf) = %f\n", exp(-INFINITY));
//error handling
errno = 0; feclearexcept(FE_ALL_EXCEPT);
printf("exp(710) = %f\n", exp(710));
if(errno == ERANGE) printf(" errno == ERANGE\n");
if(fetestexcept(FE_OVERFLOW)) printf(" FE_OVERFLOW raised\n");
return 0; return 0;
} }