mirror of https://github.com/flysand7/ciabatta.git
Steal some math funcs
This commit is contained in:
parent
6f57efcaa9
commit
2320a22706
109
bake.cmd
109
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,264 @@
|
|||
|
||||
#include <math.h>
|
||||
#include <fenv.h>
|
||||
#include <stdint.h>
|
||||
#include <float.h>
|
||||
|
||||
#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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// 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
|
103
code/math/pow.h
103
code/math/pow.h
|
@ -1,103 +0,0 @@
|
|||
|
||||
#include <errno.h>
|
||||
|
||||
#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);
|
||||
}
|
438
code/printf.h
438
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 <math.h>
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
|
|
278
code/stdio.c
278
code/stdio.c
|
@ -1,139 +1,139 @@
|
|||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <_os.h>
|
||||
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
#include <string.h>
|
||||
|
||||
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 <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <stdbool.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <_os.h>
|
||||
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
#include <string.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
32
inc/ctype.h
32
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);
|
||||
|
|
18
inc/errno.h
18
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;
|
||||
|
|
120
inc/fenv.h
120
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
|
90
inc/locale.h
90
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);
|
||||
|
|
522
inc/math.h
522
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);
|
||||
|
||||
|
|
52
inc/signal.h
52
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);
|
||||
|
|
130
inc/string.h
130
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 <stddef.h>
|
||||
|
||||
#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 <stddef.h>
|
||||
|
||||
#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
|
||||
|
|
132
inc/tgmath.h
132
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
|
||||
*/
|
142
inc/threads.h
142
inc/threads.h
|
@ -1,71 +1,71 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#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 <time.h>
|
||||
|
||||
#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);
|
||||
|
|
98
inc/time.h
98
inc/time.h
|
@ -1,49 +1,49 @@
|
|||
#pragma once
|
||||
#include <stddef.h>
|
||||
|
||||
#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 <stddef.h>
|
||||
|
||||
#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
|
||||
|
|
22
inc/uchar.h
22
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);
|
||||
|
|
202
inc/wchar.h
202
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
|
||||
|
|
58
inc/wctype.h
58
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);
|
||||
|
|
22
test/test5.c
22
test/test5.c
|
@ -1,22 +0,0 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <fenv.h>
|
||||
|
||||
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;
|
||||
}
|
Loading…
Reference in New Issue