diff --git a/bake.cmd b/bake.cmd index f4d0712..fd28549 100644 --- a/bake.cmd +++ b/bake.cmd @@ -1,54 +1,55 @@ -@echo off -setlocal enabledelayedexpansion - -:: Make sure that if I ctrl+c out of the script the dir is popped -:: If there's anything that requires user input, this script will break -:: in that case I recommend you removing the 'echo y' part. -:: although you will have to confirm termination of the script twice -if "%~1" neq "_start_" ( - pushd %~pd0 - echo y | cmd /c "%~f0" _start_ %* - popd - exit /b -) -shift /1 - -set CIABATTA_OPTIONS=-Iinc -Wall -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS -set PLATFORM=win - -if "%1"=="test" ( - goto :skip_crt_compilation -) -:: For each C file in code/ we check whether it's OS-dependent. -:: If so, we check whether the platform is the chosen one. If not, we ignore -:: that file (set ok=0). Otherwise we compile it. -:: Man, batch files are sure scary, when you try to do something serious -:: it took me a lot of time to figure out how to write this if it breaks -:: im gonna be seriously disappointed :kekw: -del ciabatta.lib 2> nul -for /R code %%F in (*.c) do ( - set ok=1 - set os_dependent=0 - set is_cur_os=0 - echo %%F | findstr /c:"%~pd0code\os" > nul - if !errorlevel! neq 1 ( - set os_dependent=1 - ) - echo %%F | findstr /c:"%~pd0code\os\%PLATFORM%" > nul - if !errorlevel! neq 1 ( - set is_cur_os=1 - ) - if "!os_dependent!"=="1" if "!is_cur_os!"=="0" ( - set ok=0 - ) - if "!ok!"=="1" ( - echo %%F - clang -c -o build\%%~nF.obj %%F %CIABATTA_OPTIONS% - ) -) -llvm-ar rc ciabatta.lib build\*.obj -del build\*.obj - -:skip_crt_compilation -echo Compiling test.. -clang test\test6.c ciabatta.lib -std=c11 -lkernel32 -luser32 -lshell32 -nostdlib %CIABATTA_OPTIONS% +@echo off +setlocal enabledelayedexpansion + +:: Make sure that if I ctrl+c out of the script the dir is popped +:: If there's anything that requires user input, this script will break +:: in that case I recommend you removing the 'echo y' part. +:: although you will have to confirm termination of the script twice +if "%~1" neq "_start_" ( + pushd %~pd0 + echo y | cmd /c "%~f0" _start_ %* + popd + exit /b +) +shift /1 + +set CIABATTA_OPTIONS=-Iinc -Wall -g -gcodeview -nodefaultlibs -D_CRT_SECURE_NO_WARNINGS +set PLATFORM=win + +if "%1"=="test" ( + goto :skip_crt_compilation +) +:: For each C file in code/ we check whether it's OS-dependent. +:: If so, we check whether the platform is the chosen one. If not, we ignore +:: that file (set ok=0). Otherwise we compile it. +:: Man, batch files are sure scary, when you try to do something serious +:: it took me a lot of time to figure out how to write this if it breaks +:: im gonna be seriously disappointed :kekw: +del ciabatta.lib 2> nul +for /R code %%F in (*.c) do ( + set ok=1 + set os_dependent=0 + set is_cur_os=0 + echo %%F | findstr /c:"%~pd0code\os" > nul + if !errorlevel! neq 1 ( + set os_dependent=1 + ) + echo %%F | findstr /c:"%~pd0code\os\%PLATFORM%" > nul + if !errorlevel! neq 1 ( + set is_cur_os=1 + ) + if "!os_dependent!"=="1" if "!is_cur_os!"=="0" ( + set ok=0 + ) + if "!ok!"=="1" ( + echo %%F + clang -c -o build\%%~nF.obj %%F %CIABATTA_OPTIONS% + ) +) +llvm-ar rc ciabatta.lib build\*.obj +del build\*.obj + +:skip_crt_compilation +echo Compiling test.. +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 diff --git a/build_cuik.cmd b/build_cuik.cmd index 6d6560c..c076edb 100644 --- a/build_cuik.cmd +++ b/build_cuik.cmd @@ -1,12 +1,12 @@ -@echo off -setlocal enabledelayedexpansion - -set PLATFORM=win -set CIABATTA_OPTIONS=--crt none -I %% -I inc - -del ciabatta.lib -cuik %CIABATTA_OPTIONS% code\*.c code\os\%PLATFORM%\*.c -c -o ciabatta.obj -lib /out:ciabatta.lib ciabatta.obj - -cuik test\test.c --lib ciabatta.lib,kernel32.lib,user32.lib,shell32.lib %CIABATTA_OPTIONS% -del ciabatta.obj +@echo off +setlocal enabledelayedexpansion + +set PLATFORM=win +set CIABATTA_OPTIONS=--crt none -I %% -I inc + +del ciabatta.lib +cuik %CIABATTA_OPTIONS% code\*.c code\os\%PLATFORM%\*.c -c -o ciabatta.obj +lib /out:ciabatta.lib ciabatta.obj + +cuik test\test.c --lib ciabatta.lib,kernel32.lib,user32.lib,shell32.lib %CIABATTA_OPTIONS% +del ciabatta.obj diff --git a/code/math/basic.h b/code/math/basic.h deleted file mode 100644 index e69de29..0000000 diff --git a/code/math/exp.h b/code/math/exp.h deleted file mode 100644 index e69de29..0000000 diff --git a/code/math/ieee754.c b/code/math/ieee754.c new file mode 100644 index 0000000..e214731 --- /dev/null +++ b/code/math/ieee754.c @@ -0,0 +1,264 @@ + +#include +#include +#include +#include + +#include <_compiler.h> +#if defined(_compiler_clang) || defined(_compiler_gnu) + #define just_do_it(t) __attribute__((unused)) volatile t +#endif + + +int _fpclassify(double x) { + union {double f; uint64_t i;} u = {x}; + int e = u.i>>52 & 0x7ff; + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; + if (e==0x7ff) return u.i<<12 ? FP_NAN : FP_INFINITE; + return FP_NORMAL; +} + +int _fpclassifyf(float x) { + union {float f; uint32_t i;} u = {x}; + int e = u.i>>23 & 0xff; + if (!e) return u.i<<1 ? FP_SUBNORMAL : FP_ZERO; + if (e==0xff) return u.i<<9 ? FP_NAN : FP_INFINITE; + return FP_NORMAL; +} + +int _fpclassifyl(long double x) { + return _fpclassify(x); +} + + +int _signbit(double x) { + union { + double d; + uint64_t i; + } y = { x }; + return y.i>>63; +} + +int _signbitf(float x) { + union { + float f; + uint32_t i; + } y = { x }; + return y.i>>31; +} + +int _signbitl(long double x) { + return _signbit(x); +} + +double copysign(double x, double y) { + union {double f; uint64_t i;} ux={x}, uy={y}; + ux.i &= ~(1ULL<<63); + ux.i |= uy.i & (1ULL<<63); + return ux.f; +} + +float copysignf(float x, float y) { + union {float f; uint32_t i;} ux={x}, uy={y}; + ux.i &= 0x7fffffff; + ux.i |= uy.i & 0x80000000; + return ux.f; +} + +long double copysignl(long double x, long double y) { + return copysign(x, y); +} + +double nan(const char *s) { + return NAN; +} + +float nanf(const char *s) { + return NAN; +} + +long double nanl(const char *s) { + return NAN; +} + + +double rint(double x) { + static const double_t toint = 1/DBL_EPSILON; + union {double f; uint64_t i;} u = {x}; + int e = u.i>>52 & 0x7ff; + int s = u.i>>63; + double y; + if (e >= 0x3ff+52) return x; + if (s) y = x - toint + toint; + else y = x + toint - toint; + if (y == 0) return s ? -0.0 : +0.0; + return y; +} + +float rintf(float x) { + static const float toint = 1/FLT_EPSILON; + union {float f; uint32_t i;} u = {x}; + int e = u.i>>23 & 0xff; + int s = u.i>>31; + float y; + if (e >= 0x7f+23) return x; + if (s) y = x - toint + toint; + else y = x + toint - toint; + if (y == 0) return s ? -0.0f : 0.0f; + return y; +} + +long double rintl(long double x) { + return rint(x); +} + + +double nearbyint(double x) { + #pragma STDC FENV_ACCESS ON + int e = fetestexcept(FE_INEXACT); + x = rint(x); + if (!e) feclearexcept(FE_INEXACT); + return x; +} + +float nearbyintf(float x) { + #pragma STDC FENV_ACCESS ON + int e = fetestexcept(FE_INEXACT); + x = rintf(x); + if (!e) feclearexcept(FE_INEXACT); + return x; +} + +long double nearbyintl(long double x) { + return nearbyint(x); +} + + +double nextafter(double x, double y) { + union {double f; uint64_t i;} ux={x}, uy={y}; + uint64_t ax, ay; + int e; + if (isnan(x) || isnan(y)) return x + y; + if (ux.i == uy.i) return y; + ax = ux.i & -1ULL/2; + ay = uy.i & -1ULL/2; + if (ax == 0) { + if (ay == 0) return y; + ux.i = (uy.i & 1ULL<<63) | 1; + } else if (ax > ay || ((ux.i ^ uy.i) & 1ULL<<63)) { + ux.i--; + } + else { + ux.i++; + } + e = ux.i >> 52 & 0x7ff; + /* raise overflow if ux.f is infinite and x is finite */ + if (e == 0x7ff) just_do_it(float) _x = x+x; + /* raise underflow if ux.f is subnormal or zero */ + if (e == 0) just_do_it(float) _x = x*x + ux.f*ux.f; + return ux.f; +} + +float nextafterf(float x, float y) { + union {float f; uint32_t i;} ux={x}, uy={y}; + uint32_t ax, ay, e; + + if (isnan(x) || isnan(y)) return x + y; + if (ux.i == uy.i) return y; + ax = ux.i & 0x7fffffff; + ay = uy.i & 0x7fffffff; + if (ax == 0) { + if (ay == 0) return y; + ux.i = (uy.i & 0x80000000) | 1; + } else if (ax > ay || ((ux.i ^ uy.i) & 0x80000000)) { + ux.i--; + } + else { + ux.i++; + } + e = ux.i & 0x7f800000; + /* raise overflow if ux.f is infinite and x is finite */ + if (e == 0x7f800000) just_do_it(float) _x = x+x; + /* raise underflow if ux.f is subnormal or zero */ + if (e == 0) just_do_it(float) _x = x*x + ux.f*ux.f; + return ux.f; +} + +long double nextafterl(long double x, long double y) { + return nextafter(x, y); +} + +double nexttoward(double x, long double y) { + return nextafter(x, y); +} + +float nexttowardf(float x, long double y) { + union {float f; uint32_t i;} ux = {x}; + uint32_t e; + if (isnan(x) || isnan(y)) return x + y; + if (x == y) return y; + if (x == 0) { + ux.i = 1; + if (signbit(y)) ux.i |= 0x80000000; + } else if (x < y) { + if (signbit(x)) ux.i--; + else ux.i++; + } else { + if (signbit(x)) ux.i++; + else ux.i--; + } + e = ux.i & 0x7f800000; + /* raise overflow if ux.f is infinite and x is finite */ + if (e == 0x7f800000) just_do_it(float) _x = x+x; + /* raise underflow if ux.f is subnormal or zero */ + if (e == 0) just_do_it(float) _x = x*x + ux.f*ux.f; + return ux.f; +} + +long double nexttowardl(long double x, long double y) { + return nextafterl(x, y); +} + + +double round(double x) { + static const double_t toint = 1/DBL_EPSILON; + union {double f; uint64_t i;} u = {x}; + int e = u.i >> 52 & 0x7ff; + double_t y; + if (e >= 0x3ff+52) return x; + if (u.i >> 63) x = -x; + if (e < 0x3ff-1) { + /* raise inexact if x!=0 */ + just_do_it(float) _x = x + toint; + return 0*u.f; + } + y = x + toint - toint - x; + if (y > 0.5) y = y + x - 1; + else if (y <= -0.5) y = y + x + 1; + else y = y + x; + if (u.i >> 63) y = -y; + return y; +} + +float roundf(float x) { + static const double_t toint = 1/FLT_EPSILON; + union {float f; uint32_t i;} u = {x}; + int e = u.i >> 23 & 0xff; + float_t y; + if (e >= 0x7f+23) return x; + if (u.i >> 31) x = -x; + if (e < 0x7f-1) { + just_do_it(float) _x = x + toint; + return 0*u.f; + } + y = x + toint - toint - x; + if (y > 0.5f) y = y + x - 1; + else if (y <= -0.5f) y = y + x + 1; + else y = y + x; + if (u.i >> 31) y = -y; + return y; +} + +long double roundl(long double x) { + return round(x); +} diff --git a/code/math/ieee754.h b/code/math/ieee754.h deleted file mode 100644 index eeef751..0000000 --- a/code/math/ieee754.h +++ /dev/null @@ -1,139 +0,0 @@ - -// Instantiates 'template' macros for floating-point values -// When including expecting the following parameters to be defined: -// ftype: Floating-point type to consider -// itype: Signed integer type corresponding to ftype's bitwidth -// f_ebits: Number of bits in the exponent -// f_mbits: Number of bits in the mantissa -// suffix(name): appends corresponding suffix to the given name, -// e.g. f for floats - -#define f_nbits (1+f_ebits+f_mbits) -#define f_emax ((1ULL << (f_ebits-1)) - 1) -#define f_emin (1 - f_emax) -#define f_ebias f_emax - -// Extracting fields from the float -#define f_eoffs (f_mbits) -#define f_soffs (f_mbits+f_ebits) -#define f_emask ((1ULL << f_ebits) - 1) -#define f_mmask ((1ULL << f_mbits) - 1) -#define f_smask 1ULL -#define f_eval(b) (((b) >> f_eoffs) & f_emask) -#define f_sval(b) (((b) >> f_soffs) & f_smask) -#define f_mval(b) (((b) >> 0) & f_mmask) -#define f_abs(b) ((b) & ~(f_smask << f_soffs)) -#define f_exp(b) (f_eval(b) - f_ebias) - -#define f_qexp(b) (f_eval(b) - f_ebias - f_mbits) -#define f_qman(b) (((b) & f_mmask) | (f_mmask+1)) - -#define b_cons(s,e,m) (((itype)s << f_soffs) | ((itype)e << f_eoffs) | (itype)(m)) - -// Converting float to integer bits -static inline itype suffix(f_bits)(ftype f) { - union _u { - ftype f; - itype b; - } u; - u.f = f; - return u.b; -} - -static inline ftype suffix(f_frombits)(itype b) { - union _u { - ftype f; - itype b; - } u; - u.b = b; - return u.f; -} - -// Floating-point classification -int suffix(_fpclassify)(ftype f) { - itype bits = suffix(f_bits)(f); - itype exp = f_eval(bits); - itype man = f_mval(bits); - if(exp == f_emask) { - if(man == 0) return FP_INFINITE; - else return FP_NAN; - } - else if(exp == 0) { - if(man == 0) return FP_ZERO; - else return FP_SUBNORMAL; - } - else return FP_NORMAL; -} - -int suffix(_signbit)(ftype f) { - itype bits = suffix(f_bits)(f); - itype sign = f_sval(bits); - return sign; -} - -ftype suffix(copysign)(ftype x, ftype y) { - itype xbits = suffix(f_bits)(x); - itype ybits = suffix(f_bits)(y); - itype exp = f_eval(xbits); - itype man = f_mval(xbits); - itype sgn = f_sval(ybits); - itype rbits = b_cons(sgn, exp, man); - return suffix(f_frombits)(rbits); -} - -// Floating-point non-signaling comparison - -static Ordering suffix(_ordering)(ftype x, ftype y) { - itype xclass = suffix(_fpclassify)(x); - itype yclass = suffix(_fpclassify)(y); - if(xclass == FP_NAN || yclass == FP_NAN) { - return UN; - } - itype xbits = suffix(f_bits)(x); - itype ybits = suffix(f_bits)(y); - itype xsgn = f_sval(xbits); - itype ysgn = f_sval(ybits); - itype xabs = f_abs(xbits); - itype yabs = f_abs(ybits); - if(xsgn == ysgn) { - if(xabs > yabs) return GR; - if(xabs < yabs) return LS; - return EQ; - } - else { - if(xabs == 0 && yabs == 0) return EQ; - if(xsgn) return LS; - if(ysgn) return GR; - } - return UN; // I may be stupid -} - -int suffix(_isgrt)(ftype x, ftype y) { - int ord = suffix(_ordering)(x, y); - return ord == GR; -} - -int suffix(_isgeq)(ftype x, ftype y) { - int ord = suffix(_ordering)(x, y); - return ord == GR || ord == EQ; -} - -int suffix(_isles)(ftype x, ftype y) { - int ord = suffix(_ordering)(x, y); - return ord == LS; -} - -int suffix(_isleq)(ftype x, ftype y) { - int ord = suffix(_ordering)(x, y); - return ord == LS || ord == EQ; -} - -int suffix(_isleg)(ftype x, ftype y) { - int ord = suffix(_ordering)(x, y); - return ord == LS || ord == GR; -} - -int suffix(_isuno)(ftype x, ftype y) { - int ord = suffix(_ordering)(x, y); - return ord == UN; -} \ No newline at end of file diff --git a/code/math/math.c b/code/math/math.c deleted file mode 100644 index 5b85c90..0000000 --- a/code/math/math.c +++ /dev/null @@ -1,53 +0,0 @@ - -#include -#include - -// Used for float comparisons in ieee754.h -enum Ordering { - LS, - EQ, - GR, - UN, -} typedef Ordering; - -#define ftype float -#define itype int32_t -#define f_ebits 8 -#define f_mbits 23 -#define suffix(n) n ## f -#include "ieee754.h" -#include "pow.h" -#undef suffix -#undef f_mbits -#undef f_ebits -#undef itype -#undef ftype - -#define ftype double -#define itype int64_t -#define f_ebits 11 -#define f_mbits 52 -#define suffix(n) n -#include "ieee754.h" -#include "pow.h" -#undef suffix -#undef f_mbits -#undef f_ebits -#undef itype -#undef ftype - -_Static_assert(sizeof(long double) == sizeof(double), - "Are these 'long doubles' in the same room with us right now?"); - -#define ftype long double -#define itype int64_t -#define f_ebits 11 -#define f_mbits 52 -#define suffix(n) n ## l -#include "ieee754.h" -#include "pow.h" -#undef suffix -#undef f_mbits -#undef f_ebits -#undef itype -#undef ftype diff --git a/code/math/near.h b/code/math/near.h deleted file mode 100644 index e69de29..0000000 diff --git a/code/math/pow.h b/code/math/pow.h deleted file mode 100644 index 163790e..0000000 --- a/code/math/pow.h +++ /dev/null @@ -1,103 +0,0 @@ - -#include - -#if !defined(_isqrt_defined) -#define _isqrt_defined -static uint64_t _isqrt(uint64_t num, uint64_t *remp) { - // To find a square root of a number - // We get rid of zero - if(num == 0) { - *remp = 0; - return 0; - } - // Then, starting from the bottom, split num into 2-digit pairs - // and find the top-most non-zero pair - uint64_t i = 0; - while(i != (sizeof(uint64_t)*8) && (num >> i) != 0) { - i += 2; - } - // Then we start taking guesses such that at each step - // sqrt^2 <= number made of consequent pairs of exausted integers - uint64_t sqrt = 0; - uint64_t rem = 0; - // Repeat until remainder is equal to zero: - do { - i -= 2; - // Bring the next two digits of the number to our remainder - rem = (rem << 2) | ((num >> i) & 0x3); - // Find d such that d(2sqrt+d) <= rem - // Since d could be either 0 or 1 we simply check 1, otherwise its 0 - uint64_t d = 1; - uint64_t t = ((sqrt<<2)|1); - if(t <= rem) { - rem -= t; - } - else { - d = 0; - } - // Append the digit to sqrt from the right - sqrt = (sqrt<<1)|d; - } while(i != 0); - - *remp = rem; - return sqrt; -} -#endif - -// For all it's worth this shit is simply equivalent to -// _isqrt((uint64)x) -// I hate porgaming. -ftype suffix(sqrt)(ftype x) { - if(x < 0) { - #if math_errhandling & MATH_ERRNO - errno = EDOM; - #endif - return NAN; - } - if(x == 0 || isinf(x)) { - return x; - } - if(isnan(x)) { - return NAN; - } - itype bits = suffix(f_bits)(x); - itype exp = f_qexp(bits); - itype man = f_qman(bits); - // Get lots of precision by shifting man right by max bits - // and subtracting this from the exponent - itype bit = 0; // highest set-bit of man - while((man >> (bit+1)) != 0) ++bit; - itype prec_shift_n = f_nbits - bit - 3; - man <<= prec_shift_n; - exp -= prec_shift_n; - // Now do the sqrt of 2^exp * man - // If exp is odd then 2^{2k+1}*sqrt(man) = 2^{2k}*sqrt{2*man} - if((2 + (exp % 2)) % 2 != 0) { - man <<= 1; - } - // Take exp sqrt - exp >>= 1; - // Take sqrt of mantissa - uint64_t rem; - man = (itype)_isqrt(man, &rem); - // Now sqrt(x) = 2^exp * man - // we need to normalize this shit - bit = 0; // highest set-bit of man - while((man >> (bit+1)) != 0) ++bit; - exp += bit; - man <<= f_nbits-bit; - exp += f_ebias; - man >>= f_nbits-f_mbits; - man &= f_mmask; - // Cons it back - bits = b_cons(0, exp, man); - return suffix(f_frombits)(bits); -} - -ftype suffix(hypot)(ftype x, ftype y) -{ - if(isinf(x) || isinf(y)) { - return INFINITY; - } - return suffix(sqrt)(x*x + y*y); -} diff --git a/code/math/stat.h b/code/math/stat.h deleted file mode 100644 index e69de29..0000000 diff --git a/code/math/trig.h b/code/math/trig.h deleted file mode 100644 index e69de29..0000000 diff --git a/code/math/trigh.h b/code/math/trigh.h deleted file mode 100644 index e69de29..0000000 diff --git a/code/printf.h b/code/printf.h index af31298..acaff47 100644 --- a/code/printf.h +++ b/code/printf.h @@ -1,218 +1,220 @@ - -//TODO: verify printf("%d", 0). From the code it looked like it would print -// an empty string. - -// NOTE: this file doesn't exist in a vacuum, it's a template for generating -// the formatted print, you should define FMT_CHAR_TYPE before including it -inline static int FMT_FUNC_NAME (void *ctx, OutputFunc out, const FMT_CHAR_TYPE *fmt, va_list args) { - size_t full_length = 0; - - while (*fmt) { - // skip any normal non percent text - const FMT_CHAR_TYPE *start = fmt; - while (*fmt && *fmt != '%') fmt++; - - // print all those non percent text - out(ctx, fmt - start, start); - full_length += (fmt - start); - - // null terminated - if (*fmt == '\0') break; - fmt += 1; - - if (*fmt == '%') { - out(ctx, 1, "%"); - fmt++; - continue; - } - - unsigned int precision = 0; - if (*fmt == '.') { - // custom precision - fmt++; - - if (isdigit(*fmt)) { - // just a small atoi - // TODO: handle overflow, just in case(?) - while (isdigit(*fmt)) { - precision *= 10u; - precision += (*fmt - '0'); - - fmt++; - } - } else if (*fmt == '*') { - int p = va_arg(args, int); - - precision = p >= 0 ? ((unsigned int)p) : 0; - fmt++; - } - } - - // integer length specifiers - enum { - CHAR, - SHORT, - INT, - LONG, - LLONG - } int_length = INT; - - if (*fmt == 'l') { - fmt++; - - if (*fmt == 'l') { - int_length = LLONG; - fmt++; - } else { - int_length = LONG; - } - } else if (*fmt == 'h') { - fmt++; - - if (*fmt == 'h') { - int_length = CHAR; - fmt++; - } else { - int_length = SHORT; - } - } else if (*fmt == 'z') { - fmt++; - - int_length = _Generic((size_t)0, - unsigned char: CHAR, - unsigned short: SHORT, - unsigned int: INT, - unsigned long: LONG, - unsigned long long: LLONG); - } - - FMT_CHAR_TYPE ch = *fmt++; - const char* characters = "0123456789abcdef"; - if (ch == 'X') characters = "0123456789ABCDEF"; - - switch (ch) { - case 'c': { - const char chr = va_arg(args, int); - out(ctx, 1, &chr); - full_length ++; - break; - } - case 'f': - case 'L': { - double d = va_arg(args, double); - - if(isinf(d)) { - out(ctx, sizeof"inf"-1, "inf"); - break; - } - else if(isnan(d)) { - out(ctx, sizeof"nan"-1, "nan"); - break; - } - - if(d < 0) { // TODO: negative zero - out(ctx, 1, "-"); - d = -d; - } - - uint64_t w = (uint64_t)d; - d -= w; - FMT_CHAR_TYPE buffer[20]; - size_t len = sizeof(buffer); - do { - buffer[--len] = characters[w % 10]; - w /= 10; - } while(w != 0); - out(ctx, sizeof(buffer) - (len * sizeof(FMT_CHAR_TYPE)), buffer + len); - - char dot = '.'; - out(ctx, 1, &dot); - - for(int i = 0; i != 6; ++i) { - d *= 10; - int dv = (int)d; - d -= dv; - char digit = characters[dv]; - out(ctx, 1, &digit); - } - } break; - case 's': { - const FMT_CHAR_TYPE *str = va_arg(args, FMT_CHAR_TYPE*); - size_t len = FMT_STRLEN_S(str, precision ? precision : SIZE_MAX); - - out(ctx, len, str); - full_length += len; - break; - } - - case 'b': - case 'o': - case 'i': - case 'u': - case 'd': - case 'x': - case 'X': { - int base = 10; - switch (ch) { - case 'X': case 'x': base = 16; break; - case 'o': base = 8; break; - case 'b': base = 2; break; - default: base = 10; break; - } - - uintmax_t i; - if (ch == 'd' || ch == 'i') { - intmax_t num = 0; - switch (int_length) { - case CHAR: num = (char) va_arg(args, int); break; - case SHORT: num = (short) va_arg(args, int); break; - case INT: num = va_arg(args, int); break; - case LONG: num = va_arg(args, long); break; - case LLONG: num = va_arg(args, long long); break; - default: break; - } - - if (num < 0) { - out(ctx, 1, "-"); - i = -num; - full_length += 1; - } else { - i = num; - } - } else { - switch (int_length) { - case CHAR: i = (char) va_arg(args, int); break; - case SHORT: i = (short) va_arg(args, int); break; - case INT: i = va_arg(args, int); break; - case LONG: i = va_arg(args, long); break; - case LLONG: i = va_arg(args, long long); break; - default: i = 0; break; - } - } - - if (i == 0) { - out(ctx, 1, "0"); - full_length += 1; - } else { - FMT_CHAR_TYPE buffer[20]; - size_t len = sizeof(buffer); - - // we build the number in reverse - while (i != 0) { - buffer[--len] = characters[i % base]; - i /= base; - } - - out(ctx, sizeof(buffer) - (len * sizeof(FMT_CHAR_TYPE)), buffer + len); - full_length += (sizeof(buffer) - len); - } - break; - } - - default: break; - } - } - - return full_length; -} - + +#include + +//TODO: verify printf("%d", 0). From the code it looked like it would print +// an empty string. + +// NOTE: this file doesn't exist in a vacuum, it's a template for generating +// the formatted print, you should define FMT_CHAR_TYPE before including it +inline static int FMT_FUNC_NAME (void *ctx, OutputFunc out, const FMT_CHAR_TYPE *fmt, va_list args) { + size_t full_length = 0; + + while (*fmt) { + // skip any normal non percent text + const FMT_CHAR_TYPE *start = fmt; + while (*fmt && *fmt != '%') fmt++; + + // print all those non percent text + out(ctx, fmt - start, start); + full_length += (fmt - start); + + // null terminated + if (*fmt == '\0') break; + fmt += 1; + + if (*fmt == '%') { + out(ctx, 1, "%"); + fmt++; + continue; + } + + unsigned int precision = 0; + if (*fmt == '.') { + // custom precision + fmt++; + + if (isdigit(*fmt)) { + // just a small atoi + // TODO: handle overflow, just in case(?) + while (isdigit(*fmt)) { + precision *= 10u; + precision += (*fmt - '0'); + + fmt++; + } + } else if (*fmt == '*') { + int p = va_arg(args, int); + + precision = p >= 0 ? ((unsigned int)p) : 0; + fmt++; + } + } + + // integer length specifiers + enum { + CHAR, + SHORT, + INT, + LONG, + LLONG + } int_length = INT; + + if (*fmt == 'l') { + fmt++; + + if (*fmt == 'l') { + int_length = LLONG; + fmt++; + } else { + int_length = LONG; + } + } else if (*fmt == 'h') { + fmt++; + + if (*fmt == 'h') { + int_length = CHAR; + fmt++; + } else { + int_length = SHORT; + } + } else if (*fmt == 'z') { + fmt++; + + int_length = _Generic((size_t)0, + unsigned char: CHAR, + unsigned short: SHORT, + unsigned int: INT, + unsigned long: LONG, + unsigned long long: LLONG); + } + + FMT_CHAR_TYPE ch = *fmt++; + const char* characters = "0123456789abcdef"; + if (ch == 'X') characters = "0123456789ABCDEF"; + + switch (ch) { + case 'c': { + const char chr = va_arg(args, int); + out(ctx, 1, &chr); + full_length ++; + break; + } + case 'f': + case 'L': { + double d = va_arg(args, double); + + if(signbit(d)) { // TODO: negative zero + out(ctx, 1, "-"); + d = -d; + } + + if(isinf(d)) { + out(ctx, sizeof"inf"-1, "inf"); + break; + } + else if(isnan(d)) { + out(ctx, sizeof"nan"-1, "nan"); + break; + } + + uint64_t w = (uint64_t)d; + d -= w; + FMT_CHAR_TYPE buffer[20]; + size_t len = sizeof(buffer); + do { + buffer[--len] = characters[w % 10]; + w /= 10; + } while(w != 0); + out(ctx, sizeof(buffer) - (len * sizeof(FMT_CHAR_TYPE)), buffer + len); + + char dot = '.'; + out(ctx, 1, &dot); + + for(int i = 0; i != 6; ++i) { + d *= 10; + int dv = (int)d; + d -= dv; + char digit = characters[dv]; + out(ctx, 1, &digit); + } + } break; + case 's': { + const FMT_CHAR_TYPE *str = va_arg(args, FMT_CHAR_TYPE*); + size_t len = FMT_STRLEN_S(str, precision ? precision : SIZE_MAX); + + out(ctx, len, str); + full_length += len; + break; + } + + case 'b': + case 'o': + case 'i': + case 'u': + case 'd': + case 'x': + case 'X': { + int base = 10; + switch (ch) { + case 'X': case 'x': base = 16; break; + case 'o': base = 8; break; + case 'b': base = 2; break; + default: base = 10; break; + } + + uintmax_t i; + if (ch == 'd' || ch == 'i') { + intmax_t num = 0; + switch (int_length) { + case CHAR: num = (char) va_arg(args, int); break; + case SHORT: num = (short) va_arg(args, int); break; + case INT: num = va_arg(args, int); break; + case LONG: num = va_arg(args, long); break; + case LLONG: num = va_arg(args, long long); break; + default: break; + } + + if (num < 0) { + out(ctx, 1, "-"); + i = -num; + full_length += 1; + } else { + i = num; + } + } else { + switch (int_length) { + case CHAR: i = (char) va_arg(args, int); break; + case SHORT: i = (short) va_arg(args, int); break; + case INT: i = va_arg(args, int); break; + case LONG: i = va_arg(args, long); break; + case LLONG: i = va_arg(args, long long); break; + default: i = 0; break; + } + } + + if (i == 0) { + out(ctx, 1, "0"); + full_length += 1; + } else { + FMT_CHAR_TYPE buffer[20]; + size_t len = sizeof(buffer); + + // we build the number in reverse + while (i != 0) { + buffer[--len] = characters[i % base]; + i /= base; + } + + out(ctx, sizeof(buffer) - (len * sizeof(FMT_CHAR_TYPE)), buffer + len); + full_length += (sizeof(buffer) - len); + } + break; + } + + default: break; + } + } + + return full_length; +} + diff --git a/code/stdio.c b/code/stdio.c index b7c782e..b233a25 100644 --- a/code/stdio.c +++ b/code/stdio.c @@ -1,139 +1,139 @@ -#include -#include -#include -#include -#include - -#include <_os.h> - -#define __STDC_WANT_LIB_EXT1__ 1 -#include - -int remove(const char *filename) -{ - return _os_del_file(filename); -} - -int rename(const char *old, const char *new) -{ - return _os_mov_file(old, new); -} - -char *tmpnam(char *s) -{ - static char static_buffer[L_tmpnam]; - char *buffer = s; - if(s == NULL) buffer = static_buffer; - return _os_tmpname(buffer); -} - -FILE *fopen(const char *restrict filename, const char *restrict mode) -{ - // Basically defined UB here by introducing missing modes - // It is simpler to implement that way I think. - int base_mode = mode[0]; - int binary = 0; - int exclusive = 0; - int update = 0; - for(; *mode != 0; ++mode) { - if(*mode == 'x') exclusive = 1; - if(*mode == 'b') binary = 1; - if(*mode == '+') update = 1; - } - if(base_mode == 'r' && exclusive) return NULL; - if(base_mode == 'a' && exclusive) return NULL; - - _OS_ModeFlags mode_flags = { - .base_mode = base_mode, - .binary = binary, - .update = update, - .exclusive = exclusive, - }; - - return _os_fopen(filename, mode_flags); -} - -int fclose(FILE *stream) -{ - return _os_fclose(stream); -} - -// TODO:kekw: -FILE *freopen( - const char *restrict filename, - const char *restrict mode, - FILE *restrict stream) -{ - fclose(stream); - return NULL; -} - -typedef void(*OutputFunc)(void* ctx, size_t n, const char str[]); - -/////////////////////////////////////////////// -// Instantiate formatted print functions -/////////////////////////////////////////////// -// TODO: instantiate wide char variants of print -#define FMT_FUNC_NAME fmt_print_char -#define FMT_CHAR_TYPE char -#define FMT_STRLEN_S(s, maxsize) strnlen_s(s, maxsize) -#include "printf.h" - -typedef struct { - size_t used, capacity; - char* string; -} StrPrintCtx; - -FILE *stdout, *stderr, *stdin; - -#define CALL_PRINTF(fmt_func, ctx, out, fmt) \ - va_list args; \ - va_start(args, fmt); \ - int result = fmt_func(ctx, out, fmt, args); \ - va_end(args) - -static void string_write(void *ctx, size_t n, const char *restrict str) { - StrPrintCtx *c = ctx; - memcpy(c->string + c->used, str, n); - c->used += n; -} - -int fprintf(FILE *file, const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, file, _os_file_write, fmt); - return result; -} - -int printf(const char *restrict fmt, ...) { - CALL_PRINTF(fmt_print_char, stdout, _os_file_write, fmt); - return result; -} - -int snprintf(char *restrict s, size_t n, const char *restrict fmt, ...) { - StrPrintCtx ctx = { 0, n, s }; - CALL_PRINTF(fmt_print_char, &ctx, string_write, fmt); - return result; -} - -int sprintf(char *restrict s, const char *restrict fmt, ...) { - StrPrintCtx ctx = { 0, SIZE_MAX, s }; - CALL_PRINTF(fmt_print_char, &ctx, string_write, fmt); - return result; -} - -int vfprintf(FILE *file, const char *restrict fmt, va_list args) { - return fmt_print_char(file, _os_file_write, fmt, args); -} - -int vprintf(const char *restrict fmt, va_list args) { - return fmt_print_char(stdout, _os_file_write, fmt, args); -} - -int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list args) { - StrPrintCtx ctx = { 0, n, s }; - return fmt_print_char(&ctx, string_write, fmt, args); -} - -int vsprintf(char *restrict s, const char *restrict fmt, va_list args) { - StrPrintCtx ctx = { 0, SIZE_MAX, s }; - return fmt_print_char(&ctx, string_write, fmt, args); -} +#include +#include +#include +#include +#include + +#include <_os.h> + +#define __STDC_WANT_LIB_EXT1__ 1 +#include + +int remove(const char *filename) +{ + return _os_del_file(filename); +} + +int rename(const char *old, const char *new) +{ + return _os_mov_file(old, new); +} + +char *tmpnam(char *s) +{ + static char static_buffer[L_tmpnam]; + char *buffer = s; + if(s == NULL) buffer = static_buffer; + return _os_tmpname(buffer); +} + +FILE *fopen(const char *restrict filename, const char *restrict mode) +{ + // Basically defined UB here by introducing missing modes + // It is simpler to implement that way I think. + int base_mode = mode[0]; + int binary = 0; + int exclusive = 0; + int update = 0; + for(; *mode != 0; ++mode) { + if(*mode == 'x') exclusive = 1; + if(*mode == 'b') binary = 1; + if(*mode == '+') update = 1; + } + if(base_mode == 'r' && exclusive) return NULL; + if(base_mode == 'a' && exclusive) return NULL; + + _OS_ModeFlags mode_flags = { + .base_mode = base_mode, + .binary = binary, + .update = update, + .exclusive = exclusive, + }; + + return _os_fopen(filename, mode_flags); +} + +int fclose(FILE *stream) +{ + return _os_fclose(stream); +} + +// TODO:kekw: +FILE *freopen( + const char *restrict filename, + const char *restrict mode, + FILE *restrict stream) +{ + fclose(stream); + return NULL; +} + +typedef void(*OutputFunc)(void* ctx, size_t n, const char str[]); + +/////////////////////////////////////////////// +// Instantiate formatted print functions +/////////////////////////////////////////////// +// TODO: instantiate wide char variants of print +#define FMT_FUNC_NAME fmt_print_char +#define FMT_CHAR_TYPE char +#define FMT_STRLEN_S(s, maxsize) strnlen_s(s, maxsize) +#include "printf.h" + +typedef struct { + size_t used, capacity; + char* string; +} StrPrintCtx; + +FILE *stdout, *stderr, *stdin; + +#define CALL_PRINTF(fmt_func, ctx, out, fmt) \ + va_list args; \ + va_start(args, fmt); \ + int result = fmt_func(ctx, out, fmt, args); \ + va_end(args) + +static void string_write(void *ctx, size_t n, const char *restrict str) { + StrPrintCtx *c = ctx; + memcpy(c->string + c->used, str, n); + c->used += n; +} + +int fprintf(FILE *file, const char *restrict fmt, ...) { + CALL_PRINTF(fmt_print_char, file, _os_file_write, fmt); + return result; +} + +int printf(const char *restrict fmt, ...) { + CALL_PRINTF(fmt_print_char, stdout, _os_file_write, fmt); + return result; +} + +int snprintf(char *restrict s, size_t n, const char *restrict fmt, ...) { + StrPrintCtx ctx = { 0, n, s }; + CALL_PRINTF(fmt_print_char, &ctx, string_write, fmt); + return result; +} + +int sprintf(char *restrict s, const char *restrict fmt, ...) { + StrPrintCtx ctx = { 0, SIZE_MAX, s }; + CALL_PRINTF(fmt_print_char, &ctx, string_write, fmt); + return result; +} + +int vfprintf(FILE *file, const char *restrict fmt, va_list args) { + return fmt_print_char(file, _os_file_write, fmt, args); +} + +int vprintf(const char *restrict fmt, va_list args) { + return fmt_print_char(stdout, _os_file_write, fmt, args); +} + +int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list args) { + StrPrintCtx ctx = { 0, n, s }; + return fmt_print_char(&ctx, string_write, fmt, args); +} + +int vsprintf(char *restrict s, const char *restrict fmt, va_list args) { + StrPrintCtx ctx = { 0, SIZE_MAX, s }; + return fmt_print_char(&ctx, string_write, fmt, args); +} diff --git a/inc/ctype.h b/inc/ctype.h index de90aca..a2b8114 100644 --- a/inc/ctype.h +++ b/inc/ctype.h @@ -1,16 +1,16 @@ -#pragma once - -int isalnum(int c); -int isalpha(int c); -int isblank(int c); -int iscntrl(int c); -int isdigit(int c); -int isgraph(int c); -int islower(int c); -int isprint(int c); -int ispunct(int c); -int isspace(int c); -int isupper(int c); -int isxdigit(int c); -int tolower(int c); -int toupper(int c); +#pragma once + +int isalnum(int c); +int isalpha(int c); +int isblank(int c); +int iscntrl(int c); +int isdigit(int c); +int isgraph(int c); +int islower(int c); +int isprint(int c); +int ispunct(int c); +int isspace(int c); +int isupper(int c); +int isxdigit(int c); +int tolower(int c); +int toupper(int c); diff --git a/inc/errno.h b/inc/errno.h index 54aea48..2f846a9 100644 --- a/inc/errno.h +++ b/inc/errno.h @@ -1,9 +1,9 @@ - -#pragma once - -#define EDOM 1 -#define EILSEQ 2 -#define ERANGE 3 - -// TODO: make it thread-local -extern int errno; + +#pragma once + +#define EDOM 1 +#define EILSEQ 2 +#define ERANGE 3 + +// TODO: make it thread-local +extern int errno; diff --git a/inc/fenv.h b/inc/fenv.h index 7e93c8b..87e6c78 100644 --- a/inc/fenv.h +++ b/inc/fenv.h @@ -1,61 +1,61 @@ - -#pragma once - -typedef unsigned fexcept_t; -typedef unsigned fenv_t; - -#define FE_INVALID (1 << 0) -#define FE_DIVBYZERO (1 << 2) -#define FE_OVERFLOW (1 << 3) -#define FE_UNDERFLOW (1 << 4) -#define FE_INEXACT (1 << 5) -// Implementation-defined flags -#define FE_DENORM (1 << 1) -#define FE_DAZ (1 << 6) - -#define FE_ALL_EXCEPT \ - ( FE_INVALID \ - | FE_DIVBYZERO \ - | FE_OVERFLOW \ - | FE_UNDERFLOW \ - | FE_INEXACT \ - | FE_DENORM \ - | FE_DAZ ) - -#define FE_TONEAREST 0x00 -#define FE_DOWNWARD 0x01 -#define FE_UPWARD 0x02 -#define FE_TOWARDZERO 0x03 - -extern fenv_t _fe_dfl_env; -#define FE_DFL_ENV (&_fe_dfl_env) - -// Exceptions - -int feclearexcept(int excepts); -int fegetexceptflag(fexcept_t *flagp, int excepts); -int feraiseexcept(int excepts); -int fesetexceptflag(const fexcept_t *flagp, int excepts); -int fetestexcept(int excepts); - -// Rounding behaviour - -int fegetround(void); -int fesetround(int round); - -// Environment - -int fegetenv(fenv_t *env); -int fesetenv(fenv_t *env); -int feholdexcept(fenv_t *envp); -int feupdateenv(fenv_t const *envp); - -// Non-standard functions - -int _feenabletraps(int excepts); -int _fedisabletraps(int excepts); - -#if defined(_CIABATTA_EXT) - #define feenabletraps _feenabletraps - #define _fedisabletraps _fedisabletraps + +#pragma once + +typedef unsigned fexcept_t; +typedef unsigned fenv_t; + +#define FE_INVALID (1 << 0) +#define FE_DIVBYZERO (1 << 2) +#define FE_OVERFLOW (1 << 3) +#define FE_UNDERFLOW (1 << 4) +#define FE_INEXACT (1 << 5) +// Implementation-defined flags +#define FE_DENORM (1 << 1) +#define FE_DAZ (1 << 6) + +#define FE_ALL_EXCEPT \ + ( FE_INVALID \ + | FE_DIVBYZERO \ + | FE_OVERFLOW \ + | FE_UNDERFLOW \ + | FE_INEXACT \ + | FE_DENORM \ + | FE_DAZ ) + +#define FE_TONEAREST 0x00 +#define FE_DOWNWARD 0x01 +#define FE_UPWARD 0x02 +#define FE_TOWARDZERO 0x03 + +extern fenv_t _fe_dfl_env; +#define FE_DFL_ENV (&_fe_dfl_env) + +// Exceptions + +int feclearexcept(int excepts); +int fegetexceptflag(fexcept_t *flagp, int excepts); +int feraiseexcept(int excepts); +int fesetexceptflag(const fexcept_t *flagp, int excepts); +int fetestexcept(int excepts); + +// Rounding behaviour + +int fegetround(void); +int fesetround(int round); + +// Environment + +int fegetenv(fenv_t *env); +int fesetenv(fenv_t *env); +int feholdexcept(fenv_t *envp); +int feupdateenv(fenv_t const *envp); + +// Non-standard functions + +int _feenabletraps(int excepts); +int _fedisabletraps(int excepts); + +#if defined(_CIABATTA_EXT) + #define feenabletraps _feenabletraps + #define _fedisabletraps _fedisabletraps #endif \ No newline at end of file diff --git a/inc/locale.h b/inc/locale.h index a59a17e..a21b81c 100644 --- a/inc/locale.h +++ b/inc/locale.h @@ -1,45 +1,45 @@ - -#pragma once - -#define _COL_IGNORE_SPACE 0x1 -#define _COL_IGNORE_SYMBOL 0x2 - -struct lconv { - // LC_NUMERIC - char *decimal_point; // "." - char *thousands_sep; // "" - char *grouping; // "" - // LC_MONETARY - char *mon_decimal_point; // "" - char *mon_thousands_sep; // "" - char *mon_grouping; // "" - char *positive_sign; // "" - char *negative_sign; // "" - char *currency_symbol; // "" - char frac_digits; // CHAR_MAX - char p_cs_precedes; // CHAR_MAX - char n_cs_precedes; // CHAR_MAX - char p_sep_by_space; // CHAR_MAX - char n_sep_by_space; // CHAR_MAX - char p_sign_posn; // CHAR_MAX - char n_sign_posn; // CHAR_MAX - char *int_curr_symbol; // "" - char int_frac_digits; // CHAR_MAX - char int_p_cs_precedes; // CHAR_MAX - char int_n_cs_precedes; // CHAR_MAX - char int_p_sep_by_space; // CHAR_MAX - char int_n_sep_by_space; // CHAR_MAX - char int_p_sign_posn; // CHAR_MAX - char int_n_sign_posn; // CHAR_MAX -}; - -// Locale categories -#define LC_ALL 0 -#define LC_COLLATE 1 -#define LC_CTYPE 2 -#define LC_MONETARY 3 -#define LC_NUMERIC 4 -#define LC_TIME 5 - -char *setlocale(int category, const char *locale); -struct lconv *localeconv(void); + +#pragma once + +#define _COL_IGNORE_SPACE 0x1 +#define _COL_IGNORE_SYMBOL 0x2 + +struct lconv { + // LC_NUMERIC + char *decimal_point; // "." + char *thousands_sep; // "" + char *grouping; // "" + // LC_MONETARY + char *mon_decimal_point; // "" + char *mon_thousands_sep; // "" + char *mon_grouping; // "" + char *positive_sign; // "" + char *negative_sign; // "" + char *currency_symbol; // "" + char frac_digits; // CHAR_MAX + char p_cs_precedes; // CHAR_MAX + char n_cs_precedes; // CHAR_MAX + char p_sep_by_space; // CHAR_MAX + char n_sep_by_space; // CHAR_MAX + char p_sign_posn; // CHAR_MAX + char n_sign_posn; // CHAR_MAX + char *int_curr_symbol; // "" + char int_frac_digits; // CHAR_MAX + char int_p_cs_precedes; // CHAR_MAX + char int_n_cs_precedes; // CHAR_MAX + char int_p_sep_by_space; // CHAR_MAX + char int_n_sep_by_space; // CHAR_MAX + char int_p_sign_posn; // CHAR_MAX + char int_n_sign_posn; // CHAR_MAX +}; + +// Locale categories +#define LC_ALL 0 +#define LC_COLLATE 1 +#define LC_CTYPE 2 +#define LC_MONETARY 3 +#define LC_NUMERIC 4 +#define LC_TIME 5 + +char *setlocale(int category, const char *locale); +struct lconv *localeconv(void); diff --git a/inc/math.h b/inc/math.h index 92da1b2..ad53ca8 100644 --- a/inc/math.h +++ b/inc/math.h @@ -1,220 +1,302 @@ - -#pragma once - -typedef float float_t; -typedef double double_t; - -#ifndef _HUGE_ENUF -#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow -#endif - -#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) -#define HUGE_VAL ((double)INFINITY) -#define HUGE_VALF ((float)INFINITY) - -#define NAN (-(float)(INFINITY * 0.0F)) - -// FP_ILOGB0 -// FP_ILOGBNAN - -#define MATH_ERRNO 1 -#define MATH_ERREXCEPT 2 - -#define math_errhandling MATH_ERRNO - -// Classification -#define FP_INFINITE 0 -#define FP_NAN 1 -#define FP_NORMAL 2 -#define FP_SUBNORMAL 3 -#define FP_ZERO 4 -int _fpclassify(double f); -int _fpclassifyf(float f); -#define fpclassify(x) (sizeof(x)==4?_fpclassifyf(x):_fpclassify(x)) -#define isfinite(x) (fpclassify(x) != FP_INFINITE && fpclassify(x) != FP_NAN) -#define isinf(x) (fpclassify(x) == FP_INFINITE) -#define isnan(x) (fpclassify(x) == FP_NAN) -#define isnormal(x) (fpclassify(x) == FP_NORMAL) - -// Sign bit shit -int _signbit(double f); -int _signbitf(float f); -#define signbit(x) (sizeof(x)==4?_signbitf(x):signbit(x)) -float copysignf(float x, float y); - -// Ordering -#define isgreater(x) (sizeof(x)==4?_isgrtf(x):_isgrt(x)) -#define isgreaterequal(x) (sizeof(x)==4?_isgeqf(x):_isgeq(x)) -#define isless(x) (sizeof(x)==4?_islesf(x):_isles(x)) -#define islessequal(x) (sizeof(x)==4?_isleqf(x):_isleq(x)) -#define islessgreater(x) (sizeof(x)==4?_islegf(x):_isleg(x)) -#define isunordered(x) (sizeof(x)==4?_isunof(x):_isuno(x)) - -double acos(double x); -float acosf(float x); - -double asin(double x); -float asinf(float x); - -double atan(double x); -float atanf(float x); - -double atan2(double y, double x); -float atan2f(float y, float x); - -double cos(double x); -float cosf(float x); - -double sin(double x); -float sinf(float x); - -double tan(double x); -float tanf(float x); - -double acosh(double x); -float acoshf(float x); - -double asinh(double x); -float asinhf(float x); - -double atanh(double x); -float atanhf(float x); - -double cosh(double x); -float coshf(float x); - -double sinh(double x); -float sinhf(float x); - -double tanh(double x); -float tanhf(float x); - -double exp(double x); -float expf(float x); - -double exp2(double x); -float exp2f(float x); - -double expm1(double x); -float expm1f(float x); - -double frexp(double value, int *exp); -float frexpf(float value, int *exp); - -int ilogb(double x); -int ilogbf(float x); - -double ldexp(double x, int exp); -float ldexpf(float x, int exp); - -double log(double x); -float logf(float x); - -double log10(double x); -float log10f(float x); - -double log1p(double x); -float log1pf(float x); - -double log2(double x); -float log2f(float x); - -double logb(double x); -float logbf(float x); - -double modf(double value, double *iptr); -float modff(float value, float *iptr); - -double scalbn(double x, int n); -float scalbnf(float x, int n); - -double scalbln(double x, long int n); -float scalblnf(float x, long int n); - -double cbrt(double x); -float cbrtf(float x); - -double fabs(double x); -float fabsf(float x); - -double hypot(double x, double y); -float hypotf(float x, float y); - -double pow(double x, double y); -float powf(float x, float y); - -double sqrt(double x); -float sqrtf(float x); - -double erf(double x); -float erff(float x); - -double erfc(double x); -float erfcf(float x); - -double lgamma(double x); -float lgammaf(float x); - -double tgamma(double x); -float tgammaf(float x); - -double ceil(double x); -float ceilf(float x); - -double floor(double x); -float floorf(float x); - -double nearbyint(double x); -float nearbyintf(float x); - -double rint(double x); -float rintf(float x); - -long int lrint(double x); -long int lrintf(float x); - -long long int llrint(double x); -long long int llrintf(float x); - -double round(double x); -float roundf(float x); - -long int lround(double x); -long int lroundf(float x); - -long long int llround(double x); -long long int llroundf(float x); - -double trunc(double x); -float truncf(float x); - -double fmod(double x, double y); -float fmodf(float x, float y); - -double remainder(double x, double y); -float remainderf(float x, float y); - -double remquo(double x, double y, int *quo); -float remquof(float x, float y, int *quo); - -double copysign(double x, double y); -float copysignf(float x, float y); - -double nan(const char *tagp); -float nanf(const char *tagp); - -double nextafter(double x, double y); -float nextafterf(float x, float y); - -double fdim(double x, double y); -float fdimf(float x, float y); - -double fmax(double x, double y); -float fmaxf(float x, float y); - -double fmin(double x, double y); -float fminf(float x, float y); - -double fma(double x, double y, double z); -float fmaf(float x, float y, float z); - + +#pragma once + +typedef float float_t; +typedef double double_t; + +#ifndef _HUGE_ENUF +#define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow +#endif + +#define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) +#define HUGE_VAL ((double)INFINITY) +#define HUGE_VALF ((float)INFINITY) + +#define NAN (-(float)(INFINITY * 0.0F)) + +#define FP_ILOGBNAN (-1-0x7fffffff) +#define FP_ILOGB0 FP_ILOGBNAN + +#define MATH_ERRNO 1 +#define MATH_ERREXCEPT 2 + +#define math_errhandling MATH_ERRNO + +// Classification +#define FP_INFINITE 0 +#define FP_NAN 1 +#define FP_NORMAL 2 +#define FP_SUBNORMAL 3 +#define FP_ZERO 4 +int _fpclassify(double); +int _fpclassifyf(float); +int _fpclassifyl(long double); +#define fpclassify(x) (sizeof(x)==4?_fpclassifyf(x)\ + :sizeof(x)==8?_fpclassify(x) \ + : _fpclassifyl(x)) +#define isfinite(x) (fpclassify(x) != FP_INFINITE && fpclassify(x) != FP_NAN) +#define isinf(x) (fpclassify(x) == FP_INFINITE) +#define isnan(x) (fpclassify(x) == FP_NAN) +#define isnormal(x) (fpclassify(x) == FP_NORMAL) + +// signbit shit +int _signbit(double); +int _signbitf(float); +int _signbitl(long double); +#define signbit(x) (sizeof(x) == sizeof(float) ? _signbitf(x) \ + :sizeof(x) == sizeof(double) ? _signbit(x) \ + : _signbitl(x)) + +// Ordering +#define isunordered(x,y) (isnan((x)) ? ((void)(y),1) : isnan((y))) +#define isgreater(x,y) (!isunordered(x,y) && ((x) > (y))) +#define isgreaterequal(x,y) (!isunordered(x,y) && ((x) >= (y))) +#define isless(x,y) (!isunordered(x,y) && ((x) < (y))) +#define islessequal(x,y) (!isunordered(x,y) && ((x) <= (y))) +#define islessgreater(x,y) (!isunordered(x,y) && ((x) != (y))) + +#if defined(_USE_MATH_DEFINES) + #define M_E 2.7182818284590452354 + #define M_LOG2E 1.4426950408889634074 + #define M_LOG10E 0.43429448190325182765 + #define M_LN2 0.69314718055994530942 + #define M_LN10 2.30258509299404568402 + #define M_PI 3.14159265358979323846 + #define M_PI_2 1.57079632679489661923 + #define M_PI_4 0.78539816339744830962 + #define M_1_PI 0.31830988618379067154 + #define M_2_PI 0.63661977236758134308 + #define M_2_SQRTPI 1.12837916709551257390 + #define M_SQRT2 1.41421356237309504880 + #define M_SQRT1_2 0.70710678118654752440 +#endif + +// Floating-point function prototypes +double acos(double); +float acosf(float); +long double acosl(long double); + +double acosh(double); +float acoshf(float); +long double acoshl(long double); + +double asin(double); +float asinf(float); +long double asinl(long double); + +double asinh(double); +float asinhf(float); +long double asinhl(long double); + +double atan(double); +float atanf(float); +long double atanl(long double); + +double atan2(double, double); +float atan2f(float, float); +long double atan2l(long double, long double); + +double atanh(double); +float atanhf(float); +long double atanhl(long double); + +double cbrt(double); +float cbrtf(float); +long double cbrtl(long double); + +double ceil(double); +float ceilf(float); +long double ceill(long double); + +double copysign(double, double); +float copysignf(float, float); +long double copysignl(long double, long double); + +double cos(double); +float cosf(float); +long double cosl(long double); + +double cosh(double); +float coshf(float); +long double coshl(long double); + +double erf(double); +float erff(float); +long double erfl(long double); + +double erfc(double); +float erfcf(float); +long double erfcl(long double); + +double exp(double); +float expf(float); +long double expl(long double); + +double exp2(double); +float exp2f(float); +long double exp2l(long double); + +double expm1(double); +float expm1f(float); +long double expm1l(long double); + +double fabs(double); +float fabsf(float); +long double fabsl(long double); + +double fdim(double, double); +float fdimf(float, float); +long double fdiml(long double, long double); + +double floor(double); +float floorf(float); +long double floorl(long double); + +double fma(double, double, double); +float fmaf(float, float, float); +long double fmal(long double, long double, long double); + +double fmax(double, double); +float fmaxf(float, float); +long double fmaxl(long double, long double); + +double fmin(double, double); +float fminf(float, float); +long double fminl(long double, long double); + +double fmod(double, double); +float fmodf(float, float); +long double fmodl(long double, long double); + +double frexp(double, int *); +float frexpf(float, int *); +long double frexpl(long double, int *); + +double hypot(double, double); +float hypotf(float, float); +long double hypotl(long double, long double); + +int ilogb(double); +int ilogbf(float); +int ilogbl(long double); + +double ldexp(double, int); +float ldexpf(float, int); +long double ldexpl(long double, int); + +double lgamma(double); +float lgammaf(float); +long double lgammal(long double); + +long long llrint(double); +long long llrintf(float); +long long llrintl(long double); + +long long llround(double); +long long llroundf(float); +long long llroundl(long double); + +double log(double); +float logf(float); +long double logl(long double); + +double log10(double); +float log10f(float); +long double log10l(long double); + +double log1p(double); +float log1pf(float); +long double log1pl(long double); + +double log2(double); +float log2f(float); +long double log2l(long double); + +double logb(double); +float logbf(float); +long double logbl(long double); + +long lrint(double); +long lrintf(float); +long lrintl(long double); + +long lround(double); +long lroundf(float); +long lroundl(long double); + +double modf(double, double *); +float modff(float, float *); +long double modfl(long double, long double *); + +double nan(const char *); +float nanf(const char *); +long double nanl(const char *); + +double nearbyint(double); +float nearbyintf(float); +long double nearbyintl(long double); + +double nextafter(double, double); +float nextafterf(float, float); +long double nextafterl(long double, long double); + +double nexttoward(double, long double); +float nexttowardf(float, long double); +long double nexttowardl(long double, long double); + +double pow(double, double); +float powf(float, float); +long double powl(long double, long double); + +double remainder(double, double); +float remainderf(float, float); +long double remainderl(long double, long double); + +double remquo(double, double, int *); +float remquof(float, float, int *); +long double remquol(long double, long double, int *); + +double rint(double); +float rintf(float); +long double rintl(long double); + +double round(double); +float roundf(float); +long double roundl(long double); + +double scalbln(double, long); +float scalblnf(float, long); +long double scalblnl(long double, long); + +double scalbn(double, int); +float scalbnf(float, int); +long double scalbnl(long double, int); + +double sin(double); +float sinf(float); +long double sinl(long double); + +double sinh(double); +float sinhf(float); +long double sinhl(long double); + +double sqrt(double); +float sqrtf(float); +long double sqrtl(long double); + +double tan(double); +float tanf(float); +long double tanl(long double); + +double tanh(double); +float tanhf(float); +long double tanhl(long double); + +double tgamma(double); +float tgammaf(float); +long double tgammal(long double); + +double trunc(double); +float truncf(float); +long double truncl(long double); + diff --git a/inc/signal.h b/inc/signal.h index e8a00c6..ed4f5fb 100644 --- a/inc/signal.h +++ b/inc/signal.h @@ -1,26 +1,26 @@ - -#pragma once - -typedef int sig_atomic_t; - -// TODO: idk about SIG_ERR, for now this -#define SIG_ERR ((void(*)(int))0) -#define SIG_DFL _signal_default_handler -#define SIG_IGN _signal_ignore_handler - -// Note(bumbread): from the impl standpoint the numbers are arbitrary -#define _SIG_MIN 0 -#define SIGINT 1 -#define SIGILL 2 -#define SIGFPE 3 -#define SIGSEGV 4 -#define SIGTERM 5 -#define SIGABRT 6 -// These guys are impl defined -#define SIGBREAK 7 -#define SIGALIGN 8 -#define SIGSTEP 9 -#define _SIG_MAX 9 - -void (*signal(int sig, void (*func)(int)))(int); -int raise(int sig); + +#pragma once + +typedef int sig_atomic_t; + +// TODO: idk about SIG_ERR, for now this +#define SIG_ERR ((void(*)(int))0) +#define SIG_DFL _signal_default_handler +#define SIG_IGN _signal_ignore_handler + +// Note(bumbread): from the impl standpoint the numbers are arbitrary +#define _SIG_MIN 0 +#define SIGINT 1 +#define SIGILL 2 +#define SIGFPE 3 +#define SIGSEGV 4 +#define SIGTERM 5 +#define SIGABRT 6 +// These guys are impl defined +#define SIGBREAK 7 +#define SIGALIGN 8 +#define SIGSTEP 9 +#define _SIG_MAX 9 + +void (*signal(int sig, void (*func)(int)))(int); +int raise(int sig); diff --git a/inc/string.h b/inc/string.h index d7185fa..b0e13d7 100644 --- a/inc/string.h +++ b/inc/string.h @@ -1,65 +1,65 @@ - -#pragma once - -// Technically all we should have here is typedef for size_t. -// but I can't get that without macro shittery so -// for now I'm just doing this, which is not quite correct -#include - -#if !defined(NULL) -#define NULL ((void *)0) -#endif - -#if !defined(__STDC_LIB_EXT1__) -#define __STDC_LIB_EXT1__ -typedef int errno_t; -typedef size_t rsize_t; -#endif - -#if __STDC_WANT_SECURE_LIB__ == 1 -#if !defined(__STDC_WANT_LIB_EXT1__) -#define __STDC_WANT_LIB_EXT1__ 1 -#endif -#endif - -// int _wcsicmp(const wchar_t *string1, const wchar_t *string2); - -void *memcpy(void *restrict s1, const void *restrict s2, size_t n); -void *memmove(void *s1, const void *s2, size_t n); -char *strcpy(char *restrict s1, const char *restrict s2); -char *strncpy(char *restrict s1, const char *restrict s2, size_t n); -char *strcat(char *restrict s1, const char *restrict s2); -char *strncat(char *restrict s1, const char *restrict s2, size_t n); -int memcmp(const void *s1, const void *s2, size_t n); -int strcmp(const char *s1, const char *s2); -int strcoll(const char *s1, const char *s2); -int strncmp(const char *s1, const char *s2, size_t n); -size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n); -void *memchr(const void *s, int c, size_t n); -char *strchr(const char *s, int c); -size_t strcspn(const char *s1, const char *s2); -char *strpbrk(const char *s1, const char *s2); -char *strrchr(const char *s, int c); -size_t strspn(const char *s1, const char *s2); -char *strstr(const char *s1, const char *s2); -char *strtok(char *restrict s1, const char *restrict s2); -void *memset(void *s, int c, size_t n); -char *strerror(int errnum); -size_t strlen(const char *s); - -// Linux extension: reentrant strtok -char *strtok_r(char *restrict s1, const char *restrict s2, char **restrict ctx); - -#if __STDC_WANT_LIB_EXT1__ == 1 -errno_t memcpy_s(void *restrict s1, rsize_t s1max, const void *restrict s2, rsize_t n); -errno_t memmove_s(void *s1, rsize_t s1max, const void *s2, rsize_t n); -errno_t strcpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2); -errno_t strncpy_s(char *restrict s1, rsize_t s1max,const char *restrict s2, rsize_t n); -errno_t strcat_s(char *restrict s1, rsize_t s1max, const char *restrict s2); -errno_t strncat_s(char *restrict s1, rsize_t s1max, const char *restrict s2, rsize_t n); -char *strtok_s(char *restrict s1, rsize_t *restrict s1max, const char *restrict s2, char **restrict ptr); -errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); -errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum); -size_t strerrorlen_s(errno_t errnum); -size_t strnlen_s(const char *str, size_t strsz); -#endif + +#pragma once + +// Technically all we should have here is typedef for size_t. +// but I can't get that without macro shittery so +// for now I'm just doing this, which is not quite correct +#include + +#if !defined(NULL) +#define NULL ((void *)0) +#endif + +#if !defined(__STDC_LIB_EXT1__) +#define __STDC_LIB_EXT1__ +typedef int errno_t; +typedef size_t rsize_t; +#endif + +#if __STDC_WANT_SECURE_LIB__ == 1 +#if !defined(__STDC_WANT_LIB_EXT1__) +#define __STDC_WANT_LIB_EXT1__ 1 +#endif +#endif + +// int _wcsicmp(const wchar_t *string1, const wchar_t *string2); + +void *memcpy(void *restrict s1, const void *restrict s2, size_t n); +void *memmove(void *s1, const void *s2, size_t n); +char *strcpy(char *restrict s1, const char *restrict s2); +char *strncpy(char *restrict s1, const char *restrict s2, size_t n); +char *strcat(char *restrict s1, const char *restrict s2); +char *strncat(char *restrict s1, const char *restrict s2, size_t n); +int memcmp(const void *s1, const void *s2, size_t n); +int strcmp(const char *s1, const char *s2); +int strcoll(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +size_t strxfrm(char *restrict s1, const char *restrict s2, size_t n); +void *memchr(const void *s, int c, size_t n); +char *strchr(const char *s, int c); +size_t strcspn(const char *s1, const char *s2); +char *strpbrk(const char *s1, const char *s2); +char *strrchr(const char *s, int c); +size_t strspn(const char *s1, const char *s2); +char *strstr(const char *s1, const char *s2); +char *strtok(char *restrict s1, const char *restrict s2); +void *memset(void *s, int c, size_t n); +char *strerror(int errnum); +size_t strlen(const char *s); + +// Linux extension: reentrant strtok +char *strtok_r(char *restrict s1, const char *restrict s2, char **restrict ctx); + +#if __STDC_WANT_LIB_EXT1__ == 1 +errno_t memcpy_s(void *restrict s1, rsize_t s1max, const void *restrict s2, rsize_t n); +errno_t memmove_s(void *s1, rsize_t s1max, const void *s2, rsize_t n); +errno_t strcpy_s(char *restrict s1, rsize_t s1max, const char *restrict s2); +errno_t strncpy_s(char *restrict s1, rsize_t s1max,const char *restrict s2, rsize_t n); +errno_t strcat_s(char *restrict s1, rsize_t s1max, const char *restrict s2); +errno_t strncat_s(char *restrict s1, rsize_t s1max, const char *restrict s2, rsize_t n); +char *strtok_s(char *restrict s1, rsize_t *restrict s1max, const char *restrict s2, char **restrict ptr); +errno_t memset_s(void *s, rsize_t smax, int c, rsize_t n); +errno_t strerror_s(char *s, rsize_t maxsize, errno_t errnum); +size_t strerrorlen_s(errno_t errnum); +size_t strnlen_s(const char *str, size_t strsz); +#endif diff --git a/inc/tgmath.h b/inc/tgmath.h index 13e302a..6e7feb2 100644 --- a/inc/tgmath.h +++ b/inc/tgmath.h @@ -1,67 +1,67 @@ - -#pragma once - -/* -these are type generic so they're macrod and use C11's _Generic - -acos -asin -atan -acosh -asinh -atanh -cos -sin -tan -cosh -sinh -tanh -exp -log -pow -sqrt -fabs -atan2 -cbrt -ceil -copysign -erf -erfc -exp2 -expm1 -fdim -floor -fma -fmax -fmin -fmod -frexp -hypot -ilogb -ldexp -lgamma -llrint -llround -log10 -log1p -log2 -logb -lrint -lround -nearbyint -nextafter -nexttoward -remainder -remquo -rint -round -scalbn -scalbln -tgamma -trunc -carg -cimag -conj -cproj -creal + +#pragma once + +/* +these are type generic so they're macrod and use C11's _Generic + +acos +asin +atan +acosh +asinh +atanh +cos +sin +tan +cosh +sinh +tanh +exp +log +pow +sqrt +fabs +atan2 +cbrt +ceil +copysign +erf +erfc +exp2 +expm1 +fdim +floor +fma +fmax +fmin +fmod +frexp +hypot +ilogb +ldexp +lgamma +llrint +llround +log10 +log1p +log2 +logb +lrint +lround +nearbyint +nextafter +nexttoward +remainder +remquo +rint +round +scalbn +scalbln +tgamma +trunc +carg +cimag +conj +cproj +creal */ \ No newline at end of file diff --git a/inc/threads.h b/inc/threads.h index fc65d53..0c36ae6 100644 --- a/inc/threads.h +++ b/inc/threads.h @@ -1,71 +1,71 @@ - -#pragma once - -#include - -#define thread_local _Thread_local -#define ONCE_FLAG_INIT 1 - -#define TSS_DTOR_ITERATIONS 32 - -typedef struct cnd_t { - int idk_yet; -} cnd_t; - -typedef struct thrd_t { - int idk_yet; -} thrd_t; - -typedef struct tss_t { - int idk_yet; -} tss_t; - -typedef struct mtx_t { - int idk_yet; -} mtx_t; - -typedef void(*tss_dtor_t)(void*); -typedef int(*thrd_start_t)(void*); - -// TODO: change this maybe? -typedef int once_flag; - -enum { - mtx_plain = 1, - mtx_recursive = 2, - mtx_timed = 4 -}; - -enum { - thrd_success, - thrd_timedout, - thrd_busy, - thrd_error, - thrd_nomem -}; - -void call_once(once_flag *flag, void (*func)(void)); -int cnd_broadcast(cnd_t *cond); -void cnd_destroy(cnd_t *cond); -int cnd_init(cnd_t *cond); -int cnd_signal(cnd_t *cond); -int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts); -int cnd_wait(cnd_t *cond, mtx_t *mtx); -void mtx_destroy(mtx_t *mtx); -int mtx_init(mtx_t *mtx, int type); -int mtx_lock(mtx_t *mtx); -int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts); -int mtx_trylock(mtx_t *mtx); -int mtx_unlock(mtx_t *mtx); -int thrd_create(thrd_t *thr, thrd_start_t func, void *arg); -thrd_t thrd_current(void); -int thrd_detach(thrd_t thr); -int thrd_equal(thrd_t thr0, thrd_t thr1); -_Noreturn void thrd_exit(int res); -int thrd_join(thrd_t thr, int *res); -int thrd_sleep(const struct timespec *duration, struct timespec *remaining); -void thrd_yield(void); -int tss_create(tss_t *key, tss_dtor_t dtor); -void tss_delete(tss_t key); -void *tss_get(tss_t key); -int tss_set(tss_t key, void *val); + +#pragma once + +#include + +#define thread_local _Thread_local +#define ONCE_FLAG_INIT 1 + +#define TSS_DTOR_ITERATIONS 32 + +typedef struct cnd_t { + int idk_yet; +} cnd_t; + +typedef struct thrd_t { + int idk_yet; +} thrd_t; + +typedef struct tss_t { + int idk_yet; +} tss_t; + +typedef struct mtx_t { + int idk_yet; +} mtx_t; + +typedef void(*tss_dtor_t)(void*); +typedef int(*thrd_start_t)(void*); + +// TODO: change this maybe? +typedef int once_flag; + +enum { + mtx_plain = 1, + mtx_recursive = 2, + mtx_timed = 4 +}; + +enum { + thrd_success, + thrd_timedout, + thrd_busy, + thrd_error, + thrd_nomem +}; + +void call_once(once_flag *flag, void (*func)(void)); +int cnd_broadcast(cnd_t *cond); +void cnd_destroy(cnd_t *cond); +int cnd_init(cnd_t *cond); +int cnd_signal(cnd_t *cond); +int cnd_timedwait(cnd_t *restrict cond, mtx_t *restrict mtx, const struct timespec *restrict ts); +int cnd_wait(cnd_t *cond, mtx_t *mtx); +void mtx_destroy(mtx_t *mtx); +int mtx_init(mtx_t *mtx, int type); +int mtx_lock(mtx_t *mtx); +int mtx_timedlock(mtx_t *restrict mtx, const struct timespec *restrict ts); +int mtx_trylock(mtx_t *mtx); +int mtx_unlock(mtx_t *mtx); +int thrd_create(thrd_t *thr, thrd_start_t func, void *arg); +thrd_t thrd_current(void); +int thrd_detach(thrd_t thr); +int thrd_equal(thrd_t thr0, thrd_t thr1); +_Noreturn void thrd_exit(int res); +int thrd_join(thrd_t thr, int *res); +int thrd_sleep(const struct timespec *duration, struct timespec *remaining); +void thrd_yield(void); +int tss_create(tss_t *key, tss_dtor_t dtor); +void tss_delete(tss_t key); +void *tss_get(tss_t key); +int tss_set(tss_t key, void *val); diff --git a/inc/time.h b/inc/time.h index 2e49983..fbd4968 100644 --- a/inc/time.h +++ b/inc/time.h @@ -1,49 +1,49 @@ -#pragma once -#include - -#if !defined(NULL) -#define NULL ((void *)0) -#endif - -// The number of clock ticks per second -#define CLOCKS_PER_SEC ((clock_t)1000) - -#define TIME_UTC 1 - -typedef size_t clock_t; -typedef size_t time_t; - -struct timespec { - time_t tv_sec; // Seconds - >= 0 - long tv_nsec; // Nanoseconds - [0, 999999999] -}; - -struct tm { - int tm_sec; // seconds after the minute - [0, 60] including leap second - int tm_min; // minutes after the hour - [0, 59] - int tm_hour; // hours since midnight - [0, 23] - int tm_mday; // day of the month - [1, 31] - int tm_mon; // months since January - [0, 11] - int tm_year; // years since 1900 - int tm_wday; // days since Sunday - [0, 6] - int tm_yday; // days since January 1 - [0, 365] - int tm_isdst; // daylight savings time flag -}; - -clock_t clock(void); -double difftime(time_t time1, time_t time0); -time_t mktime(struct tm *timeptr); -time_t time(time_t *timer); -int timespec_get(struct timespec *ts, int base); -char *asctime(const struct tm *timeptr); -char *ctime(const time_t *timer); -struct tm *gmtime(const time_t *timer); -struct tm *localtime(const time_t *timer); -size_t strftime(char * restrict s, size_t maxsize, const char * restrict format, const struct tm * restrict timeptr); - -#ifdef __STDC_WANT_LIB_EXT1__ -errno_t asctime_s(char *s, rsize_t maxsize, const struct tm *timeptr); -errno_t ctime_s(char *s, rsize_t maxsize, const time_t *timer); -struct tm *gmtime_s(const time_t * restrict timer, struct tm * restrict result); -struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result); -#endif +#pragma once +#include + +#if !defined(NULL) +#define NULL ((void *)0) +#endif + +// The number of clock ticks per second +#define CLOCKS_PER_SEC ((clock_t)1000) + +#define TIME_UTC 1 + +typedef size_t clock_t; +typedef size_t time_t; + +struct timespec { + time_t tv_sec; // Seconds - >= 0 + long tv_nsec; // Nanoseconds - [0, 999999999] +}; + +struct tm { + int tm_sec; // seconds after the minute - [0, 60] including leap second + int tm_min; // minutes after the hour - [0, 59] + int tm_hour; // hours since midnight - [0, 23] + int tm_mday; // day of the month - [1, 31] + int tm_mon; // months since January - [0, 11] + int tm_year; // years since 1900 + int tm_wday; // days since Sunday - [0, 6] + int tm_yday; // days since January 1 - [0, 365] + int tm_isdst; // daylight savings time flag +}; + +clock_t clock(void); +double difftime(time_t time1, time_t time0); +time_t mktime(struct tm *timeptr); +time_t time(time_t *timer); +int timespec_get(struct timespec *ts, int base); +char *asctime(const struct tm *timeptr); +char *ctime(const time_t *timer); +struct tm *gmtime(const time_t *timer); +struct tm *localtime(const time_t *timer); +size_t strftime(char * restrict s, size_t maxsize, const char * restrict format, const struct tm * restrict timeptr); + +#ifdef __STDC_WANT_LIB_EXT1__ +errno_t asctime_s(char *s, rsize_t maxsize, const struct tm *timeptr); +errno_t ctime_s(char *s, rsize_t maxsize, const time_t *timer); +struct tm *gmtime_s(const time_t * restrict timer, struct tm * restrict result); +struct tm *localtime_s(const time_t * restrict timer, struct tm * restrict result); +#endif diff --git a/inc/uchar.h b/inc/uchar.h index 66bb9d5..daf6373 100644 --- a/inc/uchar.h +++ b/inc/uchar.h @@ -1,11 +1,11 @@ - -#pragma once - -typedef struct mbstate_t mbstate_t; -typedef uint16_t char16_t; -typedef uint32_t char32_t; - -size_t mbrtoc16(char16_t * restrict pc16, const char * restrict s, size_t n, mbstate_t * restrict ps); -size_t c16rtomb(char * restrict s, char16_t c16, mbstate_t * restrict ps); -size_t mbrtoc32(char32_t * restrict pc32, const char * restrict s, size_t n, mbstate_t * restrict ps); -size_t c32rtomb(char * restrict s, char32_t c32, mbstate_t * restrict ps); + +#pragma once + +typedef struct mbstate_t mbstate_t; +typedef uint16_t char16_t; +typedef uint32_t char32_t; + +size_t mbrtoc16(char16_t * restrict pc16, const char * restrict s, size_t n, mbstate_t * restrict ps); +size_t c16rtomb(char * restrict s, char16_t c16, mbstate_t * restrict ps); +size_t mbrtoc32(char32_t * restrict pc32, const char * restrict s, size_t n, mbstate_t * restrict ps); +size_t c32rtomb(char * restrict s, char32_t c32, mbstate_t * restrict ps); diff --git a/inc/wchar.h b/inc/wchar.h index 73557d9..c406b15 100644 --- a/inc/wchar.h +++ b/inc/wchar.h @@ -1,101 +1,101 @@ - -#pragma once - -// On linux this will be UTF-32, on windows it's UTF-16 (or maybe UCS-2?) -typedef struct mbstate_t mbstate_t; -typedef wchar_t wint_t; - -#define WCHAR_MIN 0x0000 -#define WCHAR_MAX 0xffff - -#ifndef WEOF -#define WEOF 0 -#endif - -int fwprintf(FILE * restrict stream, const wchar_t * restrict format, ...); -int fwscanf(FILE * restrict stream, const wchar_t * restrict format, ...); -int swprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, ...); -int swscanf(const wchar_t * restrict s, const wchar_t * restrict format, ...); -int vfwprintf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); -int vfwscanf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); -int vswprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, va_list arg); -int vswscanf(const wchar_t * restrict s, const wchar_t * restrict format, va_list arg); -int vwprintf(const wchar_t * restrict format, va_list arg); -int vwscanf(const wchar_t * restrict format, va_list arg); -int wprintf(const wchar_t * restrict format, ...); -int wscanf(const wchar_t * restrict format, ...); -wint_t fgetwc(FILE *stream); -wchar_t *fgetws(wchar_t * restrict s, int n, FILE * restrict stream); -wint_t fputwc(wchar_t c, FILE *stream); -int fputws(const wchar_t * restrict s, FILE * restrict stream); -int fwide(FILE *stream, int mode); -wint_t getwc(FILE *stream); -wint_t getwchar(void); -wint_t putwc(wchar_t c, FILE *stream); -wint_t putwchar(wchar_t c); -wint_t ungetwc(wint_t c, FILE *stream); -double wcstod(const wchar_t * restrict nptr, wchar_t ** restrict endptr); -float wcstof(const wchar_t * restrict nptr, wchar_t ** restrict endptr); -long double wcstold(const wchar_t * restrict nptr, wchar_t ** restrict endptr); -long int wcstol(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); -long long int wcstoll(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); -unsigned long int wcstoul(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); -unsigned long long int wcstoull(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); -wchar_t *wcscpy(wchar_t * restrict s1, const wchar_t * restrict s2); -wchar_t *wcsncpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); -wchar_t *wmemcpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); -wchar_t *wmemmove(wchar_t *s1, const wchar_t *s2, size_t n); -wchar_t *wcscat(wchar_t * restrict s1, const wchar_t * restrict s2); -wchar_t *wcsncat(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); -int wcscmp(const wchar_t *s1, const wchar_t *s2); -int wcscoll(const wchar_t *s1, const wchar_t *s2); -int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); -size_t wcsxfrm(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); -int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n); -wchar_t *wcschr(const wchar_t *s, wchar_t c); -size_t wcscspn(const wchar_t *s1, const wchar_t *s2); -wchar_t *wcspbrk(const wchar_t *s1, const wchar_t *s2); -wchar_t *wcsrchr(const wchar_t *s, wchar_t c); -size_t wcsspn(const wchar_t *s1, const wchar_t *s2); -wchar_t *wcsstr(const wchar_t *s1, const wchar_t *s2); -wchar_t *wcstok(wchar_t * restrict s1, const wchar_t * restrict s2, wchar_t ** restrict ptr); -wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); -size_t wcslen(const wchar_t *s); -wchar_t *wmemset(wchar_t *s, wchar_t c, size_t n); -size_t wcsftime(wchar_t * restrict s, size_t maxsize, const wchar_t * restrict format, const struct tm * restrict timeptr); -wint_t btowc(int c); -int wctob(wint_t c); -int mbsinit(const mbstate_t *ps); -size_t mbrlen(const char * restrict s, size_t n, mbstate_t * restrict ps); -size_t mbrtowc(wchar_t * restrict pwc, const char * restrict s, size_t n, mbstate_t * restrict ps); -size_t wcrtomb(char * restrict s, wchar_t wc, mbstate_t * restrict ps); -size_t mbsrtowcs(wchar_t * restrict dst, const char ** restrict src, size_t len, mbstate_t * restrict ps); -size_t wcsrtombs(char * restrict dst, const wchar_t ** restrict src, size_t len, mbstate_t * restrict ps); - -#ifdef __STDC_WANT_LIB_EXT1__ -int fwprintf_s(FILE * restrict stream, const wchar_t * restrict format, ...); -int fwscanf_s(FILE * restrict stream, const wchar_t * restrict format, ...); -int snwprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, ...); -int swprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, ...); -int swscanf_s(const wchar_t * restrict s, const wchar_t * restrict format, ...); -int vfwprintf_s(FILE * restrict stream, const wchar_t * restrict format, va_list arg); -int vfwscanf_s(FILE * restrict stream, const wchar_t * restrict format, va_list arg); -int vsnwprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, va_list arg); -int vswprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, va_list arg); -int vswscanf_s(const wchar_t * restrict s, const wchar_t * restrict format, va_list arg); -int vwprintf_s(const wchar_t * restrict format, va_list arg); -int vwscanf_s(const wchar_t * restrict format, va_list arg); -int wprintf_s(const wchar_t * restrict format, ...); -int wscanf_s(const wchar_t * restrict format, ...); -errno_t wcscpy_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2); -errno_t wcsncpy_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2, rsize_t n); -errno_t wmemcpy_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2, rsize_t n); -errno_t wmemmove_s(wchar_t *s1, rsize_t s1max, const wchar_t *s2, rsize_t n); -errno_t wcscat_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2); -errno_t wcsncat_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2, rsize_t n); -wchar_t *wcstok_s(wchar_t * restrict s1, rsize_t * restrict s1max, const wchar_t * restrict s2, wchar_t ** restrict ptr); -size_t wcsnlen_s(const wchar_t *s, size_t maxsize); -errno_t wcrtomb_s(size_t * restrict retval, char * restrict s, rsize_t smax, wchar_t wc, mbstate_t * restrict ps); -errno_t mbsrtowcs_s(size_t * restrict retval, wchar_t * restrict dst, rsize_t dstmax, const char ** restrict src, rsize_t len, mbstate_t * restrict ps); -errno_t wcsrtombs_s(size_t * restrict retval, char * restrict dst, rsize_t dstmax, const wchar_t ** restrict src, rsize_t len, mbstate_t * restrict ps); -#endif + +#pragma once + +// On linux this will be UTF-32, on windows it's UTF-16 (or maybe UCS-2?) +typedef struct mbstate_t mbstate_t; +typedef wchar_t wint_t; + +#define WCHAR_MIN 0x0000 +#define WCHAR_MAX 0xffff + +#ifndef WEOF +#define WEOF 0 +#endif + +int fwprintf(FILE * restrict stream, const wchar_t * restrict format, ...); +int fwscanf(FILE * restrict stream, const wchar_t * restrict format, ...); +int swprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, ...); +int swscanf(const wchar_t * restrict s, const wchar_t * restrict format, ...); +int vfwprintf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); +int vfwscanf(FILE * restrict stream, const wchar_t * restrict format, va_list arg); +int vswprintf(wchar_t * restrict s, size_t n, const wchar_t * restrict format, va_list arg); +int vswscanf(const wchar_t * restrict s, const wchar_t * restrict format, va_list arg); +int vwprintf(const wchar_t * restrict format, va_list arg); +int vwscanf(const wchar_t * restrict format, va_list arg); +int wprintf(const wchar_t * restrict format, ...); +int wscanf(const wchar_t * restrict format, ...); +wint_t fgetwc(FILE *stream); +wchar_t *fgetws(wchar_t * restrict s, int n, FILE * restrict stream); +wint_t fputwc(wchar_t c, FILE *stream); +int fputws(const wchar_t * restrict s, FILE * restrict stream); +int fwide(FILE *stream, int mode); +wint_t getwc(FILE *stream); +wint_t getwchar(void); +wint_t putwc(wchar_t c, FILE *stream); +wint_t putwchar(wchar_t c); +wint_t ungetwc(wint_t c, FILE *stream); +double wcstod(const wchar_t * restrict nptr, wchar_t ** restrict endptr); +float wcstof(const wchar_t * restrict nptr, wchar_t ** restrict endptr); +long double wcstold(const wchar_t * restrict nptr, wchar_t ** restrict endptr); +long int wcstol(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); +long long int wcstoll(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); +unsigned long int wcstoul(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); +unsigned long long int wcstoull(const wchar_t * restrict nptr, wchar_t ** restrict endptr, int base); +wchar_t *wcscpy(wchar_t * restrict s1, const wchar_t * restrict s2); +wchar_t *wcsncpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); +wchar_t *wmemcpy(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); +wchar_t *wmemmove(wchar_t *s1, const wchar_t *s2, size_t n); +wchar_t *wcscat(wchar_t * restrict s1, const wchar_t * restrict s2); +wchar_t *wcsncat(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); +int wcscmp(const wchar_t *s1, const wchar_t *s2); +int wcscoll(const wchar_t *s1, const wchar_t *s2); +int wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n); +size_t wcsxfrm(wchar_t * restrict s1, const wchar_t * restrict s2, size_t n); +int wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n); +wchar_t *wcschr(const wchar_t *s, wchar_t c); +size_t wcscspn(const wchar_t *s1, const wchar_t *s2); +wchar_t *wcspbrk(const wchar_t *s1, const wchar_t *s2); +wchar_t *wcsrchr(const wchar_t *s, wchar_t c); +size_t wcsspn(const wchar_t *s1, const wchar_t *s2); +wchar_t *wcsstr(const wchar_t *s1, const wchar_t *s2); +wchar_t *wcstok(wchar_t * restrict s1, const wchar_t * restrict s2, wchar_t ** restrict ptr); +wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); +size_t wcslen(const wchar_t *s); +wchar_t *wmemset(wchar_t *s, wchar_t c, size_t n); +size_t wcsftime(wchar_t * restrict s, size_t maxsize, const wchar_t * restrict format, const struct tm * restrict timeptr); +wint_t btowc(int c); +int wctob(wint_t c); +int mbsinit(const mbstate_t *ps); +size_t mbrlen(const char * restrict s, size_t n, mbstate_t * restrict ps); +size_t mbrtowc(wchar_t * restrict pwc, const char * restrict s, size_t n, mbstate_t * restrict ps); +size_t wcrtomb(char * restrict s, wchar_t wc, mbstate_t * restrict ps); +size_t mbsrtowcs(wchar_t * restrict dst, const char ** restrict src, size_t len, mbstate_t * restrict ps); +size_t wcsrtombs(char * restrict dst, const wchar_t ** restrict src, size_t len, mbstate_t * restrict ps); + +#ifdef __STDC_WANT_LIB_EXT1__ +int fwprintf_s(FILE * restrict stream, const wchar_t * restrict format, ...); +int fwscanf_s(FILE * restrict stream, const wchar_t * restrict format, ...); +int snwprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, ...); +int swprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, ...); +int swscanf_s(const wchar_t * restrict s, const wchar_t * restrict format, ...); +int vfwprintf_s(FILE * restrict stream, const wchar_t * restrict format, va_list arg); +int vfwscanf_s(FILE * restrict stream, const wchar_t * restrict format, va_list arg); +int vsnwprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, va_list arg); +int vswprintf_s(wchar_t * restrict s, rsize_t n, const wchar_t * restrict format, va_list arg); +int vswscanf_s(const wchar_t * restrict s, const wchar_t * restrict format, va_list arg); +int vwprintf_s(const wchar_t * restrict format, va_list arg); +int vwscanf_s(const wchar_t * restrict format, va_list arg); +int wprintf_s(const wchar_t * restrict format, ...); +int wscanf_s(const wchar_t * restrict format, ...); +errno_t wcscpy_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2); +errno_t wcsncpy_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2, rsize_t n); +errno_t wmemcpy_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2, rsize_t n); +errno_t wmemmove_s(wchar_t *s1, rsize_t s1max, const wchar_t *s2, rsize_t n); +errno_t wcscat_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2); +errno_t wcsncat_s(wchar_t * restrict s1, rsize_t s1max, const wchar_t * restrict s2, rsize_t n); +wchar_t *wcstok_s(wchar_t * restrict s1, rsize_t * restrict s1max, const wchar_t * restrict s2, wchar_t ** restrict ptr); +size_t wcsnlen_s(const wchar_t *s, size_t maxsize); +errno_t wcrtomb_s(size_t * restrict retval, char * restrict s, rsize_t smax, wchar_t wc, mbstate_t * restrict ps); +errno_t mbsrtowcs_s(size_t * restrict retval, wchar_t * restrict dst, rsize_t dstmax, const char ** restrict src, rsize_t len, mbstate_t * restrict ps); +errno_t wcsrtombs_s(size_t * restrict retval, char * restrict dst, rsize_t dstmax, const wchar_t ** restrict src, rsize_t len, mbstate_t * restrict ps); +#endif diff --git a/inc/wctype.h b/inc/wctype.h index 220c748..0ffaa71 100644 --- a/inc/wctype.h +++ b/inc/wctype.h @@ -1,29 +1,29 @@ - -#pragma once - -typedef int wint_t; -wctrans_t; -wctype_t; - -#ifndef WEOF - #define WEOF 0 -#endif - -int iswalnum(wint_t wc); -int iswalpha(wint_t wc); -int iswblank(wint_t wc); -int iswcntrl(wint_t wc); -int iswdigit(wint_t wc); -int iswgraph(wint_t wc); -int iswlower(wint_t wc); -int iswprint(wint_t wc); -int iswpunct(wint_t wc); -int iswspace(wint_t wc); -int iswupper(wint_t wc); -int iswxdigit(wint_t wc); -int iswctype(wint_t wc, wctype_t desc); -wctype_t wctype(const char *property); -wint_t towlower(wint_t wc); -wint_t towupper(wint_t wc); -wint_t towctrans(wint_t wc, wctrans_t desc); -wctrans_t wctrans(const char *property); + +#pragma once + +typedef int wint_t; +wctrans_t; +wctype_t; + +#ifndef WEOF + #define WEOF 0 +#endif + +int iswalnum(wint_t wc); +int iswalpha(wint_t wc); +int iswblank(wint_t wc); +int iswcntrl(wint_t wc); +int iswdigit(wint_t wc); +int iswgraph(wint_t wc); +int iswlower(wint_t wc); +int iswprint(wint_t wc); +int iswpunct(wint_t wc); +int iswspace(wint_t wc); +int iswupper(wint_t wc); +int iswxdigit(wint_t wc); +int iswctype(wint_t wc, wctype_t desc); +wctype_t wctype(const char *property); +wint_t towlower(wint_t wc); +wint_t towupper(wint_t wc); +wint_t towctrans(wint_t wc, wctrans_t desc); +wctrans_t wctrans(const char *property); diff --git a/test/test5.c b/test/test5.c deleted file mode 100644 index 856970f..0000000 --- a/test/test5.c +++ /dev/null @@ -1,22 +0,0 @@ - -#include -#include - -void test_sqrt(float f) { - float s = sqrtf(f); - printf("sqrt of %f is %f\n", f, s); -} - -int main() { - test_sqrt(0.0f); - test_sqrt(1.0f); - test_sqrt(2.0f); - test_sqrt(3.0f); - test_sqrt(4.0f); - test_sqrt(7.0f); - test_sqrt(9.0f); - test_sqrt(16.0f); - test_sqrt(256.0f); - test_sqrt(257.0f); - return 0; -} diff --git a/test/test_math.c b/test/test_math.c new file mode 100644 index 0000000..7571480 --- /dev/null +++ b/test/test_math.c @@ -0,0 +1,76 @@ + +#include +#include +#include +#include + +const char *show_classification(double x) { + switch(fpclassify(x)) { + case FP_INFINITE: return "Inf"; + case FP_NAN: return "NaN"; + case FP_NORMAL: return "normal"; + case FP_SUBNORMAL: return "subnormal"; + case FP_ZERO: return "zero"; + default: return "unknown"; + } +} + +int main() { + + printf("\n=== fpclassify === \n"); + double zero = 0.0; // fucken msvc + printf("1.0/0.0 is %s\n", show_classification(1.0/zero)); + printf("0.0/0.0 is %s\n", show_classification(0.0/zero)); + printf("DBL_MIN/2 is %s\n", show_classification(DBL_MIN/2)); + printf("-0.0 is %s\n", show_classification(-0.0)); + printf("1.0 is %s\n", show_classification(1.0)); + + printf("\n\n=== signbit === \n"); + printf("signbit(+0.0) = %d\n", signbit(+0.0)); + printf("signbit(-0.0) = %d\n", signbit(-0.0)); + + printf("\n\n=== copysign === \n"); + printf("copysign(1.0,+2.0) = %f\n", copysign(1.0,+2.0)); + printf("copysign(1.0,-2.0) = %f\n", copysign(1.0,-2.0)); + printf("copysign(INFINITY,-2.0) = %f\n", copysign(INFINITY,-2.0)); + printf("copysign(NAN,-2.0) = %f\n", copysign(NAN,-2.0)); + + printf("\n\n=== rint === \n"); + fesetround(FE_TONEAREST); + printf("rounding to nearest (halfway cases to even):\n" + "rint(+2.3) = %f ", rint(2.3)); + printf("rint(+2.5) = %f ", rint(2.5)); + printf("rint(+3.5) = %f\n", rint(3.5)); + printf("rint(-2.3) = %f ", rint(-2.3)); + printf("rint(-2.5) = %f ", rint(-2.5)); + printf("rint(-3.5) = %f\n", rint(-3.5)); + fesetround(FE_DOWNWARD); + printf("rounding down: \nrint(+2.3) = %f ", rint(2.3)); + printf("rint(+2.5) = %f ", rint(2.5)); + printf("rint(+3.5) = %f\n", rint(3.5)); + printf("rint(-2.3) = %f ", rint(-2.3)); + printf("rint(-2.5) = %f ", rint(-2.5)); + printf("rint(-3.5) = %f\n", rint(-3.5)); + feclearexcept(FE_ALL_EXCEPT); + printf("rint(1.1) = %f\n", rint(1.1)); + if(fetestexcept(FE_INEXACT)) printf(" FE_INEXACT was raised\n"); + + + float from1 = 0, to1 = nextafterf(from1, 1); + printf("The next representable float after %f is %f\n", from1, to1); + float from2 = 1, to2 = nextafterf(from2, 2); + printf("The next representable float after %f is %f\n", from2, to2); + { + #pragma STDC FENV_ACCESS ON + feclearexcept(FE_ALL_EXCEPT); + double from4 = DBL_MAX, to4 = nextafter(from4, INFINITY); + printf("The next representable double after %f is %f\n", + from4, to4); + if(fetestexcept(FE_OVERFLOW)) printf(" raised FE_OVERFLOW\n"); + if(fetestexcept(FE_INEXACT)) printf(" raised FE_INEXACT\n"); + } + float from5 = 0.0, to5 = nextafter(from5, -0.0); + printf("nextafter(+0.0, -0.0) gives %f (%f)\n", to5, to5); + + return 0; +}