├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── bench ├── double │ ├── cbrt.c │ ├── common.h │ ├── cos.c │ ├── cosh.c │ ├── exp.c │ ├── exp2.c │ ├── expm1.c │ ├── log.c │ ├── log10.c │ ├── log1p.c │ ├── log2.c │ ├── logb.c │ ├── sin.c │ ├── sinh.c │ ├── tan.c │ └── tanh.c └── float │ ├── acosf.c │ ├── acoshf.c │ ├── asinf.c │ ├── asinhf.c │ ├── atanf.c │ ├── atanhf.c │ ├── cbrtf.c │ ├── common.h │ ├── cosf.c │ ├── coshf.c │ ├── erfcf.c │ ├── erff.c │ ├── exp2f.c │ ├── expf.c │ ├── expm1f.c │ ├── lgammaf.c │ ├── log10f.c │ ├── log1pf.c │ ├── log2f.c │ ├── logbf.c │ ├── logf.c │ ├── sinf.c │ ├── sinhf.c │ ├── tanf.c │ ├── tanhf.c │ └── tgammaf.c ├── include ├── assert.h ├── bits │ ├── cmathcalls.h │ ├── mathcalls.h │ ├── null.h │ ├── specifiers.h │ └── types │ │ ├── loff.h │ │ ├── mbstate.h │ │ └── timespec.h ├── complex.h ├── ctype.h ├── errno.h ├── fcntl.h ├── fenv.h ├── float.h ├── iso646.h ├── limits.h ├── math.h ├── stdalign.h ├── stdarg.h ├── stdbool.h ├── stddef.h ├── stdint.h ├── stdio.h ├── stdlib.h ├── stdnoreturn.h ├── string.h ├── sys │ └── stat.h ├── tgmath.h ├── time.h ├── wchar.h └── wctype.h ├── src ├── crt │ └── crt1.c ├── ctype │ ├── isalnum.c │ ├── isalpha.c │ ├── isblank.c │ ├── iscntrl.c │ ├── isdigit.c │ ├── isgraph.c │ ├── islower.c │ ├── isprint.c │ ├── ispunct.c │ ├── isspace.c │ ├── isupper.c │ ├── isxdigit.c │ ├── tolower.c │ └── toupper.c ├── errno │ └── errno.c ├── fenv │ ├── feclearexcept.c │ ├── fegetenv.c │ ├── fegetexceptflag.c │ ├── fegetround.c │ ├── feholdexcept.c │ ├── feraiseexcept.c │ ├── fesetenv.c │ ├── fesetexceptflag.c │ ├── fesetround.c │ ├── fetestexcept.c │ └── feupdateenv.c ├── math │ ├── double │ │ ├── cbrt.c │ │ ├── ceil.c │ │ ├── ceil.h │ │ ├── cis.h │ │ ├── cos.c │ │ ├── cosh.c │ │ ├── divs.h │ │ ├── erf.c │ │ ├── erfc.c │ │ ├── exp.c │ │ ├── exp2.c │ │ ├── expm1.c │ │ ├── fabs.c │ │ ├── fdim.c │ │ ├── floor.c │ │ ├── floor.h │ │ ├── fma.c │ │ ├── fmax.c │ │ ├── fmin.c │ │ ├── fmod.c │ │ ├── fmod.h │ │ ├── frexp.c │ │ ├── hypot.c │ │ ├── ilogb.c │ │ ├── kernel │ │ │ ├── exp.h │ │ │ ├── expm1.h │ │ │ ├── log.h │ │ │ └── sincos.h │ │ ├── llrint.c │ │ ├── llround.c │ │ ├── log.c │ │ ├── log10.c │ │ ├── log1p.c │ │ ├── log2.c │ │ ├── logb.c │ │ ├── lrint.c │ │ ├── lround.c │ │ ├── modf.c │ │ ├── nan.c │ │ ├── nextafter.c │ │ ├── normalize.h │ │ ├── pow.c │ │ ├── rem_pio2.c │ │ ├── remainder.c │ │ ├── remquo.c │ │ ├── remquo.h │ │ ├── rint.c │ │ ├── rint.h │ │ ├── round.c │ │ ├── round.h │ │ ├── scalbln.c │ │ ├── scalbn.c │ │ ├── scalbn.h │ │ ├── shift.h │ │ ├── sin.c │ │ ├── sinh.c │ │ ├── split.h │ │ ├── sqrt.c │ │ ├── tan.c │ │ ├── tanh.c │ │ ├── trunc.c │ │ ├── trunc.h │ │ └── truncate.h │ ├── float │ │ ├── acosf.c │ │ ├── acoshf.c │ │ ├── asinf.c │ │ ├── asinhf.c │ │ ├── atan2f.c │ │ ├── atan2f.h │ │ ├── atanf.c │ │ ├── atanhf.c │ │ ├── cabsf.c │ │ ├── cacosf.c │ │ ├── cacoshf.c │ │ ├── cacoshf.h │ │ ├── cargf.c │ │ ├── casinf.c │ │ ├── casinhf.c │ │ ├── casinhf.h │ │ ├── catanf.c │ │ ├── catanf.h │ │ ├── catanhf.c │ │ ├── cbrtf.c │ │ ├── ccosf.c │ │ ├── ccoshf.c │ │ ├── ccoshf.h │ │ ├── ceilf.c │ │ ├── ceilf.h │ │ ├── cexpf.c │ │ ├── cimagf.c │ │ ├── cisf.h │ │ ├── clogf.c │ │ ├── clogf.h │ │ ├── conjf.c │ │ ├── cosf.c │ │ ├── coshf.c │ │ ├── cpowf.c │ │ ├── cprojf.c │ │ ├── crealf.c │ │ ├── csinf.c │ │ ├── csinhf.c │ │ ├── csinhf.h │ │ ├── csqrtf.c │ │ ├── ctanf.c │ │ ├── ctanhf.c │ │ ├── erfcf.c │ │ ├── erff.c │ │ ├── exp2f.c │ │ ├── exp2f.h │ │ ├── expf.c │ │ ├── expf.h │ │ ├── expm1f.c │ │ ├── expm1f.h │ │ ├── fabsf.c │ │ ├── fdimf.c │ │ ├── finite │ │ │ ├── cashf.h │ │ │ ├── csqrt.h │ │ │ ├── log1pf.h │ │ │ ├── log2f.h │ │ │ └── sinpif.h │ │ ├── floorf.c │ │ ├── floorf.h │ │ ├── fmaf.c │ │ ├── fmaf.h │ │ ├── fmaxf.c │ │ ├── fminf.c │ │ ├── fmodf.c │ │ ├── fmodf.h │ │ ├── frexpf.c │ │ ├── hypotf.c │ │ ├── ilogbf.c │ │ ├── kernel │ │ │ ├── atanf.h │ │ │ ├── atanh.h │ │ │ ├── atanhf.h │ │ │ ├── exp2f.h │ │ │ ├── expf.h │ │ │ ├── lanczos.h │ │ │ ├── sincosf.h │ │ │ └── sinf.h │ │ ├── lgammaf.c │ │ ├── llrintf.c │ │ ├── llroundf.c │ │ ├── log10f.c │ │ ├── log1pf.c │ │ ├── log2f.c │ │ ├── logbf.c │ │ ├── logf.c │ │ ├── lrintf.c │ │ ├── lroundf.c │ │ ├── modff.c │ │ ├── nanf.c │ │ ├── nextafterf.c │ │ ├── normalizef.h │ │ ├── powf.c │ │ ├── rem_pio2f.c │ │ ├── remainderf.c │ │ ├── remquof.c │ │ ├── remquof.h │ │ ├── rintf.c │ │ ├── rintf.h │ │ ├── roundf.c │ │ ├── roundf.h │ │ ├── scalblnf.c │ │ ├── scalbnf.c │ │ ├── scalbnf.h │ │ ├── sinf.c │ │ ├── sinhf.c │ │ ├── sqrtf.c │ │ ├── tanf.c │ │ ├── tanhf.c │ │ ├── tgammaf.c │ │ ├── truncf.c │ │ └── truncf.h │ ├── long-double │ │ ├── normalizel.h │ │ ├── sqrtl.c │ │ └── truncl.c │ ├── reinterpret.h │ └── rounding.h ├── soft │ ├── complex │ │ ├── complex.h │ │ ├── divdc3.c │ │ ├── division.h │ │ ├── divsc3.c │ │ ├── muldc3.c │ │ ├── mulsc3.c │ │ └── multiplication.h │ ├── float │ │ ├── addtf3.c │ │ ├── cmptf2.c │ │ ├── compose │ │ │ └── product.h │ │ ├── divtf3.c │ │ ├── eqtf2.c │ │ ├── extenddftf2.c │ │ ├── extendsftf2.c │ │ ├── fixtfdi.c │ │ ├── fixtfsi.c │ │ ├── fixtfti.c │ │ ├── fixunstfdi.c │ │ ├── fixunstfdi.h │ │ ├── fixunstfsi.c │ │ ├── fixunstfti.c │ │ ├── fixunstfti.h │ │ ├── floatditf.c │ │ ├── floatsitf.c │ │ ├── floattitf.c │ │ ├── floatunditf.c │ │ ├── floatunsitf.c │ │ ├── floatuntitf.c │ │ ├── isnanl.h │ │ ├── multf3.c │ │ ├── trunctfdf2.c │ │ ├── trunctfsf2.c │ │ ├── unordtf2.c │ │ └── unordtf2.h │ ├── integer │ │ ├── ashlti3.c │ │ ├── ashrti3.c │ │ ├── clzti2.h │ │ ├── divti3.c │ │ ├── fixdfti.c │ │ ├── fixdfti.h │ │ ├── fixsfti.c │ │ ├── fixsfti.h │ │ ├── fixunsdfti.c │ │ ├── fixunsdfti.h │ │ ├── fixunssfti.c │ │ ├── fixunssfti.h │ │ ├── floattidf.c │ │ ├── floattidf.h │ │ ├── floattisf.c │ │ ├── floattisf.h │ │ ├── floatuntidf.c │ │ ├── floatuntidf.h │ │ ├── floatuntisf.c │ │ ├── floatuntisf.h │ │ ├── lshrti3.c │ │ ├── modti3.c │ │ ├── multi3.c │ │ ├── udivmodti4.c │ │ ├── udivmodti4.h │ │ ├── udivti3.c │ │ ├── umodti3.c │ │ ├── umulditi3.h │ │ └── umulti4.h │ └── powi │ │ ├── powi.h │ │ ├── powidf2.c │ │ └── powisf2.c ├── stdio │ ├── FILE.h │ ├── FILE_.h │ ├── _close.c │ ├── _read.c │ ├── _seek.c │ ├── _write.c │ ├── clearerr.c │ ├── fclose.c │ ├── feof.c │ ├── ferror.c │ ├── fgetpos.c │ ├── flush.h │ ├── fopen.c │ ├── fprintf.c │ ├── fputs.c │ ├── fread.c │ ├── freopen.c │ ├── fseek.c │ ├── fsetpos.c │ ├── ftell.c │ ├── fwrite.c │ ├── getc.c │ ├── getc.h │ ├── getchar.c │ ├── gets.c │ ├── modeflags.h │ ├── printf.c │ ├── putc.c │ ├── putc.h │ ├── putchar.c │ ├── puts.c │ ├── remove.c │ ├── rename.c │ ├── rewind.c │ ├── stderr.c │ ├── stdin.c │ ├── stdout.c │ ├── ungetc.c │ ├── vfprintf.c │ ├── vprintf.c │ ├── vsnprintf.c │ └── vsprintf.c ├── stdlib │ ├── abs.c │ ├── abs.h │ ├── atoi.c │ ├── atoi.h │ ├── atol.c │ ├── atoll.c │ ├── bsearch.c │ ├── div.c │ ├── div.h │ ├── labs.c │ ├── ldiv.c │ ├── llabs.c │ ├── lldiv.c │ ├── malloc.c │ ├── parse │ │ ├── digit.h │ │ ├── float.h │ │ ├── integer.h │ │ ├── nan.h │ │ ├── scientific.h │ │ └── scientificf.h │ ├── qsort.c │ ├── rand.c │ ├── strtod.c │ ├── strtof.c │ ├── strtol.c │ ├── strtoll.c │ ├── strtoul.c │ ├── strtoull.c │ └── system.c ├── string │ ├── aliased.h │ ├── copy.h │ ├── memchr.c │ ├── memcmp.c │ ├── memcpy.c │ ├── memmove.c │ ├── memset.c │ ├── strcat.c │ ├── strchr.c │ ├── strcmp.c │ ├── strcpy.c │ ├── strcspn.c │ ├── strlen.c │ ├── strncat.c │ ├── strncmp.c │ ├── strncpy.c │ ├── strpbrk.c │ ├── strrchr.c │ ├── strspn.c │ ├── strstr.c │ └── strtok.c ├── sys │ ├── stat │ │ ├── fstat.c │ │ ├── lstat.c │ │ └── stat.c │ └── syscall.h ├── time │ ├── time.c │ └── timespec_get.c ├── unistd │ └── sbrk.c └── wchar │ └── wcrtomb.c └── test ├── native ├── assertf.h ├── math │ ├── double │ │ ├── binary.h │ │ ├── cbrt.c │ │ ├── ceil.c │ │ ├── cos.c │ │ ├── cosh.c │ │ ├── erf.c │ │ ├── erfc.c │ │ ├── exp.c │ │ ├── exp2.c │ │ ├── expm1.c │ │ ├── floor.c │ │ ├── fmod.c │ │ ├── log.c │ │ ├── log.h │ │ ├── log10.c │ │ ├── log1p.c │ │ ├── log2.c │ │ ├── pow.c │ │ ├── remquo.c │ │ ├── rint.c │ │ ├── round.c │ │ ├── sin.c │ │ ├── sinh.c │ │ ├── tan.c │ │ ├── tanh.c │ │ ├── trunc.c │ │ └── unary.h │ └── float │ │ ├── acosf.c │ │ ├── acoshf.c │ │ ├── asinf.c │ │ ├── asinhf.c │ │ ├── atan2f.c │ │ ├── atanf.c │ │ ├── atanhf.c │ │ ├── binary.h │ │ ├── cacoshf.c │ │ ├── casinhf.c │ │ ├── catanf.c │ │ ├── cbrtf.c │ │ ├── ccoshf.c │ │ ├── ceilf.c │ │ ├── cexpf.c │ │ ├── clogf.c │ │ ├── complex.h │ │ ├── cosf.c │ │ ├── coshf.c │ │ ├── csinhf.c │ │ ├── csqrtf.c │ │ ├── ctanhf.c │ │ ├── erfcf.c │ │ ├── erff.c │ │ ├── exp.h │ │ ├── exp2f.c │ │ ├── expf.c │ │ ├── expm1f.c │ │ ├── floorf.c │ │ ├── fmodf.c │ │ ├── hypotf.c │ │ ├── lgammaf.c │ │ ├── log.h │ │ ├── log10f.c │ │ ├── log1pf.c │ │ ├── log2f.c │ │ ├── logf.c │ │ ├── powf.c │ │ ├── remquof.c │ │ ├── rintf.c │ │ ├── roundf.c │ │ ├── sinf.c │ │ ├── sinhf.c │ │ ├── tanf.c │ │ ├── tanhf.c │ │ ├── tgammaf.c │ │ ├── truncf.c │ │ └── unary.h ├── soft │ ├── float │ │ ├── isnanl.c │ │ └── unary.h │ └── integer │ │ ├── fixdfti.c │ │ ├── fixsfti.c │ │ ├── fixunsdfti.c │ │ ├── fixunssfti.c │ │ ├── floattidf.c │ │ ├── floattisf.c │ │ ├── floatuntidf.c │ │ ├── floatuntisf.c │ │ └── umulti4.c └── stdlib │ ├── strtod.c │ └── strtof.c └── wasm ├── crt └── argv.c ├── math ├── double │ ├── fdim.c │ ├── frexp.c │ ├── identical.h │ ├── ilogb.c │ ├── logb.c │ ├── lround.c │ ├── nextafter.c │ └── scalbn.c ├── float │ ├── cabsf.c │ ├── cacosf.c │ ├── cargf.c │ ├── casinf.c │ ├── catanhf.c │ ├── ccosf.c │ ├── cidentical.h │ ├── csinf.c │ ├── ctanf.c │ ├── fdimf.c │ ├── fmaf.c │ ├── frexpf.c │ ├── identical.h │ ├── ilogbf.c │ ├── logbf.c │ ├── nextafterf.c │ └── scalbnf.c └── long-double │ └── sqrtl.c ├── soft ├── float │ ├── addtf3.c │ ├── divtf3.c │ ├── extenddftf2.c │ ├── extendsftf2.c │ ├── fixtfdi.c │ ├── fixtfsi.c │ ├── fixtfti.c │ ├── fixunstfdi.c │ ├── fixunstfsi.c │ ├── fixunstfti.c │ ├── floatditf.c │ ├── floatsitf.c │ ├── floatunditf.c │ ├── floatunsitf.c │ └── multf3.c └── integer │ ├── ashlti3.c │ ├── ashrti3.c │ ├── lshrti3.c │ ├── multi3.c │ └── udivmodti4.c ├── stdio ├── feof.c ├── fopen.c ├── fseek.c ├── printf.c └── ungetc.c ├── stdlib ├── qsort.c ├── strtof.c ├── strtol.c ├── strtoll.c ├── strtoul.c └── strtoull.c └── time └── timespec.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | -------------------------------------------------------------------------------- /bench/double/cbrt.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define cbrt(x) metallic_cbrt(x) 6 | #include "src/math/double/cbrt.c" 7 | #undef cbrt 8 | 9 | BENCH(cbrt) 10 | -------------------------------------------------------------------------------- /bench/double/common.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | static double bench(double f(double)) 6 | { 7 | volatile double dummy; 8 | clock_t start = clock(); 9 | 10 | for (uint64_t i = 0x7FF8000000000000; i <= 0xFFF0000000000000; i += 0x0000000893205C62) { 11 | double x = reinterpret(double, i); 12 | dummy = f(x); 13 | dummy = f(-x); 14 | } 15 | 16 | return (double)(clock() - start) / CLOCKS_PER_SEC; 17 | dummy; 18 | } 19 | 20 | #define BENCH(f) int main(void) { printf("%9f\n%9f\n", bench(metallic_##f), bench(f)); } 21 | -------------------------------------------------------------------------------- /bench/double/cos.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/rem_pio2.c" 2 | #include "common.h" 3 | #include 4 | #include 5 | 6 | #define cos(x) metallic_cos(x) 7 | #include "src/math/double/cos.c" 8 | #undef cos 9 | 10 | BENCH(cos) 11 | -------------------------------------------------------------------------------- /bench/double/cosh.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define cosh(x) metallic_cosh(x) 6 | #include "src/math/double/cosh.c" 7 | #undef cosh 8 | 9 | BENCH(cosh) 10 | -------------------------------------------------------------------------------- /bench/double/exp.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define exp(x) metallic_exp(x) 6 | #include "src/math/double/exp.c" 7 | #undef exp 8 | 9 | BENCH(exp) 10 | -------------------------------------------------------------------------------- /bench/double/exp2.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define exp2(x) metallic_exp2(x) 6 | #include "src/math/double/exp2.c" 7 | #undef exp2 8 | 9 | BENCH(exp2) 10 | -------------------------------------------------------------------------------- /bench/double/expm1.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define expm1(x) metallic_expm1(x) 6 | #include "src/math/double/expm1.c" 7 | #undef expm1 8 | 9 | BENCH(expm1) 10 | -------------------------------------------------------------------------------- /bench/double/log.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define log(x) metallic_log(x) 6 | #include "src/math/double/log.c" 7 | #undef log 8 | 9 | BENCH(log) 10 | -------------------------------------------------------------------------------- /bench/double/log10.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define log10(x) metallic_log10(x) 6 | #include "src/math/double/log10.c" 7 | #undef log10 8 | 9 | BENCH(log10) 10 | -------------------------------------------------------------------------------- /bench/double/log1p.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define log1p(x) metallic_log1p(x) 6 | #include "src/math/double/log1p.c" 7 | #undef log1p 8 | 9 | BENCH(log1p) 10 | -------------------------------------------------------------------------------- /bench/double/log2.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define log2(x) metallic_log2(x) 6 | #include "src/math/double/log2.c" 7 | #undef log2 8 | 9 | BENCH(log2) 10 | -------------------------------------------------------------------------------- /bench/double/logb.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define logb(x) metallic_logb(x) 6 | #include "src/math/double/logb.c" 7 | #undef logb 8 | 9 | BENCH(logb) 10 | -------------------------------------------------------------------------------- /bench/double/sin.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/rem_pio2.c" 2 | #include "common.h" 3 | #include 4 | #include 5 | 6 | #define sin(x) metallic_sin(x) 7 | #include "src/math/double/sin.c" 8 | #undef sin 9 | 10 | BENCH(sin) 11 | -------------------------------------------------------------------------------- /bench/double/sinh.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define sinh(x) metallic_sinh(x) 6 | #include "src/math/double/sinh.c" 7 | #undef sinh 8 | 9 | BENCH(sinh) 10 | -------------------------------------------------------------------------------- /bench/double/tan.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/rem_pio2.c" 2 | #include "common.h" 3 | #include 4 | #include 5 | 6 | #define tan(x) metallic_tan(x) 7 | #include "src/math/double/tan.c" 8 | #undef tan 9 | 10 | BENCH(tan) 11 | -------------------------------------------------------------------------------- /bench/double/tanh.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define tanh(x) metallic_tanh(x) 6 | #include "src/math/double/tanh.c" 7 | #undef tanh 8 | 9 | BENCH(tanh) 10 | -------------------------------------------------------------------------------- /bench/float/acosf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define acosf(x) metallic_acosf(x) 6 | #include "src/math/float/acosf.c" 7 | #undef acosf 8 | 9 | BENCH(acosf) 10 | -------------------------------------------------------------------------------- /bench/float/acoshf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define acoshf(x) metallic_acoshf(x) 6 | #include "src/math/float/acoshf.c" 7 | #undef acoshf 8 | 9 | BENCH(acoshf) 10 | -------------------------------------------------------------------------------- /bench/float/asinf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define asinf(x) metallic_asinf(x) 6 | #include "src/math/float/asinf.c" 7 | #undef asinf 8 | 9 | BENCH(asinf) 10 | -------------------------------------------------------------------------------- /bench/float/asinhf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define asinhf(x) metallic_asinhf(x) 6 | #include "src/math/float/asinhf.c" 7 | #undef asinhf 8 | 9 | BENCH(asinhf) 10 | -------------------------------------------------------------------------------- /bench/float/atanf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define atanf(x) metallic_atanf(x) 6 | #include "src/math/float/atanf.c" 7 | #undef atanf 8 | 9 | BENCH(atanf) 10 | -------------------------------------------------------------------------------- /bench/float/atanhf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define atanhf(x) metallic_atanhf(x) 6 | #include "src/math/float/atanhf.c" 7 | #undef atanhf 8 | 9 | BENCH(atanhf) 10 | -------------------------------------------------------------------------------- /bench/float/cbrtf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define cbrtf(x) metallic_cbrtf(x) 6 | #include "src/math/float/cbrtf.c" 7 | #undef cbrtf 8 | 9 | BENCH(cbrtf) 10 | -------------------------------------------------------------------------------- /bench/float/common.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | static double bench(float f(float)) 6 | { 7 | volatile float dummy; 8 | clock_t start = clock(); 9 | 10 | for (uint32_t i = 0x7FF00000; i <= 0xFF800000; i += 19) { 11 | double x = reinterpret(float, i); 12 | dummy = f(x); 13 | dummy = f(-x); 14 | } 15 | 16 | return (double)(clock() - start) / CLOCKS_PER_SEC; 17 | dummy; 18 | } 19 | 20 | #define BENCH(f) int main(void) { printf("%9f\n%9f\n", bench(metallic_##f), bench(f)); } 21 | -------------------------------------------------------------------------------- /bench/float/cosf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/rem_pio2f.c" 2 | #include "common.h" 3 | #include 4 | #include 5 | 6 | #define cosf(x) metallic_cosf(x) 7 | #include "src/math/float/cosf.c" 8 | #undef cosf 9 | 10 | BENCH(cosf) 11 | -------------------------------------------------------------------------------- /bench/float/coshf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define coshf(x) metallic_coshf(x) 6 | #include "src/math/float/coshf.c" 7 | #undef coshf 8 | 9 | BENCH(coshf) 10 | -------------------------------------------------------------------------------- /bench/float/erfcf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define erfcf(x) metallic_erfcf(x) 6 | #include "src/math/float/erfcf.c" 7 | #undef erfcf 8 | 9 | BENCH(erfcf) 10 | -------------------------------------------------------------------------------- /bench/float/erff.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define erff(x) metallic_erff(x) 6 | #include "src/math/float/erff.c" 7 | #undef erff 8 | 9 | BENCH(erff) 10 | -------------------------------------------------------------------------------- /bench/float/exp2f.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define exp2f(x) metallic_exp2f(x) 6 | #include "src/math/float/exp2f.c" 7 | #undef exp2f 8 | 9 | BENCH(exp2f) 10 | -------------------------------------------------------------------------------- /bench/float/expf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define expf(x) metallic_expf(x) 6 | #include "src/math/float/expf.c" 7 | #undef expf 8 | 9 | BENCH(expf) 10 | -------------------------------------------------------------------------------- /bench/float/expm1f.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define expm1f(x) metallic_expm1f(x) 6 | #include "src/math/float/expm1f.c" 7 | #undef expm1f 8 | 9 | BENCH(expm1f) 10 | -------------------------------------------------------------------------------- /bench/float/lgammaf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define lgammaf(x) metallic_lgammaf(x) 6 | #include "src/math/float/lgammaf.c" 7 | #undef lgammaf 8 | 9 | BENCH(lgammaf) 10 | -------------------------------------------------------------------------------- /bench/float/log10f.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define log10f(x) metallic_log10f(x) 6 | #include "src/math/float/log10f.c" 7 | #undef log10f 8 | 9 | BENCH(log10f) 10 | -------------------------------------------------------------------------------- /bench/float/log1pf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define log1pf(x) metallic_log1pf(x) 6 | #include "src/math/float/log1pf.c" 7 | #undef log1pf 8 | 9 | BENCH(log1pf) 10 | -------------------------------------------------------------------------------- /bench/float/log2f.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define log2f(x) metallic_log2f(x) 6 | #include "src/math/float/log2f.c" 7 | #undef log2f 8 | 9 | BENCH(log2f) 10 | -------------------------------------------------------------------------------- /bench/float/logbf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define logbf(x) metallic_logbf(x) 6 | #include "src/math/float/logbf.c" 7 | #undef logbf 8 | 9 | BENCH(logbf) 10 | -------------------------------------------------------------------------------- /bench/float/logf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define logf(x) metallic_logf(x) 6 | #include "src/math/float/logf.c" 7 | #undef logf 8 | 9 | BENCH(logf) 10 | -------------------------------------------------------------------------------- /bench/float/sinf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/rem_pio2f.c" 2 | #include "common.h" 3 | #include 4 | #include 5 | 6 | #define sinf(x) metallic_sinf(x) 7 | #include "src/math/float/sinf.c" 8 | #undef sinf 9 | 10 | BENCH(sinf) 11 | -------------------------------------------------------------------------------- /bench/float/sinhf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define sinhf(x) metallic_sinhf(x) 6 | #include "src/math/float/sinhf.c" 7 | #undef sinhf 8 | 9 | BENCH(sinhf) 10 | -------------------------------------------------------------------------------- /bench/float/tanf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/rem_pio2f.c" 2 | #include "common.h" 3 | #include 4 | #include 5 | 6 | #define tanf(x) metallic_tanf(x) 7 | #include "src/math/float/tanf.c" 8 | #undef tanf 9 | 10 | BENCH(tanf) 11 | -------------------------------------------------------------------------------- /bench/float/tanhf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define tanhf(x) metallic_tanhf(x) 6 | #include "src/math/float/tanhf.c" 7 | #undef tanhf 8 | 9 | BENCH(tanhf) 10 | -------------------------------------------------------------------------------- /bench/float/tgammaf.c: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | #include 4 | 5 | #define tgammaf(x) metallic_tgammaf(x) 6 | #include "src/math/float/tgammaf.c" 7 | #undef tgammaf 8 | 9 | BENCH(tgammaf) 10 | -------------------------------------------------------------------------------- /include/assert.h: -------------------------------------------------------------------------------- 1 | #ifdef __cplusplus 2 | extern "C" 3 | #endif 4 | long __write(int, const void*, __SIZE_TYPE__); 5 | 6 | #define _STDERR(x) __write(2, (x), sizeof(x) - 1) 7 | #define _STRINGIFYIMPL(x) #x 8 | #define _STRINGIFY(x) _STRINGIFYIMPL(x) 9 | 10 | #ifdef NDEBUG 11 | #define assert(cond) ((void)0) 12 | #else 13 | #define assert(cond) do if (!(cond)) { \ 14 | _STDERR(__FILE__":"_STRINGIFY(__LINE__)": "); \ 15 | _STDERR(__func__); \ 16 | _STDERR(": Assertion `"#cond"' failed.\n"); \ 17 | __builtin_trap(); \ 18 | } while (0) 19 | #endif 20 | -------------------------------------------------------------------------------- /include/bits/null.h: -------------------------------------------------------------------------------- 1 | #ifndef NULL 2 | 3 | #if __cplusplus >= 201103L 4 | #define NULL nullptr 5 | #elif __GNUG__ 6 | #define NULL __null 7 | #elif __cplusplus 8 | #define NULL 0 9 | #else 10 | #define NULL ((void*)0) 11 | #endif 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /include/bits/specifiers.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITS_SPECIFIERS_H 2 | #define _BITS_SPECIFIERS_H 3 | 4 | #if __cplusplus >= 201103L 5 | #define _NORETURN [[noreturn]] 6 | #elif __STDC_VERSION__ >= 201112L 7 | #define _NORETURN _Noreturn 8 | #elif __GNUC__ 9 | #define _NORETURN __attribute__((__noreturn__)) 10 | #else 11 | #define _NORETURN 12 | #endif 13 | 14 | #if __cplusplus >= 201103L 15 | #define _NOEXCEPT noexcept 16 | #else 17 | #define _NOEXCEPT 18 | #endif 19 | 20 | #endif /* bits/specifiers.h */ 21 | -------------------------------------------------------------------------------- /include/bits/types/loff.h: -------------------------------------------------------------------------------- 1 | #ifdef __wasm32__ 2 | typedef double __loff_t; 3 | #else 4 | typedef long long __loff_t; 5 | #endif 6 | -------------------------------------------------------------------------------- /include/bits/types/mbstate.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITS_TYPES_MBSTATE_H 2 | #define _BITS_TYPES_MBSTATE_H 3 | 4 | struct __mbstate_t 5 | { 6 | unsigned __code; 7 | }; 8 | 9 | typedef struct __mbstate_t mbstate_t; 10 | 11 | #endif /* bits/types/mbstate.h */ 12 | -------------------------------------------------------------------------------- /include/bits/types/timespec.h: -------------------------------------------------------------------------------- 1 | #ifndef _BITS_TYPES_TIMESPEC_H 2 | #define _BITS_TYPES_TIMESPEC_H 3 | 4 | typedef long long time_t; 5 | 6 | struct timespec 7 | { 8 | time_t tv_sec; 9 | long tv_nsec; 10 | }; 11 | 12 | #endif /* bits/types/timespec.h */ 13 | 14 | -------------------------------------------------------------------------------- /include/ctype.h: -------------------------------------------------------------------------------- 1 | #ifndef _CTYPE_H 2 | #define _CTYPE_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | int iscntrl(int); 9 | int isprint(int); 10 | int isblank(int); 11 | int isspace(int); 12 | int isgraph(int); 13 | 14 | int isupper(int); 15 | int islower(int); 16 | int isalpha(int); 17 | 18 | int isdigit(int); 19 | int isxdigit(int); 20 | 21 | int isalnum(int); 22 | int ispunct(int); 23 | 24 | int toupper(int); 25 | int tolower(int); 26 | 27 | #ifdef __cplusplus 28 | } 29 | #endif 30 | 31 | #endif /* ctype.h */ 32 | -------------------------------------------------------------------------------- /include/iso646.h: -------------------------------------------------------------------------------- 1 | #ifndef _ISO646_H 2 | #define _ISO646_H 3 | 4 | #ifndef __cplusplus 5 | #define and && 6 | #define and_eq &= 7 | #define bitand & 8 | #define bitor | 9 | #define compl ~ 10 | #define not ! 11 | #define not_eq != 12 | #define or || 13 | #define or_eq |= 14 | #define xor ^ 15 | #define xor_eq ^= 16 | #endif 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/stdalign.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDALIGN_H 2 | #define _STDALIGN_H 3 | 4 | #ifndef __cplusplus 5 | #define alignas _Alignas 6 | #define alignof _Alignof 7 | #endif 8 | 9 | #define __alignas_is_defined 1 10 | #define __alignof_is_defined 1 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/stdarg.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDARG_H 2 | #define _STDARG_H 3 | 4 | typedef __builtin_va_list va_list; 5 | 6 | #define va_start(list, antecedent) __builtin_va_start(list, antecedent) 7 | #define va_arg(list, type) __builtin_va_arg(list, type) 8 | #define va_end(list) __builtin_va_end(list) 9 | 10 | #if __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L 11 | #define va_copy(destination, source) __builtin_va_copy(destination, source) 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /include/stdbool.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDBOOL_H 2 | #define _STDBOOL_H 3 | 4 | #ifndef __cplusplus 5 | #define bool _Bool 6 | #define true 1 7 | #define false 0 8 | #endif 9 | 10 | #define __bool_true_false_are_defined 1 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/stddef.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDDEF_H 2 | #define _STDDEF_H 3 | 4 | #include "bits/null.h" 5 | 6 | typedef __SIZE_TYPE__ size_t; 7 | typedef __PTRDIFF_TYPE__ ptrdiff_t; 8 | 9 | #define offsetof(type, member) __builtin_offsetof(type, member) 10 | 11 | #if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L 12 | struct __max_align_t 13 | { 14 | #ifdef __i386__ 15 | __float128 __g; 16 | #endif 17 | long double __e; 18 | long long __x; 19 | }; 20 | 21 | typedef struct __max_align_t max_align_t; 22 | #endif 23 | 24 | #endif /* stddef.h */ 25 | -------------------------------------------------------------------------------- /include/stdnoreturn.h: -------------------------------------------------------------------------------- 1 | #ifndef _STDNORETURN_H 2 | #define _STDNORETURN_H 3 | 4 | #ifndef __cplusplus 5 | #define noreturn _Noreturn 6 | #endif 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/ctype/isalnum.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int isalnum(int c) 4 | { 5 | return isdigit(c) || isalpha(c); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/ctype/isalpha.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int isalpha(int c) 4 | { 5 | return islower(c | 32); 6 | } 7 | -------------------------------------------------------------------------------- /src/ctype/isblank.c: -------------------------------------------------------------------------------- 1 | int isblank(int c) 2 | { 3 | return c == 32 || c == 9; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/iscntrl.c: -------------------------------------------------------------------------------- 1 | int iscntrl(int c) 2 | { 3 | return c < 32u || c == 127; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/isdigit.c: -------------------------------------------------------------------------------- 1 | int isdigit(int c) 2 | { 3 | return c - '0' < 10u; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/isgraph.c: -------------------------------------------------------------------------------- 1 | int isgraph(int c) 2 | { 3 | return c - 33 < 94u; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/islower.c: -------------------------------------------------------------------------------- 1 | int islower(int c) 2 | { 3 | return c - 'a' < 26u; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/isprint.c: -------------------------------------------------------------------------------- 1 | int isprint(int c) 2 | { 3 | return c - 32 < 95u; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/ispunct.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int ispunct(int c) 4 | { 5 | return isgraph(c) && !isalnum(c); 6 | } 7 | -------------------------------------------------------------------------------- /src/ctype/isspace.c: -------------------------------------------------------------------------------- 1 | int isspace(int c) 2 | { 3 | return c == 32 || c - 9 < 5u; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/isupper.c: -------------------------------------------------------------------------------- 1 | int isupper(int c) 2 | { 3 | return c - 'A' < 26u; 4 | } 5 | -------------------------------------------------------------------------------- /src/ctype/isxdigit.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int isxdigit(int c) 4 | { 5 | return isdigit(c) || (c | 32) - 'a' < 6u; 6 | } 7 | -------------------------------------------------------------------------------- /src/ctype/tolower.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int tolower(int c) 4 | { 5 | return c | isupper(c) << 5; 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/ctype/toupper.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int toupper(int c) 4 | { 5 | return c & ~(islower(c) << 5); 6 | } 7 | 8 | -------------------------------------------------------------------------------- /src/errno/errno.c: -------------------------------------------------------------------------------- 1 | _Thread_local int errno = 0; 2 | 3 | int* __errno_location(void) 4 | { 5 | return &errno; 6 | } 7 | -------------------------------------------------------------------------------- /src/fenv/feclearexcept.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int feclearexcept(int); 4 | -------------------------------------------------------------------------------- /src/fenv/fegetenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fegetenv(fenv_t*); 4 | -------------------------------------------------------------------------------- /src/fenv/fegetexceptflag.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fegetexceptflag(fexcept_t*, int); 4 | -------------------------------------------------------------------------------- /src/fenv/fegetround.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fegetround(void); 4 | -------------------------------------------------------------------------------- /src/fenv/feholdexcept.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int feholdexcept(fenv_t*); 4 | -------------------------------------------------------------------------------- /src/fenv/feraiseexcept.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int feraiseexcept(int); 4 | -------------------------------------------------------------------------------- /src/fenv/fesetenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fesetenv(const fenv_t*); 4 | -------------------------------------------------------------------------------- /src/fenv/fesetexceptflag.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fesetexceptflag(const fexcept_t*, int); 4 | -------------------------------------------------------------------------------- /src/fenv/fesetround.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fesetround(int); 4 | -------------------------------------------------------------------------------- /src/fenv/fetestexcept.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int fetestexcept(int); 4 | -------------------------------------------------------------------------------- /src/fenv/feupdateenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int feupdateenv(const fenv_t*); 4 | -------------------------------------------------------------------------------- /src/math/double/cbrt.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include "normalize.h" 3 | #include 4 | #include 5 | 6 | static double kernel_(double x) 7 | { 8 | int64_t i = reinterpret(int64_t, x); 9 | 10 | if (i == 0 || i >= 0x7FF0000000000000) 11 | return x; 12 | 13 | i = 0x2A9F7AF196E8E6E8 + normalize_(i) / 3; 14 | 15 | double y = reinterpret(double, i); 16 | 17 | y += 0.33333333333333333333 * (x / (y * y) - y); 18 | y += 0.33333333333333333333 * (x / (y * y) - y); 19 | y += 0.33333333333333333333 * (x / (y * y) - y); 20 | y += 0.33333333333333333333 * (x / (y * y) - y); 21 | 22 | return y; 23 | } 24 | 25 | double cbrt(double x) 26 | { 27 | return copysign(kernel_(fabs(x)), x); 28 | } 29 | -------------------------------------------------------------------------------- /src/math/double/ceil.c: -------------------------------------------------------------------------------- 1 | #include "ceil.h" 2 | #include "../rounding.h" 3 | 4 | double ceil(double x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_ceil(x); 8 | #endif 9 | return ceil_(x); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/double/ceil.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | static double ceil_(double x) 5 | { 6 | int64_t bits = reinterpret(int64_t, x); 7 | int64_t magnitude = bits & 0x7FFFFFFFFFFFFFFF; 8 | 9 | if (magnitude == 0 || magnitude >= 0x4330000000000000) /* 0x1p52 */ 10 | return x; 11 | 12 | if (magnitude < 0x3FF0000000000000) /* 1 */ 13 | return -(double)~(bits >> 63); 14 | 15 | int64_t mask = 0x000FFFFFFFFFFFFF >> ((magnitude >> 52) - 1023); 16 | 17 | return reinterpret(double, (bits + (bits >= 0) * mask) & ~mask); 18 | } 19 | -------------------------------------------------------------------------------- /src/math/double/cos.c: -------------------------------------------------------------------------------- 1 | #include "kernel/sincos.h" 2 | 3 | double cos(double x) 4 | { 5 | double y[2]; 6 | unsigned q = __rem_pio2(x, y); 7 | 8 | double z = q & 1 ? kernel_sin_(y[0], y[1]) : kernel_cos_(y[0], y[1]); 9 | return (q + 1) & 2 ? -z : z; 10 | } 11 | -------------------------------------------------------------------------------- /src/math/double/divs.h: -------------------------------------------------------------------------------- 1 | #include "truncate.h" 2 | 3 | /* Faithfully rounded c / (a + b) where |a| > |b| or |a| is a power of 2 */ 4 | static double divs_(double c, double a, double b) 5 | { 6 | double s = truncate_(a + b, 32); 7 | double x = truncate_(c / (a + b), 21); 8 | 9 | return x + (c - x * s - x * (a - s + b)) / (a + b); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/double/fabs.c: -------------------------------------------------------------------------------- 1 | double fabs(double x) 2 | { 3 | return __builtin_fabs(x); 4 | } 5 | -------------------------------------------------------------------------------- /src/math/double/fdim.c: -------------------------------------------------------------------------------- 1 | double fdim(double x, double y) 2 | { 3 | return x <= y ? 0 : x - y; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/double/floor.c: -------------------------------------------------------------------------------- 1 | #include "floor.h" 2 | #include "../rounding.h" 3 | 4 | double floor(double x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_floor(x); 8 | #endif 9 | return floor_(x); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/double/floor.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | static double floor_(double x) 5 | { 6 | int64_t bits = reinterpret(int64_t, x); 7 | int64_t magnitude = bits & 0x7FFFFFFFFFFFFFFF; 8 | 9 | if (magnitude == 0 || magnitude >= 0x4330000000000000) /* 0x1p52 */ 10 | return x; 11 | 12 | if (magnitude < 0x3FF0000000000000) /* 1 */ 13 | return bits >> 63; 14 | 15 | int64_t mask = 0x000FFFFFFFFFFFFF >> ((magnitude >> 52) - 1023); 16 | 17 | return reinterpret(double, (bits + (bits < 0) * mask) & ~mask); 18 | } 19 | -------------------------------------------------------------------------------- /src/math/double/fmax.c: -------------------------------------------------------------------------------- 1 | double fmax(double x, double y) 2 | { 3 | return x >= y || y != y ? x : y; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/double/fmin.c: -------------------------------------------------------------------------------- 1 | double fmin(double x, double y) 2 | { 3 | return x <= y || y != y ? x : y; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/double/fmod.c: -------------------------------------------------------------------------------- 1 | #include "fmod.h" 2 | 3 | double fmod(double numerator, double denominator) 4 | { 5 | return fmod_(numerator, denominator); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/double/frexp.c: -------------------------------------------------------------------------------- 1 | #include "normalize.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | 6 | double frexp(double x, int exp[static 1]) 7 | { 8 | int64_t i = reinterpret(int64_t, fabs(x)); 9 | 10 | if (i == 0 || i >= 0x7FF0000000000000) { 11 | *exp = 0; 12 | return x; 13 | } 14 | 15 | i = normalize_(i); 16 | *exp = (i >> 52) - 1022; 17 | 18 | return copysign(reinterpret(double, (i & 0x000FFFFFFFFFFFFF) | 0x3FE0000000000000), x); 19 | } 20 | -------------------------------------------------------------------------------- /src/math/double/ilogb.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int ilogb(double x) 7 | { 8 | int64_t word = reinterpret(int64_t, fabs(x)); 9 | 10 | if (word == 0) 11 | return FP_ILOGB0; 12 | 13 | if (word < 0x0010000000000000) 14 | return -(1011 + __builtin_clzll(word)); 15 | 16 | if (word < 0x7FF0000000000000) 17 | return (word >> 52) - 1023; 18 | 19 | if (FP_ILOGBNAN != INT_MAX && word == 0x7FF0000000000000) 20 | return INT_MAX; 21 | 22 | return FP_ILOGBNAN; 23 | } 24 | -------------------------------------------------------------------------------- /src/math/double/kernel/exp.h: -------------------------------------------------------------------------------- 1 | /* Restriction of expm1(a + b) to [0, 0.5 ln 2] 2 | * 3 | * Preferably, |b| < 0x1p-26 * |a| 4 | */ 5 | static double kernel_expb_(double a, double b) 6 | { 7 | const double c[] = { 8 | 1.6666666666666661553e-1, 9 | -2.7777777777564778614e-3, 10 | 6.6137564717940089175e-5, 11 | -1.6534060280704224368e-6, 12 | 4.1437773411068822733e-8 13 | }; 14 | 15 | double x = a + b; 16 | double xx = x * x; 17 | double y = x - xx * ((((c[4] * xx + c[3]) * xx + c[2]) * xx + c[1]) * xx + c[0]); 18 | 19 | return x * y / (2 - y) + b + a; 20 | } 21 | -------------------------------------------------------------------------------- /src/math/double/kernel/expm1.h: -------------------------------------------------------------------------------- 1 | /* Restriction of expm1(a + b) to [-0.5 ln 2, 0.5 ln 2] 2 | * where |b| < |a| 3 | */ 4 | static double kernel_expm1_(double a, double b, double residue[static 1]) 5 | { 6 | const double c[] = { 7 | -3.33333333333271196132e-2, 8 | 1.58730158656754696783e-3, 9 | -7.93650511970857863499e-5, 10 | 4.00786528423672283783e-6, 11 | -1.99315105709308306083e-7 12 | }; 13 | 14 | double s = a + b; 15 | double e = a - s + b; 16 | double h = 0.5 * s; 17 | double z = h * s; 18 | double r = ((((c[4] * z + c[3]) * z + c[2]) * z + c[1]) * z + c[0]) * z + 1; 19 | double t = r * h - 3; 20 | 21 | *residue = s * (e - (r + t) / (6 + s * t) * z) + e + z; 22 | return s; 23 | } 24 | -------------------------------------------------------------------------------- /src/math/double/kernel/log.h: -------------------------------------------------------------------------------- 1 | /* Restriction of (x -> 2 atanh(x) / x - 2) to [-c, c], where 2 | * 3 | * √2 - 1 1 + c 4 | * c = ------ the solution to ----- = √2. 5 | * √2 + 1, 1 - c 6 | */ 7 | static double kernel_log_(double x) 8 | { 9 | const double c[] = { 10 | 0.66666666666666697269, 11 | 0.39999999999898506593, 12 | 0.28571428626371267947, 13 | 0.22222211077397895313, 14 | 0.18182892887251091476, 15 | 0.15331607963815718446, 16 | 0.14617736819453644924 17 | }; 18 | 19 | x *= x; 20 | 21 | return x * ((((((c[6] * x + c[5]) * x + c[4]) * x + c[3]) * x + c[2]) * x + c[1]) * x + c[0]); 22 | } 23 | -------------------------------------------------------------------------------- /src/math/double/llrint.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | long long llrint(double x) 5 | { 6 | x = rint(x); 7 | 8 | return x >= LLONG_MAX ? LLONG_MAX : x > LLONG_MIN ? (long long)x : LLONG_MIN; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/double/llround.c: -------------------------------------------------------------------------------- 1 | #include "round.h" 2 | #include 3 | 4 | long long llround(double x) 5 | { 6 | double y = round_(x); 7 | 8 | return y >= LLONG_MAX ? LLONG_MAX : y > LLONG_MIN ? (long long)y : LLONG_MIN; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/double/log.c: -------------------------------------------------------------------------------- 1 | #include "kernel/log.h" 2 | #include "normalize.h" 3 | #include "../reinterpret.h" 4 | #include 5 | 6 | static double finite_(int64_t i) 7 | { 8 | const double ln2[] = { 0x1.62e42fefa4p-1, -0x1.8432a1b0e2634p-43 }; 9 | 10 | int64_t exponent = (i - 0x3FE6A09E667F3BCD) >> 52; 11 | double x = reinterpret(double, i - (exponent << 52)) - 1; 12 | double z = x / (x + 2); 13 | double h = 0.5 * x * x; 14 | 15 | return exponent * ln2[1] + z * (h + kernel_log_(z)) - h + x + exponent * ln2[0]; 16 | } 17 | 18 | double log(double x) 19 | { 20 | int64_t i = reinterpret(int64_t, x); 21 | 22 | if (i <= 0) 23 | return i << 1 == 0 ? -HUGE_VAL : NAN; 24 | 25 | if (i < 0x7FF0000000000000) 26 | return finite_(normalize_(i)); 27 | 28 | return x; 29 | } 30 | -------------------------------------------------------------------------------- /src/math/double/logb.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | 5 | double logb(double x) 6 | { 7 | double y = fabs(x); 8 | int64_t word = reinterpret(int64_t, y); 9 | 10 | if (word == 0) 11 | return -HUGE_VAL; 12 | 13 | if (word < 0x0010000000000000) 14 | return -(1011 + __builtin_clzll(word)); 15 | 16 | if (word < 0x7FF0000000000000) 17 | return (word >> 52) - 1023; 18 | 19 | return y; 20 | } 21 | -------------------------------------------------------------------------------- /src/math/double/lrint.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | long lrint(double x) 5 | { 6 | x = rint(x); 7 | 8 | return x >= LONG_MAX ? LONG_MAX : x > LONG_MIN ? (long)x : LONG_MIN; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/double/lround.c: -------------------------------------------------------------------------------- 1 | #include "round.h" 2 | #include 3 | #include 4 | 5 | long lround(double x) 6 | { 7 | double y = LONG_MAX < 0x1p52 ? x + copysign(0.5, x) : round_(x); 8 | 9 | return y >= LONG_MAX ? LONG_MAX : y > LONG_MIN ? (long)y : LONG_MIN; 10 | } 11 | -------------------------------------------------------------------------------- /src/math/double/modf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | double modf(double x, double i[static 1]) 4 | { 5 | *i = trunc(x); 6 | 7 | return copysign(isinf(x) ? 0 : x - *i, x); 8 | } 9 | -------------------------------------------------------------------------------- /src/math/double/nan.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef double Scalar; 4 | typedef uint64_t Bitset; 5 | 6 | #include "../../stdlib/parse/nan.h" 7 | 8 | double nan(const char s[static 1]) 9 | { 10 | char* dummy; 11 | return nan_(s, &dummy, '\0'); 12 | } 13 | -------------------------------------------------------------------------------- /src/math/double/nextafter.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | double nextafter(double from, double to) 7 | { 8 | if (from == to || to != to) 9 | return to; 10 | 11 | if (from != from) 12 | return from; 13 | 14 | if (from == 0) 15 | return copysign(DBL_TRUE_MIN, to); 16 | 17 | int64_t a = reinterpret(int64_t, from); 18 | int64_t b = reinterpret(int64_t, to); 19 | 20 | return reinterpret(double, b < a || (a ^ b) < 0 ? a - 1 : a + 1); 21 | } 22 | -------------------------------------------------------------------------------- /src/math/double/remquo.c: -------------------------------------------------------------------------------- 1 | #include "remquo.h" 2 | 3 | double remquo(double numerator, double denominator, int quotient[static 1]) 4 | { 5 | return remquo_(numerator, denominator, quotient); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/double/rint.c: -------------------------------------------------------------------------------- 1 | #include "rint.h" 2 | #include "../rounding.h" 3 | 4 | double rint(double x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_rint(x); 8 | #endif 9 | return rint_(x); 10 | } 11 | 12 | #ifdef __wasm__ 13 | double nearbyint(double) __attribute__((alias("rint"))); 14 | #endif 15 | -------------------------------------------------------------------------------- /src/math/double/rint.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static double rint_(double x) 4 | { 5 | const double rectifier = 0x1p52; 6 | double r = fabs(x); 7 | 8 | if (r < rectifier) { 9 | double y = r + rectifier; 10 | return copysign(y - rectifier, x); 11 | } 12 | 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /src/math/double/round.c: -------------------------------------------------------------------------------- 1 | #include "round.h" 2 | 3 | double round(double x) { return round_(x); } 4 | -------------------------------------------------------------------------------- /src/math/double/round.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static double round_(double x) 4 | { 5 | double r = fabs(x); 6 | double i = trunc(r); 7 | 8 | return copysign(i + (r - i >= 0.5), x); 9 | } 10 | -------------------------------------------------------------------------------- /src/math/double/scalbln.c: -------------------------------------------------------------------------------- 1 | typedef long Integer; 2 | 3 | #include 4 | #if LONG_MAX > INT_MAX 5 | #define SCALBN scalbln 6 | #include "scalbn.h" 7 | #endif 8 | -------------------------------------------------------------------------------- /src/math/double/scalbn.c: -------------------------------------------------------------------------------- 1 | #define SCALBN scalbn 2 | 3 | typedef int Integer; 4 | 5 | #include "scalbn.h" 6 | #include 7 | 8 | double ldexp(double, int) __attribute__((alias("scalbn"))); 9 | 10 | #if LONG_MAX == INT_MAX 11 | double scalbln(double, long) __attribute__((alias("scalbn"))); 12 | #endif 13 | -------------------------------------------------------------------------------- /src/math/double/scalbn.h: -------------------------------------------------------------------------------- 1 | #include "normalize.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | #include 6 | 7 | double SCALBN(double x, Integer exp) 8 | { 9 | int64_t i = reinterpret(int64_t, fabs(x)); 10 | 11 | if (i == 0 || i >= 0x7FF0000000000000) 12 | return x; 13 | 14 | i = normalize_(i); 15 | 16 | int64_t biased = exp + (i >> 52); 17 | 18 | if (biased >= 0x7FF || biased < -53) 19 | return x * (exp < 0 ? 0 : HUGE_VAL); 20 | 21 | i &= 0x000FFFFFFFFFFFFF; 22 | 23 | if (biased > 0) 24 | return copysign(reinterpret(double, i | biased << 52), x); 25 | 26 | return copysign(0x1p-53, x) * reinterpret(double, i | (biased + 53) << 52); 27 | } 28 | -------------------------------------------------------------------------------- /src/math/double/shift.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | static double shift_(double x, int64_t n) 5 | { 6 | int64_t i = reinterpret(int64_t, x) + (n << 52); 7 | 8 | return reinterpret(double, i); 9 | } 10 | -------------------------------------------------------------------------------- /src/math/double/sin.c: -------------------------------------------------------------------------------- 1 | #include "kernel/sincos.h" 2 | 3 | double sin(double x) 4 | { 5 | double y[2]; 6 | unsigned q = __rem_pio2(x, y); 7 | 8 | double z = q & 1 ? kernel_cos_(y[0], y[1]) : kernel_sin_(y[0], y[1]); 9 | return q & 2 ? -z : z; 10 | } 11 | -------------------------------------------------------------------------------- /src/math/double/split.h: -------------------------------------------------------------------------------- 1 | static double split_(double x) 2 | { 3 | double s = (0x1p27 + 1) * x; 4 | double c = x - s; 5 | 6 | return s + c; 7 | } 8 | -------------------------------------------------------------------------------- /src/math/double/sqrt.c: -------------------------------------------------------------------------------- 1 | double sqrt(double x) 2 | { 3 | return __builtin_sqrt(x); 4 | } 5 | -------------------------------------------------------------------------------- /src/math/double/trunc.c: -------------------------------------------------------------------------------- 1 | #include "trunc.h" 2 | #include "../rounding.h" 3 | 4 | double trunc(double x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_trunc(x); 8 | #endif 9 | return trunc_(x); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/double/trunc.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | static double trunc_(double x) 5 | { 6 | const int64_t mask = 0xFFF0000000000000; 7 | int64_t bits = reinterpret(int64_t, x); 8 | int64_t magnitude = bits & 0x7FFFFFFFFFFFFFFF; 9 | 10 | if (magnitude < 0x3FF0000000000000) /* 1 */ 11 | return reinterpret(double, bits & 0x8000000000000000); 12 | 13 | if (magnitude < 0x4330000000000000) /* 0x1p52 */ 14 | return reinterpret(double, mask >> ((magnitude >> 52) - 1023) & bits); 15 | 16 | return x; 17 | } 18 | -------------------------------------------------------------------------------- /src/math/double/truncate.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | /* Truncate the least significant bits */ 5 | static double truncate_(double x, int bits) 6 | { 7 | uint64_t i = reinterpret(uint64_t, x) & (uint64_t)-1 << bits; 8 | return reinterpret(double, i); 9 | } 10 | -------------------------------------------------------------------------------- /src/math/float/acoshf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/atanhf.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | 6 | static double finite_(double c) 7 | { 8 | const double ln2 = 0.6931471805599453094; 9 | 10 | double s = sqrt(c * c - 1); 11 | int64_t i = reinterpret(int64_t, c + s); 12 | int64_t exponent = (i - 0x3FE6A09E667F3BCD) >> 52; 13 | double y = reinterpret(double, i - (exponent << 52)); 14 | 15 | return 2 * kernel_atanhf_((y - 1) / (y + 1)) + exponent * ln2; 16 | } 17 | 18 | float acoshf(float x) 19 | { 20 | int32_t i = reinterpret(int32_t, x); 21 | 22 | if (i < 0x3F800000) 23 | return NAN; 24 | 25 | if (i < 0x7F800000) 26 | return finite_(x); 27 | 28 | return x; 29 | } 30 | -------------------------------------------------------------------------------- /src/math/float/asinhf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/atanhf.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | 6 | static double finite_(double s) 7 | { 8 | const double ln2 = 0.6931471805599453094; 9 | 10 | double c = sqrt(s * s + 1); 11 | int64_t i = reinterpret(int64_t, c + s); 12 | int64_t exponent = (i - 0x3FE6A09E667F3BCD) >> 52; 13 | double y = reinterpret(double, i - (exponent << 52)); 14 | 15 | if (exponent) 16 | return 2 * kernel_atanhf_((y - 1) / (y + 1)) + exponent * ln2; 17 | else 18 | return 2 * kernel_atanhf_(s / (c + 1)); 19 | } 20 | 21 | float asinhf(float x) 22 | { 23 | if (x - x == 0) 24 | return copysignf(finite_(fabsf(x)), x); 25 | 26 | return x; 27 | } 28 | -------------------------------------------------------------------------------- /src/math/float/atan2f.c: -------------------------------------------------------------------------------- 1 | #include "atan2f.h" 2 | 3 | float atan2f(float y, float x) 4 | { 5 | return atan2f_(y, x); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/atan2f.h: -------------------------------------------------------------------------------- 1 | #include "kernel/atanf.h" 2 | #include 3 | 4 | static double atan2f_(double y, double x) 5 | { 6 | const double pi = 3.14159265358979323846; 7 | 8 | double a = fabs(x); 9 | double b = fabs(y); 10 | 11 | if (a < b) 12 | return copysign(pi / 2, y) - kernel_atanf_(x / y); 13 | 14 | double acute = a == b ? b ? copysign(pi / 4, y) : y : kernel_atanf_(y / a); 15 | 16 | return signbit(x) ? copysign(pi, y) - acute : acute; 17 | } 18 | -------------------------------------------------------------------------------- /src/math/float/atanf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/atanf.h" 2 | #include 3 | 4 | float atanf(float x) 5 | { 6 | const double pi_2 = 1.57079632679489661923; 7 | 8 | return fabsf(x) > 1 ? copysign(pi_2, x) - kernel_atanf_(1.0 / x) : kernel_atanf_(x); 9 | } 10 | -------------------------------------------------------------------------------- /src/math/float/atanhf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/atanhf.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | 6 | static double finite_(double x) 7 | { 8 | const double ln2 = 0.69314718055994530942; 9 | 10 | int64_t i = reinterpret(int64_t, (1 + x) / (1 - x)); 11 | int64_t exponent = (i - 0x3FE6A09E667F3BCD) >> 52; 12 | double y = reinterpret(double, i - (exponent << 52)); 13 | 14 | if (exponent) 15 | return kernel_atanhf_((y - 1) / (y + 1)) + ln2 / 2 * exponent; 16 | else 17 | return kernel_atanhf_(x); 18 | } 19 | 20 | float atanhf(float x) 21 | { 22 | float absx = fabsf(x); 23 | 24 | if (absx == 1) 25 | return copysignf(INFINITY, x); 26 | 27 | if (absx < 1) 28 | return finite_(x); 29 | 30 | return NAN; 31 | } 32 | -------------------------------------------------------------------------------- /src/math/float/cabsf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float cabsf(float _Complex z) 5 | { 6 | return hypotf(z, cimagf(z)); 7 | } 8 | -------------------------------------------------------------------------------- /src/math/float/cacosf.c: -------------------------------------------------------------------------------- 1 | #include "cacoshf.h" 2 | 3 | float _Complex cacosf(float _Complex z) 4 | { 5 | const double pi = 3.14159265358979323846; 6 | 7 | float x = z; 8 | float y = cimagf(z); 9 | 10 | double _Complex first = cacoshf_(fabsf(x), fabsf(y)); 11 | 12 | return CMPLXF(fabs(cimag(first) - (x < 0) * pi), copysignf(first, -y)); 13 | } 14 | -------------------------------------------------------------------------------- /src/math/float/cacoshf.c: -------------------------------------------------------------------------------- 1 | #include "cacoshf.h" 2 | 3 | float _Complex cacoshf(float _Complex z) 4 | { 5 | const double pi = 3.14159265358979323846; 6 | 7 | float x = z; 8 | float y = cimagf(z); 9 | 10 | double _Complex first = cacoshf_(fabsf(x), fabsf(y)); 11 | 12 | return CMPLXF(first, copysignf(cimag(first) - (x < 0) * pi, y)); 13 | } 14 | -------------------------------------------------------------------------------- /src/math/float/cacoshf.h: -------------------------------------------------------------------------------- 1 | #include "finite/cashf.h" 2 | 3 | static double atan2_(double y, double x) 4 | { 5 | return carg_(x, y); 6 | } 7 | 8 | static double _Complex cacoshf_(float x, float y) 9 | { 10 | const double pi = 3.14159265358979323846; 11 | 12 | if (x == INFINITY) 13 | return CMPLX(INFINITY, y == INFINITY ? pi / 4 : 0 * y); 14 | 15 | if (y == INFINITY) 16 | return CMPLX(INFINITY, x == x ? pi / 2 : x); 17 | 18 | if (isunordered(x, y)) 19 | return CMPLX(NAN, x ? NAN : pi / 2); 20 | 21 | return cashf_(y, x, atan2_); 22 | } 23 | -------------------------------------------------------------------------------- /src/math/float/cargf.c: -------------------------------------------------------------------------------- 1 | #include "atan2f.h" 2 | #include 3 | 4 | float cargf(float _Complex z) 5 | { 6 | return atan2f_(cimagf(z), z); 7 | } 8 | -------------------------------------------------------------------------------- /src/math/float/casinf.c: -------------------------------------------------------------------------------- 1 | #include "casinhf.h" 2 | 3 | float _Complex casinf(float _Complex z) 4 | { 5 | float x = z; 6 | float y = cimagf(z); 7 | float _Complex first = casinhf_(fabsf(y), fabsf(x)); 8 | 9 | return CMPLXF(copysignf(cimagf(first), x), copysignf(first, y)); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/casinhf.c: -------------------------------------------------------------------------------- 1 | #include "casinhf.h" 2 | 3 | float _Complex casinhf(float _Complex z) 4 | { 5 | float x = z; 6 | float y = cimagf(z); 7 | float _Complex first = casinhf_(fabsf(x), fabsf(y)); 8 | 9 | return CMPLXF(copysignf(first, x), copysignf(cimagf(first), y)); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/casinhf.h: -------------------------------------------------------------------------------- 1 | #include "finite/cashf.h" 2 | 3 | static float _Complex casinhf_(float x, float y) 4 | { 5 | const double pi = 3.14159265358979323846; 6 | 7 | if (x == INFINITY) 8 | return CMPLXF(INFINITY, y == INFINITY ? pi / 4 : 0 * y); 9 | 10 | if (y == INFINITY) 11 | return CMPLXF(INFINITY, x == x ? pi / 2 : x); 12 | 13 | if (isunordered(x, y)) 14 | return CMPLXF(NAN, y ? NAN : 0); 15 | 16 | return cashf_(x, y, carg_); 17 | } 18 | -------------------------------------------------------------------------------- /src/math/float/catanf.c: -------------------------------------------------------------------------------- 1 | #include "catanf.h" 2 | 3 | float _Complex catanf(float _Complex z) 4 | { 5 | float x = z; 6 | float y = cimagf(z); 7 | float _Complex first = catanf_(fabsf(x), fabsf(y)); 8 | 9 | return CMPLXF(copysignf(first, x), copysignf(cimagf(first), y)); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/catanhf.c: -------------------------------------------------------------------------------- 1 | #include "catanf.h" 2 | 3 | float _Complex catanhf(float _Complex z) 4 | { 5 | float x = z; 6 | float y = cimagf(z); 7 | float _Complex first = catanf_(fabsf(y), fabsf(x)); 8 | 9 | return CMPLXF(copysignf(cimagf(first), x), copysignf(first, y)); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/cbrtf.c: -------------------------------------------------------------------------------- 1 | #include "normalizef.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | 6 | static float kernel_(float x) 7 | { 8 | int32_t i = reinterpret(int32_t, x); 9 | 10 | if (i == 0 || i >= 0x7F800000) 11 | return x; 12 | 13 | i = 0x2A512CE3 + normalizef_(i) / 3; 14 | 15 | double y = reinterpret(float, i); 16 | 17 | y *= 0.5 + 1.5 * x / (2 * y * (y * y) + x); 18 | y += 0.33333333333333333333 * (x / (y * y) - y); 19 | 20 | return y; 21 | } 22 | 23 | float cbrtf(float x) 24 | { 25 | return copysignf(kernel_(fabsf(x)), x); 26 | } 27 | -------------------------------------------------------------------------------- /src/math/float/ccosf.c: -------------------------------------------------------------------------------- 1 | #include "ccoshf.h" 2 | 3 | float _Complex ccosf(float _Complex z) 4 | { 5 | return ccoshf_(-cimagf(z), z); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/ccoshf.c: -------------------------------------------------------------------------------- 1 | #include "ccoshf.h" 2 | 3 | float _Complex ccoshf(float _Complex z) 4 | { 5 | return ccoshf_(z, cimagf(z)); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/ceilf.c: -------------------------------------------------------------------------------- 1 | #include "ceilf.h" 2 | #include "../rounding.h" 3 | 4 | float ceilf(float x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_ceilf(x); 8 | #endif 9 | return ceilf_(x); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/ceilf.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | static float ceilf_(float x) 5 | { 6 | int32_t bits = reinterpret(int32_t, x); 7 | int32_t magnitude = bits & 0x7FFFFFFF; 8 | 9 | if (magnitude == 0 || magnitude >= 0x4B000000) /* 0x1p23 */ 10 | return x; 11 | 12 | if (magnitude < 0x3F800000) /* 1 */ 13 | return -(float)~(bits >> 31); 14 | 15 | int32_t mask = 0x007FFFFF >> ((magnitude >> 23) - 127); 16 | 17 | return reinterpret(float, (bits + (bits >= 0) * mask) & ~mask); 18 | } 19 | -------------------------------------------------------------------------------- /src/math/float/cexpf.c: -------------------------------------------------------------------------------- 1 | #include "cisf.h" 2 | #include "expf.h" 3 | 4 | float _Complex cexpf(float _Complex z) 5 | { 6 | float x = z; 7 | float y = cimagf(z); 8 | double r = expf_(x); 9 | 10 | if (y == 0) 11 | return CMPLXF(r, y); 12 | 13 | if (y - y) { 14 | if (x == INFINITY) 15 | return CMPLXF(x, y - y); 16 | 17 | if (x == -INFINITY) 18 | return 0; 19 | } 20 | 21 | return r * cisf_(y); 22 | } 23 | -------------------------------------------------------------------------------- /src/math/float/cimagf.c: -------------------------------------------------------------------------------- 1 | float cimagf(float _Complex z) 2 | { 3 | return __imag__ z; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/float/clogf.c: -------------------------------------------------------------------------------- 1 | #include "clogf.h" 2 | 3 | float _Complex clogf(float _Complex z) 4 | { 5 | return clogf_(z); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/conjf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float _Complex conjf(float _Complex z) 4 | { 5 | return CMPLXF(z, -cimagf(z)); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/cosf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/sincosf.h" 2 | 3 | float cosf(float x) 4 | { 5 | double y; 6 | unsigned q = __rem_pio2f(x, &y); 7 | 8 | y = q & 1 ? kernel_sinf_(y) : kernel_cosf_(y); 9 | 10 | return (q + 1) & 2 ? -y : y; 11 | } 12 | -------------------------------------------------------------------------------- /src/math/float/coshf.c: -------------------------------------------------------------------------------- 1 | #include "expf.h" 2 | #include 3 | 4 | float coshf(float x) 5 | { 6 | double y = expf_(fabsf(x)); 7 | 8 | return 0.5 * y + 0.5 / y; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/float/cpowf.c: -------------------------------------------------------------------------------- 1 | #include "clogf.h" 2 | #include "cisf.h" 3 | #include "expf.h" 4 | 5 | float _Complex cpowf(float _Complex base, float _Complex exp) 6 | { 7 | double _Complex z = exp * clogf_(base); 8 | double x = z; 9 | double y = cimag(z); 10 | 11 | if (y == 0) 12 | return CMPLX(expf_(x), y); 13 | 14 | if (y - y) { 15 | if (x == INFINITY) 16 | return CMPLX(x, y - y); 17 | 18 | if (x == -INFINITY) 19 | return 0; 20 | } 21 | 22 | return expf_(x) * cisf_(y); 23 | } 24 | -------------------------------------------------------------------------------- /src/math/float/cprojf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | float _Complex cprojf(float _Complex z) 5 | { 6 | if (isinf((float)z) || isinf(cimagf(z))) 7 | return CMPLXF(INFINITY, copysignf(0, cimagf(z))); 8 | 9 | return z; 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/crealf.c: -------------------------------------------------------------------------------- 1 | float crealf(float _Complex z) 2 | { 3 | return z; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/float/csinf.c: -------------------------------------------------------------------------------- 1 | #include "csinhf.h" 2 | 3 | float _Complex csinf(float _Complex z) 4 | { 5 | z = csinhf_(cimagf(z), z); 6 | 7 | return CMPLXF(cimagf(z), z); 8 | } 9 | -------------------------------------------------------------------------------- /src/math/float/csinhf.c: -------------------------------------------------------------------------------- 1 | #include "csinhf.h" 2 | 3 | float _Complex csinhf(float _Complex z) 4 | { 5 | return csinhf_(z, cimagf(z)); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/csinhf.h: -------------------------------------------------------------------------------- 1 | #include "cisf.h" 2 | #include "expm1f.h" 3 | #include 4 | 5 | static float _Complex csinhf_(float x, float y) 6 | { 7 | double t = expm1f_(fabsf(x)); 8 | double cosh = 0.5 * (t + 1) + 0.5 / (t + 1); 9 | double sinh = copysign(t, x) * (0.5 + 0.5 / (t + 1)); 10 | double _Complex circular = cisf_(y); 11 | 12 | if (y == 0) 13 | return CMPLXF(sinh, y); 14 | 15 | if (y - y && (x == 0 || isinf(x))) 16 | return CMPLXF(x, y - y); 17 | 18 | return CMPLXF(sinh * creal(circular), cosh * cimag(circular)); 19 | } 20 | -------------------------------------------------------------------------------- /src/math/float/csqrtf.c: -------------------------------------------------------------------------------- 1 | #include "finite/csqrt.h" 2 | #include 3 | #include 4 | 5 | float _Complex csqrtf(float _Complex z) 6 | { 7 | float x = z; 8 | float y = cimagf(z); 9 | 10 | if (z == 0) 11 | return CMPLXF(0, y); 12 | 13 | if (isinf(y)) 14 | return CMPLXF(INFINITY, y); 15 | 16 | if (x == INFINITY) 17 | return CMPLXF(x, 0 * y); 18 | 19 | if (x == -INFINITY) 20 | return CMPLXF(y - y, copysignf(x, y)); 21 | 22 | return csqrt_(x, y); 23 | } 24 | -------------------------------------------------------------------------------- /src/math/float/ctanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float _Complex ctanf(float _Complex z) 4 | { 5 | z = ctanhf(CMPLXF(cimagf(z), z)); 6 | 7 | return CMPLXF(cimagf(z), z); 8 | } 9 | -------------------------------------------------------------------------------- /src/math/float/exp2f.c: -------------------------------------------------------------------------------- 1 | #include "kernel/exp2f.h" 2 | #include "../double/shift.h" 3 | #include 4 | #include 5 | 6 | float exp2f(float x) 7 | { 8 | if (x < -150) 9 | return 0; 10 | 11 | if (x > 128) 12 | return 128 * FLT_MAX; 13 | 14 | float n = rintf(x); 15 | double y = 1 + kernel_exp2f_(x - n); 16 | 17 | return shift_(y, n); 18 | } 19 | -------------------------------------------------------------------------------- /src/math/float/exp2f.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_PREC_EXP2F_H 2 | #define METALLIC_PREC_EXP2F_H 3 | 4 | #include "kernel/exp2f.h" 5 | #include "../double/shift.h" 6 | #include 7 | #include 8 | 9 | static double exp2f_(double x) 10 | { 11 | if (x < -1022) 12 | return 0; 13 | 14 | if (x >= 1024) 15 | return x * HUGE_VAL; 16 | 17 | double n = rint(x); 18 | double y = 1 + kernel_exp2f_(x - n); 19 | 20 | return shift_(y, n); 21 | } 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/math/float/expf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/expf.h" 2 | #include "../double/shift.h" 3 | #include 4 | #include 5 | 6 | float expf(float x) 7 | { 8 | const float minimum = -103.972077083991796; 9 | const float maximum = 88.7228391116729996; 10 | 11 | const float log2e = 1.442695040888963407; 12 | const double ln2 = 0.6931471805599453094; 13 | 14 | if (x < minimum) 15 | return 0; 16 | 17 | if (x > maximum) 18 | return maximum * FLT_MAX; 19 | 20 | float n = rintf(x * log2e); 21 | double y = 1 + kernel_expf_(x - n * ln2); 22 | 23 | return shift_(y, n); 24 | } 25 | -------------------------------------------------------------------------------- /src/math/float/expf.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_PREC_EXPF_H 2 | #define METALLIC_PREC_EXPF_H 3 | 4 | #include "kernel/expf.h" 5 | #include "../double/shift.h" 6 | #include 7 | 8 | static double expf_(double x) 9 | { 10 | const double minimum = -708.39641853226410622; 11 | const double maximum = 709.78271289338399684; 12 | 13 | const double log2e = 1.442695040888963407; 14 | const double ln2 = 0.6931471805599453094; 15 | 16 | if (x < minimum) 17 | return 0; 18 | 19 | if (x > maximum) 20 | return x * HUGE_VAL; 21 | 22 | double n = rint(x * log2e); 23 | double y = 1 + kernel_expf_(x - n * ln2); 24 | 25 | return shift_(y, n); 26 | } 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/math/float/expm1f.c: -------------------------------------------------------------------------------- 1 | #include "expm1f.h" 2 | 3 | float expm1f(float x) 4 | { 5 | return expm1f_(x); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/expm1f.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_EXPM1F_H 2 | #define METALLIC_EXPM1F_H 3 | 4 | #include "kernel/expf.h" 5 | #include "../double/shift.h" 6 | #include 7 | 8 | static double expm1f_(float x) 9 | { 10 | const float minimum = -37.42994775023704671; 11 | const float maximum = 709.78271289338399684; 12 | 13 | const float log2e = 1.442695040888963407; 14 | const double ln2 = 0.6931471805599453094; 15 | 16 | if (x < minimum) 17 | return -1; 18 | 19 | if (x > maximum) 20 | return x * HUGE_VAL; 21 | 22 | float n = rintf(x * log2e) + 0; 23 | double y = kernel_expf_(x - n * ln2); 24 | 25 | if (n == 0) 26 | return y; 27 | 28 | return shift_(y + 1, n) - 1; 29 | } 30 | #endif 31 | -------------------------------------------------------------------------------- /src/math/float/fabsf.c: -------------------------------------------------------------------------------- 1 | float fabsf(float x) 2 | { 3 | return __builtin_fabsf(x); 4 | } 5 | -------------------------------------------------------------------------------- /src/math/float/fdimf.c: -------------------------------------------------------------------------------- 1 | float fdimf(float x, float y) 2 | { 3 | return x <= y ? 0 : x - y; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/float/finite/csqrt.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Finite nonzero complex square root */ 5 | static double _Complex csqrt_(double x, double y) 6 | { 7 | double s = sqrt(0.5 * (fabs(x) + sqrt(x * x + y * y))); 8 | double t = 0.5 * y / s; 9 | 10 | if (signbit(x)) 11 | return CMPLX(fabs(t), copysign(s, y)); 12 | else 13 | return CMPLX(s, t); 14 | } 15 | -------------------------------------------------------------------------------- /src/math/float/finite/log1pf.h: -------------------------------------------------------------------------------- 1 | #include "../kernel/atanhf.h" 2 | #include "../../reinterpret.h" 3 | #include 4 | 5 | static double log1pf_(double x) 6 | { 7 | const double ln2 = 0.69314718055994530942; 8 | 9 | int64_t i = reinterpret(int64_t, 1 + x); 10 | int64_t exponent = (i - 0x3FE6A09E667F3BCD) >> 52; 11 | double y = reinterpret(double, i - (exponent << 52)); 12 | 13 | if (exponent) 14 | return 2 * kernel_atanhf_((y - 1) / (y + 1)) + exponent * ln2; 15 | else 16 | return 2 * kernel_atanhf_(x / (2 + x)); 17 | } 18 | -------------------------------------------------------------------------------- /src/math/float/finite/log2f.h: -------------------------------------------------------------------------------- 1 | #include "../kernel/atanh.h" 2 | #include "../../reinterpret.h" 3 | #include 4 | 5 | static double log2f_(double x) 6 | { 7 | const double log2e = 1.44269504088896340736; 8 | 9 | int64_t i = reinterpret(int64_t, x); 10 | int64_t exponent = (i - 0x3FE6A09E667F3BCD) >> 52; 11 | 12 | x = reinterpret(double, i - (exponent << 52)); 13 | 14 | return 2 * log2e * kernel_atanh_((x - 1) / (x + 1)) + exponent; 15 | } 16 | -------------------------------------------------------------------------------- /src/math/float/floorf.c: -------------------------------------------------------------------------------- 1 | #include "floorf.h" 2 | #include "../rounding.h" 3 | 4 | float floorf(float x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_floorf(x); 8 | #endif 9 | return floorf_(x); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/floorf.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | static float floorf_(float x) 5 | { 6 | int32_t bits = reinterpret(int32_t, x); 7 | int32_t magnitude = bits & 0x7FFFFFFF; 8 | 9 | if (magnitude == 0 || magnitude >= 0x4B000000) /* 0x1p23 */ 10 | return x; 11 | 12 | if (magnitude < 0x3F800000) /* 1 */ 13 | return bits >> 31; 14 | 15 | int32_t mask = 0x007FFFFF >> ((magnitude >> 23) - 127); 16 | 17 | return reinterpret(float, (bits + (bits < 0) * mask) & ~mask); 18 | } 19 | -------------------------------------------------------------------------------- /src/math/float/fmaf.c: -------------------------------------------------------------------------------- 1 | #include "fmaf.h" 2 | 3 | float fmaf(float a, float b, float c) 4 | { 5 | return fmaf_(a, b, c); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/fmaf.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | 5 | static float fmaf_(float a, float b, float c) 6 | { 7 | #pragma STDC FENV_ACCESS ON 8 | #pragma STDC FP_CONTRACT ON 9 | 10 | #ifdef FP_FAST_FMAF 11 | return a * b + c; 12 | #endif 13 | 14 | double ab = (double)a * b; 15 | double s = ab + c; 16 | uint64_t i = reinterpret(uint64_t, s); 17 | 18 | if ((i & 0x1FFFFFFF) != 0x10000000 || s - s || s - ab == c || fegetround() != FE_TONEAREST) 19 | return s; 20 | 21 | uint64_t adjustment = 1 - ((i ^ reinterpret(uint64_t, ab - s + c)) >> 63 << 1); 22 | return reinterpret(double, i + adjustment); 23 | } 24 | -------------------------------------------------------------------------------- /src/math/float/fmaxf.c: -------------------------------------------------------------------------------- 1 | float fmaxf(float x, float y) 2 | { 3 | return x >= y || y != y ? x : y; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/float/fminf.c: -------------------------------------------------------------------------------- 1 | float fminf(float x, float y) 2 | { 3 | return x <= y || y != y ? x : y; 4 | } 5 | -------------------------------------------------------------------------------- /src/math/float/fmodf.c: -------------------------------------------------------------------------------- 1 | #include "fmodf.h" 2 | 3 | float fmodf(float numerator, float denominator) 4 | { 5 | return fmodf_(numerator, denominator); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/frexpf.c: -------------------------------------------------------------------------------- 1 | #include "normalizef.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | 6 | float frexpf(float x, int exp[static 1]) 7 | { 8 | int32_t i = reinterpret(int32_t, fabsf(x)); 9 | 10 | if (i == 0 || i >= 0x7F800000) { 11 | *exp = 0; 12 | return x; 13 | } 14 | 15 | i = normalizef_(i); 16 | *exp = (i >> 23) - 126; 17 | 18 | return copysignf(reinterpret(float, (i & 0x007FFFFF) | 0x3F000000), x); 19 | } 20 | -------------------------------------------------------------------------------- /src/math/float/hypotf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float hypotf(float x, float y) 4 | { 5 | if (isinf(x) || isinf(y)) 6 | return INFINITY; 7 | 8 | double a = x; 9 | double b = y; 10 | 11 | return sqrt(a * a + b * b); 12 | } 13 | -------------------------------------------------------------------------------- /src/math/float/ilogbf.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int ilogbf(float x) 7 | { 8 | int32_t magnitude = reinterpret(int32_t, fabsf(x)); 9 | 10 | if (magnitude == 0) 11 | return FP_ILOGB0; 12 | 13 | if (magnitude < 0x00800000) 14 | return -(118 + __builtin_clz(magnitude)); 15 | 16 | if (magnitude < 0x7F800000) 17 | return (magnitude >> 23) - 127; 18 | 19 | if (FP_ILOGBNAN != INT_MAX && magnitude == 0x7F800000) 20 | return INT_MAX; 21 | 22 | return FP_ILOGBNAN; 23 | } 24 | -------------------------------------------------------------------------------- /src/math/float/kernel/atanf.h: -------------------------------------------------------------------------------- 1 | /* Arctangent restricted to [-1, 1] */ 2 | static double kernel_atanf_(double x) 3 | { 4 | const double n[] = { 5 | 80.3271869581482272, 6 | 72.2722811622844352, 7 | 11.0979939649070095 8 | }; 9 | 10 | const double d[] = { 11 | 80.3271884011195215, 12 | 99.0478590867740213, 13 | 28.0510393790794482, 14 | }; 15 | 16 | double x2 = x * x; 17 | double x4 = x2 * x2; 18 | double num = n[0] + n[1] * x2 + n[2] * x4; 19 | double den = d[0] + d[1] * x2 + (d[2] + x2) * x4; 20 | 21 | return x * num / den; 22 | } 23 | -------------------------------------------------------------------------------- /src/math/float/kernel/atanh.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_KERNEL_FAST_ATANH_H 2 | #define METALLIC_KERNEL_FAST_ATANH_H 3 | 4 | /* Inverse hyperbolic tangent restricted to [-c, c], where 5 | * 6 | * √2 - 1 1 + c 7 | * c = ------ the solution to ----- = √2. 8 | * √2 + 1, 1 - c 9 | */ 10 | static double kernel_atanh_(double x) 11 | { 12 | const double c[] = { 13 | 0.33333332822728226129, 14 | 0.20000167595436263505, 15 | 0.14268654271188685375, 16 | 0.11791075649681414150 17 | }; 18 | 19 | double xx = x * x; 20 | 21 | return x + x * xx * (((c[3] * xx + c[2]) * xx + c[1]) * xx + c[0]); 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /src/math/float/kernel/atanhf.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_KERNEL_ATANHF_H 2 | #define METALLIC_KERNEL_ATANHF_H 3 | 4 | /* Inverse hyperbolic tangent restricted to [-c, c], where 5 | * 6 | * √2 - 1 1 + c 7 | * c = ------ the solution to ----- = √2. 8 | * √2 + 1, 1 - c 9 | */ 10 | static double kernel_atanhf_(double x) 11 | { 12 | const double c[] = { 13 | 0.33333388190810157475, 14 | 0.19988770787788511120, 15 | 0.14935863879449999474 16 | }; 17 | 18 | double xx = x * x; 19 | 20 | return x + x * xx * ((c[2] * xx + c[1]) * xx + c[0]); 21 | } 22 | #endif 23 | -------------------------------------------------------------------------------- /src/math/float/kernel/exp2f.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_KERNEL_EXP2F_H 2 | #define METALLIC_KERNEL_EXP2F_H 3 | 4 | /* Restriction of (x -> 2^x - 1) to [-0.5, 0.5] */ 5 | static double kernel_exp2f_(double x) 6 | { 7 | const double c[] = { 8 | 6.931471880289532425e-1, 9 | 2.402265108421173406e-1, 10 | 5.550357105498874537e-2, 11 | 9.618030771171497658e-3, 12 | 1.339086685300950937e-3, 13 | 1.546973499989028719e-4 14 | }; 15 | 16 | return x * (((((c[5] * x + c[4]) * x + c[3]) * x + c[2]) * x + c[1]) * x + c[0]); 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /src/math/float/kernel/expf.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_KERNEL_EXPF_H 2 | #define METALLIC_KERNEL_EXPF_H 3 | 4 | /* Restriction of `expm1f` to [-0.5 ln 2, 0.5 ln 2] */ 5 | static double kernel_expf_(double x) 6 | { 7 | const double c[] = { 8 | 1.000000010775500705, 9 | 5.000000080819903627e-1, 10 | 1.666650523422326531e-1, 11 | 4.166624066361261157e-2, 12 | 8.369150671031008566e-3, 13 | 1.394858354331218335e-3 14 | }; 15 | 16 | return x * (((((c[5] * x + c[4]) * x + c[3]) * x + c[2]) * x + c[1]) * x + c[0]); 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /src/math/float/kernel/lanczos.h: -------------------------------------------------------------------------------- 1 | static double lanczos_series_(double z) 2 | { 3 | const double p[] = { 4 | 2.5066282972608683788, 5 | 93.724008703110370647, 6 | -85.030278048785721233, 7 | 15.313090747320992728, 8 | -0.2376573970640603182 9 | }; 10 | 11 | return p[4] / (z + 4) + p[3] / (z + 3) + (p[2] / (z + 2) + p[1] / (z + 1)) + p[0]; 12 | } 13 | 14 | static const double lanczos_g_ = 4.3644453082153116114; 15 | -------------------------------------------------------------------------------- /src/math/float/kernel/sincosf.h: -------------------------------------------------------------------------------- 1 | #include "sinf.h" 2 | 3 | static double kernel_cosf_(double x) 4 | { 5 | const double c[] = { 6 | 9.9999997242332292107e-1, 7 | -4.9999856695848847717e-1, 8 | 4.1655026884251524438e-2, 9 | -1.3585908510113298585e-3 10 | }; 11 | 12 | x *= x; 13 | 14 | return ((c[3] * x + c[2]) * x + c[1]) * x + c[0]; 15 | } 16 | -------------------------------------------------------------------------------- /src/math/float/kernel/sinf.h: -------------------------------------------------------------------------------- 1 | static double kernel_sinf_(double x) 2 | { 3 | const double c[] = { 4 | 9.9999999692634277740e-1, 5 | -1.6666650699202422675e-1, 6 | 8.3320368751598070196e-3, 7 | -1.9504022000675618505e-4 8 | }; 9 | 10 | double xx = x * x; 11 | 12 | return x * (((c[3] * xx + c[2]) * xx + c[1]) * xx + c[0]); 13 | } 14 | 15 | int __rem_pio2f(float x, double y[static 1]); 16 | -------------------------------------------------------------------------------- /src/math/float/llrintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | long long llrintf(float x) 5 | { 6 | x = rintf(x); 7 | 8 | return x >= LLONG_MAX ? LLONG_MAX : x > LLONG_MIN ? (long long)x : LLONG_MIN; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/float/llroundf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | long long llroundf(float x) 5 | { 6 | double y = x + copysign(0.5, x); 7 | 8 | return y >= LLONG_MAX ? LLONG_MAX : y > LLONG_MIN ? (long long)y : LLONG_MIN; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/float/log10f.c: -------------------------------------------------------------------------------- 1 | #include "normalizef.h" 2 | #include "kernel/atanhf.h" 3 | #include "../reinterpret.h" 4 | #include 5 | 6 | static float finite_(int32_t i) 7 | { 8 | const double log10_e = 0.43429448190325182765; 9 | const double log10_2 = 0.30102999566398119521; 10 | 11 | int32_t exponent = (i - 0x3F3504F4) >> 23; 12 | double x = reinterpret(float, i - (exponent << 23)); 13 | 14 | return 2 * log10_e * kernel_atanhf_((x - 1) / (x + 1)) + exponent * log10_2; 15 | } 16 | 17 | float log10f(float x) 18 | { 19 | int32_t i = reinterpret(int32_t, x); 20 | 21 | if (i <= 0) 22 | return i << 1 == 0 ? -INFINITY : NAN; 23 | 24 | if (i < 0x7F800000) 25 | return finite_(normalizef_(i)); 26 | 27 | return x; 28 | } 29 | -------------------------------------------------------------------------------- /src/math/float/log1pf.c: -------------------------------------------------------------------------------- 1 | #include "finite/log1pf.h" 2 | #include "../reinterpret.h" 3 | #include 4 | #include 5 | 6 | float log1pf(float x) 7 | { 8 | int32_t i = reinterpret(int32_t, x); 9 | 10 | if (i == 0xBF800000) 11 | return -INFINITY; 12 | 13 | if (i > 0xBF800000) 14 | return NAN; 15 | 16 | if (i < 0x7F800000) 17 | return log1pf_(x); 18 | 19 | return x; 20 | } 21 | -------------------------------------------------------------------------------- /src/math/float/log2f.c: -------------------------------------------------------------------------------- 1 | #include "normalizef.h" 2 | #include "kernel/atanhf.h" 3 | #include "../reinterpret.h" 4 | #include 5 | 6 | static float finite_(int32_t i) 7 | { 8 | const double log2e = 1.44269504088896340736; 9 | 10 | int32_t exponent = (i - 0x3F3504F4) >> 23; 11 | double x = reinterpret(float, i - (exponent << 23)); 12 | 13 | return 2 * log2e * kernel_atanhf_((x - 1) / (x + 1)) + exponent; 14 | } 15 | 16 | float log2f(float x) 17 | { 18 | int32_t i = reinterpret(int32_t, x); 19 | 20 | if (i <= 0) 21 | return i << 1 == 0 ? -INFINITY : NAN; 22 | 23 | if (i < 0x7F800000) 24 | return finite_(normalizef_(i)); 25 | 26 | return x; 27 | } 28 | -------------------------------------------------------------------------------- /src/math/float/logbf.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | 5 | float logbf(float x) 6 | { 7 | float y = fabsf(x); 8 | int32_t word = reinterpret(int32_t, y); 9 | 10 | if (word == 0) 11 | return -INFINITY; 12 | 13 | if (word < 0x00800000) 14 | return -(118 + __builtin_clz(word)); 15 | 16 | if (word < 0x7F800000) 17 | return (word >> 23) - 127; 18 | 19 | return y; 20 | } 21 | -------------------------------------------------------------------------------- /src/math/float/logf.c: -------------------------------------------------------------------------------- 1 | #include "normalizef.h" 2 | #include "kernel/atanhf.h" 3 | #include "../reinterpret.h" 4 | #include 5 | 6 | static float finite_(int32_t i) 7 | { 8 | const double ln2 = 0.69314718055994530942; 9 | 10 | int32_t exponent = (i - 0x3F3504F4) >> 23; 11 | double x = reinterpret(float, i - (exponent << 23)); 12 | 13 | return 2 * kernel_atanhf_((x - 1) / (x + 1)) + exponent * ln2; 14 | } 15 | 16 | float logf(float x) 17 | { 18 | int32_t i = reinterpret(int32_t, x); 19 | 20 | if (i <= 0) 21 | return i << 1 == 0 ? -INFINITY : NAN; 22 | 23 | if (i < 0x7F800000) 24 | return finite_(normalizef_(i)); 25 | 26 | return x; 27 | } 28 | -------------------------------------------------------------------------------- /src/math/float/lrintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | long lrintf(float x) 5 | { 6 | x = rintf(x); 7 | 8 | return x >= LONG_MAX ? LONG_MAX : x > LONG_MIN ? (long)x : LONG_MIN; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/float/lroundf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | long lroundf(float x) 5 | { 6 | double y = x + copysign(0.5, x); 7 | 8 | return y >= LONG_MAX ? LONG_MAX : y > LONG_MIN ? (long)y : LONG_MIN; 9 | } 10 | -------------------------------------------------------------------------------- /src/math/float/modff.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | float modff(float x, float i[static 1]) 4 | { 5 | *i = truncf(x); 6 | 7 | return copysignf(isinf(x) ? 0 : x - *i, x); 8 | } 9 | -------------------------------------------------------------------------------- /src/math/float/nanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | typedef float Scalar; 4 | typedef uint32_t Bitset; 5 | 6 | #include "../../stdlib/parse/nan.h" 7 | 8 | float nanf(const char s[static 1]) 9 | { 10 | char* dummy; 11 | return nan_(s, &dummy, '\0'); 12 | } 13 | -------------------------------------------------------------------------------- /src/math/float/nextafterf.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | float nextafterf(float from, float to) 7 | { 8 | if (from == to || to != to) 9 | return to; 10 | 11 | if (from != from) 12 | return from; 13 | 14 | if (from == 0) 15 | return copysignf(FLT_TRUE_MIN, to); 16 | 17 | int32_t a = reinterpret(int32_t, from); 18 | int32_t b = reinterpret(int32_t, to); 19 | 20 | return reinterpret(float, b < a || (a ^ b) < 0 ? a - 1 : a + 1); 21 | } 22 | -------------------------------------------------------------------------------- /src/math/float/normalizef.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_NORMALIZEF_H 2 | #define METALLIC_NORMALIZEF_H 3 | 4 | #include 5 | 6 | /* Normalize nonzero magnitude 7 | * 8 | * See normalize_(int64_t) for details 9 | */ 10 | static int32_t normalizef_(int32_t i) 11 | { 12 | if (i < 0x00800000) { 13 | int32_t shift = __builtin_clz(i) - 8; 14 | return (i << shift) - (shift << 23); 15 | } 16 | return i; 17 | } 18 | #endif 19 | -------------------------------------------------------------------------------- /src/math/float/remquof.c: -------------------------------------------------------------------------------- 1 | #include "remquof.h" 2 | 3 | float remquof(float numerator, float denominator, int quotient[static 1]) 4 | { 5 | return remquof_(numerator, denominator, quotient); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/rintf.c: -------------------------------------------------------------------------------- 1 | #include "rintf.h" 2 | #include "../rounding.h" 3 | 4 | float rintf(float x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_rintf(x); 8 | #endif 9 | return rintf_(x); 10 | } 11 | 12 | #ifdef __wasm__ 13 | float nearbyintf(float) __attribute__((alias("rintf"))); 14 | #endif 15 | -------------------------------------------------------------------------------- /src/math/float/rintf.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static float rintf_(float x) 4 | { 5 | const float rectifier = 0x1p23f; 6 | float r = fabsf(x); 7 | 8 | if (r < rectifier) { 9 | float y = r + rectifier; 10 | return copysignf(y - rectifier, x); 11 | } 12 | 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /src/math/float/roundf.c: -------------------------------------------------------------------------------- 1 | #include "roundf.h" 2 | 3 | float roundf(float x) { return roundf_(x); } 4 | -------------------------------------------------------------------------------- /src/math/float/roundf.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static float roundf_(float x) 4 | { 5 | return trunc(x + copysign(0.5, x)); 6 | } 7 | -------------------------------------------------------------------------------- /src/math/float/scalblnf.c: -------------------------------------------------------------------------------- 1 | typedef long Integer; 2 | 3 | #include 4 | #if LONG_MAX > INT_MAX 5 | #define SCALBNF scalblnf 6 | #include "scalbnf.h" 7 | #endif 8 | -------------------------------------------------------------------------------- /src/math/float/scalbnf.c: -------------------------------------------------------------------------------- 1 | #define SCALBNF scalbnf 2 | 3 | typedef int Integer; 4 | 5 | #include "scalbnf.h" 6 | #include 7 | 8 | float ldexpf(float, int) __attribute__((alias("scalbnf"))); 9 | 10 | #if LONG_MAX == INT_MAX 11 | float scalblnf(float, long) __attribute__((alias("scalbnf"))); 12 | #endif 13 | -------------------------------------------------------------------------------- /src/math/float/scalbnf.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | #include 4 | 5 | static double coeff_(Integer exp) 6 | { 7 | if (exp >= 1024) 8 | return DBL_MAX; 9 | 10 | if (exp < -1022) 11 | return 0x1p-1023; 12 | 13 | return reinterpret(double, (uint64_t)(1023 + exp) << 52); 14 | } 15 | 16 | float SCALBNF(float x, Integer exp) 17 | { 18 | return x * coeff_(exp); 19 | } 20 | -------------------------------------------------------------------------------- /src/math/float/sinf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/sincosf.h" 2 | 3 | float sinf(float x) 4 | { 5 | double y; 6 | unsigned q = __rem_pio2f(x, &y); 7 | 8 | y = q & 1 ? kernel_cosf_(y) : kernel_sinf_(y); 9 | 10 | return q & 2 ? -y : y; 11 | } 12 | -------------------------------------------------------------------------------- /src/math/float/sinhf.c: -------------------------------------------------------------------------------- 1 | #include "expm1f.h" 2 | #include 3 | 4 | float sinhf(float x) 5 | { 6 | float r = fabsf(x); 7 | double y = expm1f_(r); 8 | 9 | return copysign(y, x) * (0.5 + 0.5 / (y + 1)); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/sqrtf.c: -------------------------------------------------------------------------------- 1 | float sqrtf(float x) 2 | { 3 | return __builtin_sqrtf(x); 4 | } 5 | -------------------------------------------------------------------------------- /src/math/float/tanf.c: -------------------------------------------------------------------------------- 1 | int __rem_pio2f(float x, double y[static 1]); 2 | 3 | /* Restriction of (x -> √x cot(√x)) to [0, (π/4)^2] */ 4 | static double kernel_(double x) 5 | { 6 | const double c[] = { 7 | 9.9999999547970088679e-1, 8 | -3.3333297156778390385e-1, 9 | -2.2226847402057085257e-2, 10 | -2.0958255714778903209e-3, 11 | -2.4838647503256150943e-4 12 | }; 13 | 14 | return (((c[4] * x + c[3]) * x + c[2]) * x + c[1]) * x + c[0]; 15 | } 16 | 17 | float tanf(float x) 18 | { 19 | double y; 20 | unsigned q = __rem_pio2f(x, &y); 21 | double ycoty = kernel_(y * y); 22 | 23 | return q & 1 ? ycoty / -y : y / ycoty; 24 | } 25 | -------------------------------------------------------------------------------- /src/math/float/tanhf.c: -------------------------------------------------------------------------------- 1 | #include "expm1f.h" 2 | #include 3 | 4 | static float right_(float x) 5 | { 6 | if (x > 9.010913f) 7 | return 1; 8 | 9 | double y = expm1f_(2 * x); 10 | 11 | return y / (y + 2); 12 | } 13 | 14 | float tanhf(float x) 15 | { 16 | return copysignf(right_(fabsf(x)), x); 17 | } 18 | -------------------------------------------------------------------------------- /src/math/float/tgammaf.c: -------------------------------------------------------------------------------- 1 | #include "kernel/lanczos.h" 2 | #include "finite/log2f.h" 3 | #include "finite/sinpif.h" 4 | #include "exp2f.h" 5 | #include 6 | 7 | static double gamma1p_(double z) 8 | { 9 | const double log2e = 1.442695040888963407; 10 | 11 | double base = lanczos_g_ + 0.5 + z; 12 | 13 | return exp2f_((0.5 + z) * log2f_(base) - log2e * base) * lanczos_series_(z); 14 | } 15 | 16 | float tgammaf(float z) 17 | { 18 | const double pi = 3.14159265358979324; 19 | 20 | if (z == 0) 21 | return copysignf(INFINITY, z); 22 | 23 | if (z == INFINITY) 24 | return INFINITY; 25 | 26 | if (z < 0.5f) { 27 | if (rintf(z) == z) 28 | return NAN; 29 | return pi / (sinpif_(z) * gamma1p_(-z)); 30 | } 31 | 32 | return gamma1p_(z - 1.0); 33 | } 34 | -------------------------------------------------------------------------------- /src/math/float/truncf.c: -------------------------------------------------------------------------------- 1 | #include "truncf.h" 2 | #include "../rounding.h" 3 | 4 | float truncf(float x) 5 | { 6 | #ifdef METALLIC_FAST_ROUNDING 7 | return __builtin_truncf(x); 8 | #endif 9 | return truncf_(x); 10 | } 11 | -------------------------------------------------------------------------------- /src/math/float/truncf.h: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | #include 3 | 4 | static float truncf_(float x) 5 | { 6 | const int32_t mask = 0xFF800000; 7 | int32_t bits = reinterpret(int32_t, x); 8 | int32_t magnitude = bits & 0x7FFFFFFF; 9 | 10 | if (magnitude < 0x3F800000) /* 1 */ 11 | return reinterpret(float, bits & 0x80000000); 12 | 13 | if (magnitude < 0x4B000000) /* 0x1p23 */ 14 | return reinterpret(float, mask >> ((magnitude >> 23) - 127) & bits); 15 | 16 | return x; 17 | } 18 | -------------------------------------------------------------------------------- /src/math/long-double/normalizel.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_NORMALIZEL_H 2 | #define METALLIC_NORMALIZEL_H 3 | 4 | #include "../../soft/integer/clzti2.h" 5 | 6 | /* Normalize nonzero magnitude 7 | * 8 | * See normalize_(int64_t) for details 9 | */ 10 | static __int128 normalizel_(__int128 i) 11 | { 12 | if (i < (__int128)1 << 112) { 13 | int shift = clzti2_(i) - 15; 14 | return (i << shift) - ((__int128)shift << 112); 15 | } 16 | return i; 17 | } 18 | #endif 19 | 20 | -------------------------------------------------------------------------------- /src/math/long-double/truncl.c: -------------------------------------------------------------------------------- 1 | #include "../reinterpret.h" 2 | 3 | static int maskshift_(int exp) 4 | { 5 | if (exp < 0x3FFF) 6 | return 127; 7 | 8 | int shift = 112 + 0x3FFF - exp; 9 | return shift < 0 ? 0 : shift; 10 | } 11 | 12 | long double truncl(long double x) 13 | { 14 | const unsigned __int128 max = -1; 15 | unsigned __int128 bits = reinterpret(unsigned __int128, x); 16 | unsigned __int128 mask = max << maskshift_(bits << 1 >> 113); 17 | 18 | return reinterpret(long double, bits & mask); 19 | } 20 | -------------------------------------------------------------------------------- /src/math/reinterpret.h: -------------------------------------------------------------------------------- 1 | #define reinterpret(T, x) ((union { \ 2 | __typeof__(x) _from; \ 3 | T _to; \ 4 | char _check[sizeof(T) == sizeof(x) ? 1 : -1]; \ 5 | }){ x }._to) 6 | -------------------------------------------------------------------------------- /src/math/rounding.h: -------------------------------------------------------------------------------- 1 | #if defined(__wasm__) || defined(__aarch64__) || defined(__SSE4_1__) 2 | #define METALLIC_FAST_ROUNDING 3 | #endif 4 | -------------------------------------------------------------------------------- /src/soft/complex/complex.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static Complex complex_(Real x, Real y) 4 | { 5 | return _Generic(x, 6 | float: CMPLXF(x, y), 7 | double: CMPLX(x, y), 8 | long double: CMPLXL(x, y) 9 | ); 10 | } 11 | 12 | -------------------------------------------------------------------------------- /src/soft/complex/divdc3.c: -------------------------------------------------------------------------------- 1 | typedef double Real; 2 | typedef double _Complex Complex; 3 | 4 | #define FUNCTION __divdc3 5 | 6 | #include "division.h" 7 | -------------------------------------------------------------------------------- /src/soft/complex/muldc3.c: -------------------------------------------------------------------------------- 1 | typedef double Real; 2 | typedef double _Complex Complex; 3 | 4 | #define FUNCTION __muldc3 5 | 6 | #include "multiplication.h" 7 | -------------------------------------------------------------------------------- /src/soft/complex/mulsc3.c: -------------------------------------------------------------------------------- 1 | typedef float Real; 2 | typedef float _Complex Complex; 3 | 4 | #define FUNCTION __mulsc3 5 | 6 | #include "multiplication.h" 7 | -------------------------------------------------------------------------------- /src/soft/float/compose/product.h: -------------------------------------------------------------------------------- 1 | static unsigned __int128 compose_product_(int exp, unsigned __int128 significand) 2 | { 3 | if (exp >= 0x7FFF) 4 | return (unsigned __int128)0x7FFF << 112; 5 | 6 | if (exp > 0) { 7 | unsigned __int128 tail = significand << 1; 8 | return ((unsigned __int128)exp << 112 | tail >> 16) + (((tail & 0xFFFF) | (tail >> 16 & 1)) > 0x8000); 9 | } 10 | 11 | if (exp >= -112) { 12 | unsigned __int128 q = significand >> 16 >> -exp; 13 | unsigned __int128 r = significand << (112 + exp); 14 | return q + ((r >> 64 | (q & 1 || r & 0xFFFFFFFFFFFFFFFF)) > 0x8000000000000000); 15 | } 16 | 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /src/soft/float/eqtf2.c: -------------------------------------------------------------------------------- 1 | #include "isnanl.h" 2 | 3 | int __eqtf2(long double x, long double y) 4 | { 5 | unsigned __int128 a = reinterpret(unsigned __int128, x); 6 | unsigned __int128 b = reinterpret(unsigned __int128, y); 7 | 8 | return (a != b || isnanl_(a)) && (a | b) << 1; 9 | } 10 | 11 | int __netf2(long double, long double) __attribute__((__alias__("__eqtf2"))); 12 | -------------------------------------------------------------------------------- /src/soft/float/extenddftf2.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include "../../math/double/normalize.h" 3 | #include 4 | #include 5 | 6 | static __int128 magnitude_(int64_t i) 7 | { 8 | if (i >= 0x7FF0000000000000) 9 | return (__int128)0x78 << 120 | (__int128)i << 60; 10 | 11 | return i ? ((__int128)0x3C << 120) + ((__int128)normalize_(i) << 60) : 0; 12 | } 13 | 14 | long double __extenddftf2(double x) 15 | { 16 | int64_t i = reinterpret(int64_t, fabs(x)); 17 | 18 | return copysignl(reinterpret(long double, magnitude_(i)), x); 19 | } 20 | -------------------------------------------------------------------------------- /src/soft/float/extendsftf2.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | static uint64_t magnitude_(uint64_t i) 6 | { 7 | if (i >= 0x7FF0000000000000) 8 | return 0x7800000000000000 | i >> 4; 9 | 10 | return i ? 0x3C00000000000000 + (i >> 4) : 0; 11 | } 12 | 13 | long double __extendsftf2(float x) 14 | { 15 | uint64_t i = reinterpret(uint64_t, (double)x); 16 | uint64_t high = magnitude_(i & INT64_MAX) | (i & 0x8000000000000000); 17 | 18 | return reinterpret(long double, (unsigned __int128)high << 64); 19 | } 20 | -------------------------------------------------------------------------------- /src/soft/float/fixtfdi.c: -------------------------------------------------------------------------------- 1 | #include "fixunstfdi.h" 2 | #include "../../math/reinterpret.h" 3 | #include 4 | 5 | int64_t __fixtfdi(long double x) 6 | { 7 | __int128 bits = reinterpret(__int128, x); 8 | int64_t high = bits >> 64; 9 | int64_t sign = high >> 63; 10 | 11 | return fixunstfdi_(high & INT64_MAX, bits) + sign ^ sign; 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/float/fixtfsi.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | 4 | int32_t __fixtfsi(long double x) 5 | { 6 | uint64_t high = reinterpret(unsigned __int128, x) >> 64; 7 | 8 | if ((high & INT64_MAX) < 0x3FFF000000000000) 9 | return 0; 10 | 11 | uint64_t sign = high & 0x8000000000000000; 12 | uint64_t magnitude = (high - 0x3C00000000000000) << 4; 13 | 14 | return reinterpret(double, sign | magnitude); 15 | } 16 | -------------------------------------------------------------------------------- /src/soft/float/fixtfti.c: -------------------------------------------------------------------------------- 1 | #include "fixunstfti.h" 2 | #include "../../math/reinterpret.h" 3 | #include 4 | 5 | __int128 __fixtfti(long double x) 6 | { 7 | __int128 magnitude = fixunstfti_(reinterpret(__int128, fabsl(x))); 8 | 9 | return signbit(x) ? -magnitude : magnitude; 10 | } 11 | -------------------------------------------------------------------------------- /src/soft/float/fixunstfdi.c: -------------------------------------------------------------------------------- 1 | #include "fixunstfdi.h" 2 | #include "../../math/reinterpret.h" 3 | #include 4 | 5 | uint64_t __fixunstfdi(long double x) 6 | { 7 | __int128 bits = reinterpret(__int128, x); 8 | 9 | return fixunstfdi_(bits >> 64, bits); 10 | } 11 | -------------------------------------------------------------------------------- /src/soft/float/fixunstfdi.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static uint64_t fixunstfdi_(int64_t high, uint64_t low) 4 | { 5 | if (high < 0x3FFF000000000000) 6 | return 0; 7 | 8 | int shift = 112 + 0x3FFF - (int)(high >> 48); 9 | uint64_t significand = (high & 0x0000FFFFFFFFFFFF) | 0x0001000000000000; 10 | 11 | if (shift < 64) 12 | return significand << (64 - shift) | low >> shift; 13 | 14 | return significand >> (shift & 63); 15 | } 16 | -------------------------------------------------------------------------------- /src/soft/float/fixunstfsi.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | 4 | uint32_t __fixunstfsi(long double x) 5 | { 6 | int64_t high = reinterpret(__int128, x) >> 64; 7 | 8 | if (high < 0x3FFF000000000000) 9 | return 0; 10 | 11 | return reinterpret(double, (high - 0x3C00000000000000) << 4); 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/float/fixunstfti.c: -------------------------------------------------------------------------------- 1 | #include "fixunstfti.h" 2 | #include "../../math/reinterpret.h" 3 | 4 | unsigned __int128 __fixunstfti(long double x) 5 | { 6 | return fixunstfti_(reinterpret(__int128, x)); 7 | } 8 | -------------------------------------------------------------------------------- /src/soft/float/fixunstfti.h: -------------------------------------------------------------------------------- 1 | static unsigned __int128 fixunstfti_(__int128 bits) 2 | { 3 | const unsigned __int128 implied = (unsigned __int128)1 << 112; 4 | 5 | if (bits >> 64 < 0x3FFF000000000000) 6 | return 0; 7 | 8 | int shift = 112 + 0x3FFF - (int)(bits >> 112); 9 | unsigned __int128 significand = (bits & (implied - 1)) | implied; 10 | 11 | return shift < 0 ? significand << -shift : significand >> shift; 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/float/floatditf.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | long double __floatditf(int64_t a) 6 | { 7 | if (!a) 8 | return 0; 9 | 10 | uint64_t sign = a & 0x8000000000000000; 11 | uint64_t magnitude = llabs(a); 12 | 13 | int space = __builtin_clzll(magnitude); 14 | unsigned __int128 significand = (unsigned __int128)(magnitude << space & INT64_MAX) << 49; 15 | unsigned __int128 exp = 0x3FFF + 63 - space; 16 | 17 | return reinterpret(long double, significand | exp << 112 | (unsigned __int128)sign << 64); 18 | } 19 | -------------------------------------------------------------------------------- /src/soft/float/floatsitf.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | long double __floatsitf(int32_t a) 6 | { 7 | if (!a) 8 | return 0; 9 | 10 | uint64_t sign = (uint64_t)a & 0x8000000000000000; 11 | uint64_t magnitude = (reinterpret(uint64_t, fabs((double)a)) >> 4) + 0x3C00000000000000; 12 | 13 | return reinterpret(long double, (unsigned __int128)(sign | magnitude) << 64); 14 | } 15 | -------------------------------------------------------------------------------- /src/soft/float/floattitf.c: -------------------------------------------------------------------------------- 1 | #include "../integer/clzti2.h" 2 | #include "../../math/reinterpret.h" 3 | 4 | long double __floattitf(__int128 a) 5 | { 6 | const unsigned __int128 mask = (unsigned __int128)-1 >> 16; 7 | 8 | if (!a) 9 | return 0; 10 | 11 | unsigned __int128 sign = a & (unsigned __int128)1 << 127; 12 | unsigned __int128 magnitude = a < 0 ? -a : a; 13 | 14 | int space = clzti2_(magnitude); 15 | unsigned __int128 normalized = magnitude << space; 16 | unsigned __int128 adjustment = normalized & 0x4000 && normalized & 0xBFFF; 17 | unsigned __int128 significand = normalized >> 15 & mask; 18 | unsigned __int128 exp = 0x3FFF + 127 - space; 19 | 20 | return reinterpret(long double, (significand | exp << 112 | sign) + adjustment); 21 | } 22 | -------------------------------------------------------------------------------- /src/soft/float/floatunditf.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | 4 | long double __floatunditf(uint64_t a) 5 | { 6 | if (!a) 7 | return 0; 8 | 9 | int space = __builtin_clzll(a); 10 | unsigned __int128 significand = (unsigned __int128)(a << space & INT64_MAX) << 49; 11 | unsigned __int128 exp = 0x3FFF + 63 - space; 12 | 13 | return reinterpret(long double, significand | exp << 112); 14 | } 15 | -------------------------------------------------------------------------------- /src/soft/float/floatunsitf.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | 4 | long double __floatunsitf(uint32_t a) 5 | { 6 | if (!a) 7 | return 0; 8 | 9 | uint64_t high = (reinterpret(uint64_t, (double)a) >> 4) + 0x3C00000000000000; 10 | 11 | return reinterpret(long double, (unsigned __int128)high << 64); 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/float/floatuntitf.c: -------------------------------------------------------------------------------- 1 | #include "../integer/clzti2.h" 2 | #include "../../math/reinterpret.h" 3 | 4 | long double __floatuntitf(unsigned __int128 a) 5 | { 6 | const unsigned __int128 mask = (unsigned __int128)-1 >> 16; 7 | 8 | if (!a) 9 | return 0; 10 | 11 | int space = clzti2_(a); 12 | unsigned __int128 normalized = a << space; 13 | unsigned __int128 adjustment = normalized & 0x4000 && normalized & 0xBFFF; 14 | unsigned __int128 significand = normalized >> 15 & mask; 15 | unsigned __int128 exp = 0x3FFF + 127 - space; 16 | 17 | return reinterpret(long double, (significand | exp << 112) + adjustment); 18 | } 19 | -------------------------------------------------------------------------------- /src/soft/float/isnanl.h: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | 3 | static int isnanl_(unsigned __int128 a) 4 | { 5 | return a << 1 > (unsigned __int128)0x7FFF << 113; 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/float/trunctfsf2.c: -------------------------------------------------------------------------------- 1 | #include "../../math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | static uint64_t magnitude_(uint64_t i) 6 | { 7 | if (i > 0x7FFF000000000000) 8 | return i; 9 | 10 | if (i >= 0x43FF000000000000) 11 | return 0x7FF0000000000000; 12 | 13 | if (i > 0x3C00000000000000) 14 | return (i - 0x3C00000000000000) << 4; 15 | 16 | return 0; 17 | } 18 | 19 | float __trunctfsf2(long double x) 20 | { 21 | unsigned __int128 bits = reinterpret(unsigned __int128, x); 22 | uint64_t i = bits >> 64 | !!(bits & UINT64_MAX); 23 | 24 | return reinterpret(double, magnitude_(i & INT64_MAX) | (i & 0x8000000000000000)); 25 | } 26 | -------------------------------------------------------------------------------- /src/soft/float/unordtf2.c: -------------------------------------------------------------------------------- 1 | #include "unordtf2.h" 2 | 3 | int __unordtf2(long double x, long double y) 4 | { 5 | unsigned __int128 a = reinterpret(unsigned __int128, x); 6 | unsigned __int128 b = reinterpret(unsigned __int128, y); 7 | 8 | return unordtf2_(a, b); 9 | } 10 | -------------------------------------------------------------------------------- /src/soft/float/unordtf2.h: -------------------------------------------------------------------------------- 1 | #include "isnanl.h" 2 | 3 | static int unordtf2_(unsigned __int128 a, unsigned __int128 b) 4 | { 5 | return isnanl_(a) || isnanl_(b); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/ashlti3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | __int128 __ashlti3(__int128 x, int shift) 4 | { 5 | int64_t high = x >> 64; 6 | uint64_t low = x; 7 | 8 | if (shift & 64) 9 | return (__int128)(low << shift) << 64; 10 | else if (shift) 11 | return (__int128)(high << shift | low >> (64 - shift)) << 64 | low << shift; 12 | else 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /src/soft/integer/ashrti3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | __int128 __ashrti3(__int128 x, int shift) 4 | { 5 | int64_t high = x >> 64; 6 | uint64_t low = x; 7 | 8 | if (shift & 64) 9 | return high >> shift; 10 | else if (shift) 11 | return (__int128)(high >> shift) << 64 | (high << (64 - shift) | low >> shift); 12 | else 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /src/soft/integer/clzti2.h: -------------------------------------------------------------------------------- 1 | static int clzti2_(unsigned __int128 x) 2 | { 3 | return x >> 64 ? __builtin_clzll(x >> 64) : 64 | __builtin_clzll(x); 4 | } 5 | 6 | -------------------------------------------------------------------------------- /src/soft/integer/divti3.c: -------------------------------------------------------------------------------- 1 | #include "udivmodti4.h" 2 | 3 | __int128 __divti3(__int128 a, __int128 b) 4 | { 5 | __int128 signa = a >> 127; 6 | __int128 signb = b >> 127; 7 | __int128 signq = signa ^ signb; 8 | unsigned __int128 r; 9 | 10 | return udivmodti4_(a + signa ^ signa, b + signb ^ signb, &r) + signq ^ signq; 11 | } 12 | -------------------------------------------------------------------------------- /src/soft/integer/fixdfti.c: -------------------------------------------------------------------------------- 1 | #include "fixdfti.h" 2 | #include 3 | 4 | __int128 __fixdfti(double x) 5 | { 6 | return fixdfti_(x); 7 | } 8 | -------------------------------------------------------------------------------- /src/soft/integer/fixdfti.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static __int128 fixdfti_(double x) 5 | { 6 | double r = fabs(x); 7 | uint64_t high = 0x1p-64 * r; 8 | uint64_t low = r - 0x1p64 * high; 9 | __int128 abs = (__int128)high << 64 | low; 10 | 11 | return signbit(x) ? -abs : abs; 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/integer/fixsfti.c: -------------------------------------------------------------------------------- 1 | #include "fixsfti.h" 2 | 3 | __int128 __fixsfti(float x) 4 | { 5 | return fixsfti_(x); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/fixsfti.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static __int128 fixsfti_(float x) 5 | { 6 | float r = fabsf(x); 7 | uint64_t high = 0x1p-64f * r; 8 | uint64_t low = r - 0x1p64f * high; 9 | __int128 abs = (__int128)high << 64 | low; 10 | 11 | return signbit(x) ? -abs : abs; 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/integer/fixunsdfti.c: -------------------------------------------------------------------------------- 1 | #include "fixunsdfti.h" 2 | 3 | unsigned __int128 __fixunsdfti(double x) 4 | { 5 | return fixunsdfti_(x); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/fixunsdfti.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned __int128 fixunsdfti_(double x) 4 | { 5 | if (x < 1) 6 | return 0; 7 | 8 | uint64_t high = 0x1p-64 * x; 9 | uint64_t low = x - 0x1p64 * high; 10 | 11 | return (unsigned __int128)high << 64 | low; 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/integer/fixunssfti.c: -------------------------------------------------------------------------------- 1 | #include "fixunssfti.h" 2 | 3 | unsigned __int128 __fixunssfti(float x) 4 | { 5 | return fixunssfti_(x); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/fixunssfti.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned __int128 fixunssfti_(float x) 4 | { 5 | if (x < 1) 6 | return 0; 7 | 8 | uint64_t high = 0x1p-64f * x; 9 | uint64_t low = x - 0x1p64f * high; 10 | 11 | return (unsigned __int128)high << 64 | low; 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/integer/floattidf.c: -------------------------------------------------------------------------------- 1 | #include "floattidf.h" 2 | 3 | double __floattidf(__int128 a) 4 | { 5 | return floattidf_(a); 6 | } 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/soft/integer/floattidf.h: -------------------------------------------------------------------------------- 1 | #include "clzti2.h" 2 | #include "../../math/reinterpret.h" 3 | #include 4 | 5 | static double floattidf_(__int128 a) 6 | { 7 | const unsigned __int128 bit = (unsigned __int128)1 << 74; 8 | const unsigned __int128 mask = 3 * bit - 1; 9 | 10 | if (!a) 11 | return 0; 12 | 13 | unsigned __int128 magnitude = a < 0 ? -a : a; 14 | 15 | int space = clzti2_(magnitude); 16 | unsigned __int128 normalized = magnitude << space; 17 | uint64_t adjustment = normalized & bit && normalized & mask; 18 | uint64_t significand = normalized >> 75 & 0x000FFFFFFFFFFFFF; 19 | uint64_t exp = 1023 + 127 - space; 20 | uint64_t sign = a >> 64 & 0x8000000000000000; 21 | 22 | return reinterpret(double, (significand | exp << 52 | sign) + adjustment); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/soft/integer/floattisf.c: -------------------------------------------------------------------------------- 1 | #include "floattisf.h" 2 | 3 | float __floattisf(__int128 a) 4 | { 5 | return floattisf_(a); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/floattisf.h: -------------------------------------------------------------------------------- 1 | #include "clzti2.h" 2 | #include "../../math/reinterpret.h" 3 | #include 4 | 5 | static float floattisf_(__int128 a) 6 | { 7 | const unsigned __int128 bit = (unsigned __int128)1 << 103; 8 | const unsigned __int128 mask = 3 * bit - 1; 9 | 10 | if (!a) 11 | return 0; 12 | 13 | unsigned __int128 magnitude = a < 0 ? -a : a; 14 | 15 | int space = clzti2_(magnitude); 16 | unsigned __int128 normalized = magnitude << space; 17 | uint32_t adjustment = normalized & bit && normalized & mask; 18 | uint32_t significand = normalized >> 104 & 0x007FFFFF; 19 | uint32_t exp = 127 + 127 - space; 20 | uint32_t sign = a >> 96 & 0x80000000; 21 | 22 | return reinterpret(float, (significand | exp << 23 | sign) + adjustment); 23 | } 24 | -------------------------------------------------------------------------------- /src/soft/integer/floatuntidf.c: -------------------------------------------------------------------------------- 1 | #include "floatuntidf.h" 2 | 3 | double __floatuntidf(unsigned __int128 a) 4 | { 5 | return floatuntidf_(a); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/floatuntidf.h: -------------------------------------------------------------------------------- 1 | #include "clzti2.h" 2 | #include "../../math/reinterpret.h" 3 | #include 4 | 5 | static double floatuntidf_(unsigned __int128 a) 6 | { 7 | const unsigned __int128 bit = (unsigned __int128)1 << 74; 8 | const unsigned __int128 mask = 3 * bit - 1; 9 | 10 | if (!a) 11 | return 0; 12 | 13 | int space = clzti2_(a); 14 | unsigned __int128 normalized = a << space; 15 | uint64_t adjustment = normalized & bit && normalized & mask; 16 | uint64_t significand = normalized >> 75 & 0x000FFFFFFFFFFFFF; 17 | uint64_t exp = 1023 + 127 - space; 18 | 19 | return reinterpret(double, (significand | exp << 52) + adjustment); 20 | } 21 | -------------------------------------------------------------------------------- /src/soft/integer/floatuntisf.c: -------------------------------------------------------------------------------- 1 | #include "floatuntisf.h" 2 | 3 | float __floatuntisf(unsigned __int128 a) 4 | { 5 | return floatuntisf_(a); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/floatuntisf.h: -------------------------------------------------------------------------------- 1 | #include "clzti2.h" 2 | #include "../../math/reinterpret.h" 3 | #include 4 | 5 | static float floatuntisf_(unsigned __int128 a) 6 | { 7 | const unsigned __int128 bit = (unsigned __int128)1 << 103; 8 | const unsigned __int128 mask = 3 * bit - 1; 9 | 10 | if (!a) 11 | return 0; 12 | 13 | int space = clzti2_(a); 14 | unsigned __int128 normalized = a << space; 15 | uint32_t adjustment = normalized & bit && normalized & mask; 16 | uint32_t significand = normalized >> 104 & 0x7FFFFF; 17 | uint32_t exp = 127 + 127 - space; 18 | 19 | return reinterpret(float, (significand | exp << 23) + adjustment); 20 | } 21 | -------------------------------------------------------------------------------- /src/soft/integer/lshrti3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | unsigned __int128 __lshrti3(unsigned __int128 x, int shift) 4 | { 5 | uint64_t high = x >> 64; 6 | uint64_t low = x; 7 | 8 | if (shift & 64) 9 | return high >> shift; 10 | else if (shift) 11 | return (unsigned __int128)(high >> shift) << 64 | (high << (64 - shift) | low >> shift); 12 | else 13 | return x; 14 | } 15 | -------------------------------------------------------------------------------- /src/soft/integer/modti3.c: -------------------------------------------------------------------------------- 1 | #include "udivmodti4.h" 2 | 3 | __int128 __modti3(__int128 a, __int128 b) 4 | { 5 | unsigned __int128 r; 6 | unsigned __int128 sign = a >> 127; 7 | 8 | udivmodti4_(a + sign ^ sign, b < 0 ? -b : b, &r); 9 | 10 | return r + sign ^ sign; 11 | } 12 | -------------------------------------------------------------------------------- /src/soft/integer/multi3.c: -------------------------------------------------------------------------------- 1 | #include "umulditi3.h" 2 | #include 3 | 4 | unsigned __int128 __multi3(unsigned __int128 a, unsigned __int128 b) 5 | { 6 | uint64_t a1 = a >> 64; 7 | uint64_t b1 = b >> 64; 8 | uint64_t a0 = a; 9 | uint64_t b0 = b; 10 | 11 | return ((unsigned __int128)(a1 * b0 + a0 * b1) << 64) + umulditi3_(a0, b0); 12 | } 13 | -------------------------------------------------------------------------------- /src/soft/integer/udivmodti4.c: -------------------------------------------------------------------------------- 1 | #include "udivmodti4.h" 2 | 3 | unsigned __int128 __udivmodti4(unsigned __int128 a, unsigned __int128 b, unsigned __int128 r[static 1]) 4 | { 5 | return udivmodti4_(a, b, r); 6 | } 7 | -------------------------------------------------------------------------------- /src/soft/integer/udivti3.c: -------------------------------------------------------------------------------- 1 | #include "udivmodti4.h" 2 | 3 | unsigned __int128 __udivti3(unsigned __int128 a, unsigned __int128 b) 4 | { 5 | unsigned __int128 r; 6 | 7 | return udivmodti4_(a, b, &r); 8 | } 9 | -------------------------------------------------------------------------------- /src/soft/integer/umodti3.c: -------------------------------------------------------------------------------- 1 | #include "udivmodti4.h" 2 | 3 | unsigned __int128 __umodti3(unsigned __int128 a, unsigned __int128 b) 4 | { 5 | unsigned __int128 r; 6 | 7 | udivmodti4_(a, b, &r); 8 | 9 | return r; 10 | } 11 | -------------------------------------------------------------------------------- /src/soft/integer/umulditi3.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static unsigned __int128 umulditi3_(uint64_t a, uint64_t b) 4 | { 5 | #if defined(__x86_64__) || defined(__aarch64__) 6 | return (unsigned __int128)a * b; 7 | #endif 8 | 9 | uint32_t a1 = a >> 32; 10 | uint32_t b1 = b >> 32; 11 | uint32_t a0 = a; 12 | uint32_t b0 = b; 13 | 14 | return ((unsigned __int128)a1 * b1 << 64 | (uint64_t)a0 * b0) 15 | + ((unsigned __int128)a1 * b0 << 32) 16 | + ((unsigned __int128)a0 * b1 << 32); 17 | } 18 | -------------------------------------------------------------------------------- /src/soft/integer/umulti4.h: -------------------------------------------------------------------------------- 1 | #include "umulditi3.h" 2 | 3 | static unsigned __int128 umulti4_(unsigned __int128 a, unsigned __int128 b, unsigned __int128 high[static 1]) 4 | { 5 | uint64_t a1 = a >> 64; 6 | uint64_t b1 = b >> 64; 7 | uint64_t a0 = a; 8 | uint64_t b0 = b; 9 | 10 | unsigned __int128 a1b1 = umulditi3_(a1, b1); 11 | unsigned __int128 a1b0 = umulditi3_(a1, b0); 12 | unsigned __int128 a0b1 = umulditi3_(a0, b1); 13 | unsigned __int128 a0b0 = umulditi3_(a0, b0); 14 | unsigned __int128 mid = (a0b0 >> 64) + (uint64_t)a1b0 + (uint64_t)a0b1; 15 | 16 | *high = (mid >> 64) + (a1b0 >> 64) + (a0b1 >> 64) + a1b1; 17 | return mid << 64 | (uint64_t)a0b0; 18 | } 19 | -------------------------------------------------------------------------------- /src/soft/powi/powi.h: -------------------------------------------------------------------------------- 1 | static Scalar powu_(Scalar x, unsigned i) 2 | { 3 | Scalar y = 1; 4 | 5 | for (; i; i >>= 1) { 6 | if (i & 1) 7 | y *= x; 8 | x *= x; 9 | } 10 | return y; 11 | } 12 | 13 | static Scalar powi_(Scalar x, int i) 14 | { 15 | if (i < 0) 16 | return powu_(1 / x, -i); 17 | 18 | return powu_(x, i); 19 | } 20 | -------------------------------------------------------------------------------- /src/soft/powi/powidf2.c: -------------------------------------------------------------------------------- 1 | typedef double Scalar; 2 | 3 | #include "powi.h" 4 | 5 | double __powidf2(double x, int i) 6 | { 7 | return powi_(x, i); 8 | } 9 | -------------------------------------------------------------------------------- /src/soft/powi/powisf2.c: -------------------------------------------------------------------------------- 1 | typedef float Scalar; 2 | 3 | #include "powi.h" 4 | 5 | float __powisf2(float x, int i) 6 | { 7 | return powi_(x, i); 8 | } 9 | -------------------------------------------------------------------------------- /src/stdio/FILE.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_FILE_H 2 | #define METALLIC_FILE_H 3 | 4 | #include 5 | #include 6 | 7 | typedef long long off_t; 8 | typedef struct __FILE FILE; 9 | 10 | struct __FILE 11 | { 12 | unsigned state; 13 | unsigned avail; 14 | unsigned char cache[4 * MB_LEN_MAX]; 15 | 16 | unsigned char* base; 17 | unsigned char* ptr; 18 | unsigned char* end; 19 | 20 | size_t (*read)(FILE*, void*, size_t); 21 | size_t (*write)(FILE*, const void*, size_t); 22 | off_t (*seek)(FILE*, off_t, int); 23 | int (*close)(FILE*); 24 | 25 | int fd; 26 | }; 27 | 28 | enum 29 | { 30 | eofbit_ = 0x10, 31 | errbit_ = 0x20, 32 | appbit_ = 0x80, 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/stdio/FILE_.h: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | size_t __stdio_read(FILE[restrict static 1], void* restrict, size_t); 4 | size_t __stdio_write(FILE[restrict static 1], const void* restrict, size_t); 5 | off_t __stdio_seek(FILE[static 1], off_t, int); 6 | int __stdio_close(FILE[static 1]); 7 | 8 | #define FILE_(_fd, ...) ((FILE){ \ 9 | .read = __stdio_read, \ 10 | .write = __stdio_write, \ 11 | .seek = __stdio_seek, \ 12 | .close = __stdio_close, \ 13 | .fd = (_fd), \ 14 | __VA_ARGS__ \ 15 | }) 16 | -------------------------------------------------------------------------------- /src/stdio/_close.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | int __close(int); 4 | 5 | int __stdio_close(FILE stream[restrict static 1]) 6 | { 7 | return __close(stream->fd); 8 | } 9 | -------------------------------------------------------------------------------- /src/stdio/_read.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | extern _Thread_local int errno; 4 | 5 | long __read(int, void*, size_t); 6 | 7 | size_t __stdio_read(FILE stream[restrict static 1], void* restrict buffer, size_t size) 8 | { 9 | long count = __read(stream->fd, buffer, size); 10 | 11 | if (count >= 0) { 12 | stream->state |= (count < size) * eofbit_; 13 | return count; 14 | } 15 | 16 | stream->state |= errbit_; 17 | errno = -count; 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/stdio/_write.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | extern _Thread_local int errno; 4 | 5 | long __write(int, const void*, size_t); 6 | 7 | size_t __stdio_write(FILE stream[restrict static 1], const void* restrict buffer, size_t size) 8 | { 9 | long count = __write(stream->fd, buffer, size); 10 | 11 | if (count >= 0) { 12 | stream->state |= (count < size) * errbit_; 13 | return count; 14 | } 15 | 16 | stream->state |= errbit_; 17 | errno = -count; 18 | return 0; 19 | } 20 | -------------------------------------------------------------------------------- /src/stdio/clearerr.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | void clearerr(FILE stream[static 1]) 4 | { 5 | stream->state = 0; 6 | } 7 | -------------------------------------------------------------------------------- /src/stdio/fclose.c: -------------------------------------------------------------------------------- 1 | #include "flush.h" 2 | #include "FILE.h" 3 | #include 4 | #include 5 | 6 | extern _Thread_local int errno; 7 | 8 | int fclose(FILE stream[static 1]) 9 | { 10 | flush_(stream); 11 | 12 | int status = stream->close(stream); 13 | free(stream); 14 | 15 | if (status >= 0) 16 | return 0; 17 | 18 | errno = -status; 19 | return EOF; 20 | } 21 | -------------------------------------------------------------------------------- /src/stdio/feof.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | int feof(FILE stream[static 1]) 4 | { 5 | return stream->state & eofbit_; 6 | } 7 | -------------------------------------------------------------------------------- /src/stdio/ferror.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | int ferror(FILE stream[static 1]) 4 | { 5 | return stream->state & errbit_; 6 | } 7 | -------------------------------------------------------------------------------- /src/stdio/fgetpos.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | 4 | off_t __ftello(FILE stream[static 1]); 5 | 6 | int fgetpos(FILE stream[restrict static 1], fpos_t position[restrict static 1]) 7 | { 8 | position->_offset = __ftello(stream); 9 | 10 | return position->_offset == -1; 11 | } 12 | -------------------------------------------------------------------------------- /src/stdio/flush.h: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | 4 | static int flush_(FILE stream[static 1]) 5 | { 6 | if (stream->base) { 7 | stream->write(stream, (void*)0, 0); 8 | 9 | if (stream->state & errbit_) 10 | return EOF; 11 | } 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /src/stdio/fopen.c: -------------------------------------------------------------------------------- 1 | #include "modeflags.h" 2 | #include "FILE_.h" 3 | #include 4 | 5 | extern _Thread_local int errno; 6 | 7 | int __open(const char[static 1], int, int); 8 | 9 | FILE* fopen(const char path[restrict static 1], const char mode[restrict static 1]) 10 | { 11 | int flags = modeflags_(mode); 12 | int fd = __open(path, flags, 0666); 13 | 14 | if (fd >= 0) { 15 | FILE* file = malloc(sizeof(FILE)); 16 | *file = FILE_(fd, .state = flags & O_APPEND ? appbit_ : 0); 17 | return file; 18 | } 19 | 20 | errno = -fd; 21 | return (void*)0; 22 | } 23 | -------------------------------------------------------------------------------- /src/stdio/fprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int fprintf(FILE* restrict stream, const char format[restrict static 1], ...) 5 | { 6 | va_list list; 7 | va_start(list, format); 8 | 9 | int status = vfprintf(stream, format, list); 10 | va_end(list); 11 | 12 | return status; 13 | } 14 | -------------------------------------------------------------------------------- /src/stdio/fputs.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | 4 | int fputs(const char s[restrict static 1], FILE stream[restrict static 1]) 5 | { 6 | size_t size = strlen(s); 7 | 8 | return (stream->write(stream, s, size) == size) - 1; 9 | } 10 | -------------------------------------------------------------------------------- /src/stdio/fread.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | 4 | static size_t wrapper_(unsigned char* restrict buffer, size_t size, FILE stream[restrict static 1]) 5 | { 6 | size_t hit = stream->avail < size ? stream->avail : size; 7 | size_t missed = size - hit; 8 | 9 | memcpy(buffer, stream->cache + sizeof(stream->cache) - stream->avail, hit); 10 | stream->avail -= hit; 11 | return hit + (missed ? stream->read(stream, buffer + hit, missed) : 0); 12 | } 13 | 14 | size_t fread(void* restrict buffer, size_t size, size_t count, FILE stream[restrict static 1]) 15 | { 16 | return wrapper_(buffer, size * count, stream) / size; 17 | } 18 | -------------------------------------------------------------------------------- /src/stdio/fseek.c: -------------------------------------------------------------------------------- 1 | #include "flush.h" 2 | #include "FILE.h" 3 | 4 | int __fseeko(FILE stream[static 1], off_t offset, int origin) 5 | { 6 | if (origin == SEEK_CUR) 7 | offset -= stream->avail; 8 | 9 | stream->avail = 0; 10 | 11 | return flush_(stream) || stream->seek(stream, offset, origin) == -1; 12 | } 13 | 14 | int fseek(FILE stream[static 1], long offset, int origin) 15 | { 16 | return __fseeko(stream, offset, origin); 17 | } 18 | -------------------------------------------------------------------------------- /src/stdio/fsetpos.c: -------------------------------------------------------------------------------- 1 | #include "flush.h" 2 | #include "FILE.h" 3 | #include 4 | 5 | int fsetpos(FILE stream[static 1], const fpos_t position[static 1]) 6 | { 7 | stream->avail = 0; 8 | 9 | return flush_(stream) || stream->seek(stream, position->_offset, SEEK_SET) == -1; 10 | } 11 | -------------------------------------------------------------------------------- /src/stdio/ftell.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | 4 | off_t __ftello(FILE stream[static 1]) 5 | { 6 | ptrdiff_t buffered = stream->base ? stream->ptr - stream->base : 0; 7 | off_t position = stream->seek(stream, 0, stream->state & appbit_ ? SEEK_END : SEEK_CUR); 8 | 9 | return position == -1 ? -1 : position - stream->avail + buffered; 10 | } 11 | 12 | long ftell(FILE stream[static 1]) 13 | { 14 | return __ftello(stream); 15 | } 16 | -------------------------------------------------------------------------------- /src/stdio/fwrite.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | 3 | size_t fwrite(const void* restrict buffer, size_t size, size_t count, FILE stream[restrict static 1]) 4 | { 5 | return stream->write(stream, buffer, size * count) / size; 6 | } 7 | -------------------------------------------------------------------------------- /src/stdio/getc.c: -------------------------------------------------------------------------------- 1 | #include "getc.h" 2 | 3 | int getc(FILE stream[static 1]) 4 | { 5 | return getc_(stream); 6 | } 7 | 8 | int fgetc(FILE[static 1]) __attribute__((alias("getc"))); 9 | -------------------------------------------------------------------------------- /src/stdio/getc.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_GETC_H 2 | #define METALLIC_GETC_H 3 | 4 | #include "FILE.h" 5 | #include 6 | 7 | static int getc_(FILE stream[static 1]) 8 | { 9 | if (stream->avail) 10 | return stream->cache[sizeof(stream->cache) - stream->avail--]; 11 | 12 | unsigned char c; 13 | return stream->read(stream, &c, 1) ? c : EOF; 14 | } 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/stdio/getchar.c: -------------------------------------------------------------------------------- 1 | #include "getc.h" 2 | #include 3 | 4 | int getchar(void) 5 | { 6 | return getc_(stdin); 7 | } 8 | -------------------------------------------------------------------------------- /src/stdio/gets.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* gets(char buffer[static 1]) 4 | { 5 | for (char* s = buffer; ; ++s) { 6 | int c = getchar(); 7 | 8 | switch (c) { 9 | case '\n': 10 | *s = '\0'; 11 | return buffer; 12 | case EOF: 13 | *s = '\0'; 14 | return (void*)0; 15 | } 16 | *s = c; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/stdio/printf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int printf(const char format[restrict static 1], ...) 5 | { 6 | va_list list; 7 | va_start(list, format); 8 | 9 | int status = vfprintf(stdout, format, list); 10 | va_end(list); 11 | 12 | return status; 13 | } 14 | -------------------------------------------------------------------------------- /src/stdio/putc.c: -------------------------------------------------------------------------------- 1 | #include "putc.h" 2 | 3 | int putc(int c, FILE stream[static 1]) 4 | { 5 | return putc_(stream, c); 6 | } 7 | 8 | int fputc(int, FILE[static 1]) __attribute__((alias("putc"))); 9 | -------------------------------------------------------------------------------- /src/stdio/putc.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_PUTC_H 2 | #define METALLIC_PUTC_H 3 | 4 | #include "FILE.h" 5 | #include 6 | 7 | static int putc_(FILE stream[static 1], int c) 8 | { 9 | unsigned char byte = c; 10 | 11 | return stream->write(stream, &byte, 1) == 1 ? byte : EOF; 12 | } 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/stdio/putchar.c: -------------------------------------------------------------------------------- 1 | #include "putc.h" 2 | #include 3 | 4 | int putchar(int c) 5 | { 6 | return putc_(stdout, c); 7 | } 8 | -------------------------------------------------------------------------------- /src/stdio/puts.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | size_t __stdio_write(const void*, size_t, FILE*); 5 | 6 | int puts(const char s[static 1]) 7 | { 8 | __stdio_write(s, strlen(s), stdout); 9 | 10 | return putchar('\n'); 11 | } 12 | -------------------------------------------------------------------------------- /src/stdio/remove.c: -------------------------------------------------------------------------------- 1 | #include "../sys/syscall.h" 2 | #include 3 | 4 | int __unlink(const char[static 1]); 5 | int __rmdir(const char[static 1]); 6 | 7 | int remove(const char path[static 1]) 8 | { 9 | int result = __unlink(path); 10 | 11 | if (result == -EISDIR) 12 | result = __rmdir(path); 13 | 14 | return syscall_(result); 15 | } 16 | -------------------------------------------------------------------------------- /src/stdio/rename.c: -------------------------------------------------------------------------------- 1 | #include "../sys/syscall.h" 2 | 3 | int __rename(const char[static 1], const char[static 1]); 4 | 5 | int rename(const char from[static 1], const char to[static 1]) 6 | { 7 | return syscall_(__rename(from, to)); 8 | } 9 | 10 | -------------------------------------------------------------------------------- /src/stdio/rewind.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | 4 | void rewind(FILE stream[static 1]) 5 | { 6 | fseek(stream, 0, SEEK_SET); 7 | stream->state &= ~errbit_; 8 | } 9 | -------------------------------------------------------------------------------- /src/stdio/stderr.c: -------------------------------------------------------------------------------- 1 | #include "FILE_.h" 2 | FILE __stderr = FILE_(2); 3 | -------------------------------------------------------------------------------- /src/stdio/stdin.c: -------------------------------------------------------------------------------- 1 | #include "FILE_.h" 2 | FILE __stdin = FILE_(0); 3 | -------------------------------------------------------------------------------- /src/stdio/stdout.c: -------------------------------------------------------------------------------- 1 | #include "FILE_.h" 2 | FILE __stdout = FILE_(1); 3 | -------------------------------------------------------------------------------- /src/stdio/ungetc.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | 4 | int ungetc(int c, FILE stream[static 1]) 5 | { 6 | if (stream->avail < sizeof(stream->cache) && c != EOF) { 7 | ++stream->avail; 8 | stream->cache[sizeof(stream->cache) - stream->avail] = c; 9 | stream->state &= ~eofbit_; 10 | return c; 11 | } 12 | 13 | return EOF; 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/stdio/vprintf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int vprintf(const char format[restrict static 1], va_list list) 5 | { 6 | return vfprintf(stdout, format, list); 7 | } 8 | -------------------------------------------------------------------------------- /src/stdio/vsprintf.c: -------------------------------------------------------------------------------- 1 | #include "FILE.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static size_t write_(FILE stream[restrict static 1], const void* restrict buffer, size_t size) 7 | { 8 | memcpy(stream->ptr, buffer, size); 9 | stream->ptr += size; 10 | return size; 11 | } 12 | 13 | int vsprintf(char s[restrict static 1], const char format[restrict static 1], va_list list) 14 | { 15 | FILE stream = { 16 | .ptr = (unsigned char*)s, 17 | .write = write_, 18 | }; 19 | 20 | int status = vfprintf(&stream, format, list); 21 | *stream.ptr = '\0'; 22 | return status; 23 | } 24 | -------------------------------------------------------------------------------- /src/stdlib/abs.c: -------------------------------------------------------------------------------- 1 | typedef int Integer; 2 | #define PREFIX 3 | #include "abs.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/abs.h: -------------------------------------------------------------------------------- 1 | #define CAT2(a, b) a##b 2 | #define CAT(a, b) CAT2(a, b) 3 | 4 | Integer CAT(PREFIX, abs)(Integer a) 5 | { 6 | return a < 0 ? -a : a ? a : 0; 7 | } 8 | -------------------------------------------------------------------------------- /src/stdlib/atoi.c: -------------------------------------------------------------------------------- 1 | typedef int Integer; 2 | #define ATOI atoi 3 | #include "atoi.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/atoi.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | Integer ATOI(const char s[static 1]) 4 | { 5 | Integer magnitude = 0; 6 | Integer sign = 1; 7 | 8 | while (isspace(*s)) 9 | ++s; 10 | 11 | switch (*s) { 12 | case '-': 13 | sign = -1; 14 | /* fallthrough */ 15 | case '+': 16 | ++s; 17 | } 18 | 19 | for (unsigned digit = *s - '0'; digit < 10; digit = *s - '0') { 20 | magnitude = 10 * magnitude + digit; 21 | ++s; 22 | } 23 | 24 | return sign * magnitude; 25 | } 26 | -------------------------------------------------------------------------------- /src/stdlib/atol.c: -------------------------------------------------------------------------------- 1 | typedef long Integer; 2 | #define ATOI atol 3 | #include "atoi.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/atoll.c: -------------------------------------------------------------------------------- 1 | typedef long long Integer; 2 | #define ATOI atoll 3 | #include "atoi.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/bsearch.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void* bsearch(const void* key, const void* begin, size_t count, size_t size, int compare(const void*, const void*)) 4 | { 5 | if (!count) 6 | return (void*)0; 7 | 8 | size_t half = count >> 1; 9 | const void* pivot = (const char*)begin + size * half; 10 | int comparison = compare(key, pivot); 11 | 12 | if (comparison < 0) 13 | return bsearch(key, begin, half, size, compare); 14 | 15 | if (comparison) 16 | return bsearch(key, pivot, count - half, size, compare); 17 | 18 | return (void*)pivot; 19 | } 20 | -------------------------------------------------------------------------------- /src/stdlib/div.c: -------------------------------------------------------------------------------- 1 | typedef int Integer; 2 | #define PREFIX 3 | #include "div.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/div.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define CAT2(a, b) a##b 4 | #define CAT(a, b) CAT2(a, b) 5 | 6 | typedef CAT(PREFIX, div_t) Result; 7 | 8 | Result CAT(PREFIX, div)(Integer numerator, Integer denominator) 9 | { 10 | Result result; 11 | 12 | result.quot = numerator / denominator; 13 | result.rem = numerator % denominator; 14 | 15 | return result; 16 | } 17 | -------------------------------------------------------------------------------- /src/stdlib/labs.c: -------------------------------------------------------------------------------- 1 | typedef long Integer; 2 | #define PREFIX l 3 | #include "abs.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/ldiv.c: -------------------------------------------------------------------------------- 1 | typedef long Integer; 2 | #define PREFIX l 3 | #include "div.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/llabs.c: -------------------------------------------------------------------------------- 1 | typedef long long Integer; 2 | #define PREFIX ll 3 | #include "abs.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/lldiv.c: -------------------------------------------------------------------------------- 1 | typedef long long Integer; 2 | #define PREFIX ll 3 | #include "div.h" 4 | -------------------------------------------------------------------------------- /src/stdlib/parse/digit.h: -------------------------------------------------------------------------------- 1 | static unsigned digit_(unsigned c) 2 | { 3 | if (c - '0' < 10) 4 | return c - '0'; 5 | 6 | c |= 32; 7 | 8 | if (c - 'a' < 26) 9 | return c - 'a' + 10; 10 | 11 | return -1; 12 | } 13 | -------------------------------------------------------------------------------- /src/stdlib/parse/scientificf.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static float scientific_(uint32_t significand, int exp) 4 | { 5 | return significand * __builtin_powi(10, exp); 6 | } 7 | -------------------------------------------------------------------------------- /src/stdlib/rand.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static uint_fast32_t state = 1; 4 | 5 | void srand(unsigned seed) 6 | { 7 | state = seed; 8 | } 9 | 10 | int rand(void) 11 | { 12 | return state = state * 48271 % 2147483647; 13 | } 14 | 15 | int random(void) __attribute__((alias("rand"))); 16 | -------------------------------------------------------------------------------- /src/stdlib/strtod.c: -------------------------------------------------------------------------------- 1 | #include "parse/scientific.h" 2 | #include 3 | 4 | typedef double Scalar; 5 | typedef uint64_t Bitset; 6 | 7 | #include "parse/float.h" 8 | 9 | double strtod(const char s[restrict static 1], char** restrict end) 10 | { 11 | return parsefloat_(s, end); 12 | } 13 | -------------------------------------------------------------------------------- /src/stdlib/strtof.c: -------------------------------------------------------------------------------- 1 | #include "parse/scientificf.h" 2 | #include 3 | 4 | typedef float Scalar; 5 | typedef uint32_t Bitset; 6 | 7 | #include "parse/float.h" 8 | 9 | float strtof(const char s[restrict static 1], char** restrict end) 10 | { 11 | return parsefloat_(s, end); 12 | } 13 | -------------------------------------------------------------------------------- /src/stdlib/strtol.c: -------------------------------------------------------------------------------- 1 | typedef long Integer; 2 | typedef unsigned long Unsigned; 3 | 4 | #include "parse/integer.h" 5 | #include 6 | 7 | long strtol(const char s[restrict static 1], char** restrict end, int base) 8 | { 9 | return parseint_(s, end, base, LONG_MAX); 10 | } 11 | -------------------------------------------------------------------------------- /src/stdlib/strtoll.c: -------------------------------------------------------------------------------- 1 | typedef long long Integer; 2 | typedef unsigned long long Unsigned; 3 | 4 | #include "parse/integer.h" 5 | #include 6 | 7 | long long strtoll(const char s[restrict static 1], char** restrict end, int base) 8 | { 9 | return parseint_(s, end, base, LLONG_MAX); 10 | } 11 | -------------------------------------------------------------------------------- /src/stdlib/strtoul.c: -------------------------------------------------------------------------------- 1 | typedef unsigned long Integer; 2 | typedef unsigned long Unsigned; 3 | 4 | #include "parse/integer.h" 5 | 6 | unsigned long strtoul(const char s[restrict static 1], char** restrict end, int base) 7 | { 8 | return parseint_(s, end, base, -1); 9 | } 10 | -------------------------------------------------------------------------------- /src/stdlib/strtoull.c: -------------------------------------------------------------------------------- 1 | typedef unsigned long long Integer; 2 | typedef unsigned long long Unsigned; 3 | 4 | #include "parse/integer.h" 5 | 6 | unsigned long long strtoull(const char s[restrict static 1], char** restrict end, int base) 7 | { 8 | return parseint_(s, end, base, -1); 9 | } 10 | -------------------------------------------------------------------------------- /src/stdlib/system.c: -------------------------------------------------------------------------------- 1 | 2 | /* This function shall always fail because there is no shell. 3 | * Queried with NULL, this function returns 0. 4 | * With a command, this function returns EXIT_FAILURE. 5 | */ 6 | int system(const char* command) { return !!command; } 7 | -------------------------------------------------------------------------------- /src/string/aliased.h: -------------------------------------------------------------------------------- 1 | #ifdef __GNUC__ 2 | #define ALIASED __attribute__((__may_alias__)) 3 | #else 4 | #define ALIASED 5 | #endif 6 | -------------------------------------------------------------------------------- /src/string/memcmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int memcmp(const void* lhs, const void* rhs, size_t length) 4 | { 5 | const unsigned char* x = lhs; 6 | const unsigned char* y = rhs; 7 | 8 | while (length--) { 9 | unsigned char a = *x++; 10 | unsigned char b = *y++; 11 | 12 | if (a != b) 13 | return a - b; 14 | } 15 | 16 | return 0; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/string/memcpy.c: -------------------------------------------------------------------------------- 1 | #include "copy.h" 2 | #include 3 | #include 4 | 5 | void* memcpy(void* restrict destination, const void* restrict source, size_t length) 6 | { 7 | return copy_(destination, source, length); 8 | } 9 | -------------------------------------------------------------------------------- /src/string/memset.c: -------------------------------------------------------------------------------- 1 | #include "aliased.h" 2 | #include 3 | #include 4 | 5 | void* memset(void* destination, int character, size_t length) 6 | { 7 | unsigned char* output = destination; 8 | unsigned char c = character; 9 | uint64_t vector = 0x0101010101010101u * c; 10 | 11 | while ((uintptr_t)output % sizeof(uint64_t) && length--) 12 | *output++ = c; 13 | 14 | uint64_t ALIASED* alias = (uint64_t*)output; 15 | 16 | for (; length >= sizeof(uint64_t); length -= sizeof(uint64_t)) 17 | *alias++ = vector; 18 | 19 | output = (unsigned char*)alias; 20 | 21 | while (length--) 22 | *output++ = c; 23 | 24 | return destination; 25 | } 26 | -------------------------------------------------------------------------------- /src/string/strcat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* strcat(char destination[static restrict 1], const char source[static restrict 1]) 4 | { 5 | strcpy(destination + strlen(destination), source); 6 | 7 | return destination; 8 | } 9 | -------------------------------------------------------------------------------- /src/string/strcmp.c: -------------------------------------------------------------------------------- 1 | int strcmp(const char lhs[static 1], const char rhs[static 1]) 2 | { 3 | const unsigned char* x = (const unsigned char*)lhs; 4 | const unsigned char* y = (const unsigned char*)rhs; 5 | 6 | while (*x == *y && *x) { 7 | ++x; 8 | ++y; 9 | } 10 | 11 | return *x - *y; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /src/string/strcpy.c: -------------------------------------------------------------------------------- 1 | char* strcpy(char destination[static restrict 1], const char source[static restrict 1]) 2 | { 3 | char* output = destination; 4 | 5 | while ((*output++ = *source++)); 6 | 7 | return destination; 8 | } 9 | -------------------------------------------------------------------------------- /src/string/strcspn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | size_t strcspn(const char string[static 1], const char reject[static 1]) 4 | { 5 | size_t count = 0; 6 | 7 | while (!strchr(reject, string[count])) 8 | ++count; 9 | 10 | return count; 11 | } 12 | -------------------------------------------------------------------------------- /src/string/strlen.c: -------------------------------------------------------------------------------- 1 | #include "aliased.h" 2 | #include 3 | #include 4 | 5 | size_t strlen(const char begin[static 1]) 6 | { 7 | const char* end = begin; 8 | 9 | for (; (uintptr_t)end % sizeof(uint64_t); ++end) 10 | if (!*end) 11 | return end - begin; 12 | 13 | const uint64_t magic = 0x7EFEFEFEFEFEFEFF; 14 | 15 | for (const uint64_t ALIASED* vector = (const uint64_t*)end; ; end = (const char*)++vector) { 16 | if (((*vector + magic) ^ ~*vector) & ~magic) 17 | for (int k = 0; k < sizeof(uint64_t); ++k) 18 | if (!end[k]) 19 | return end - begin + k; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/string/strncat.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* strncat(char destination[static restrict 1], const char source[static restrict 1], size_t length) 4 | { 5 | char* output = destination + strlen(destination); 6 | 7 | while (length-- && (*output++ = *source++)); 8 | 9 | return destination; 10 | } 11 | -------------------------------------------------------------------------------- /src/string/strncmp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int strncmp(const char lhs[static 1], const char rhs[static 1], size_t length) 4 | { 5 | const unsigned char* x = (const unsigned char*)lhs; 6 | const unsigned char* y = (const unsigned char*)rhs; 7 | 8 | while (length--) { 9 | unsigned char a = *x++; 10 | unsigned char b = *y++; 11 | 12 | if (a != b || !a) 13 | return a - b; 14 | } 15 | 16 | return 0; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /src/string/strncpy.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* strncpy(char destination[static restrict 1], const char source[static restrict 1], size_t length) 4 | { 5 | char* output = destination; 6 | 7 | for (; length && *source; --length) 8 | *output++ = *source++; 9 | 10 | if (length) // clang is happier with this 11 | memset(output, 0, length); 12 | 13 | return destination; 14 | } 15 | -------------------------------------------------------------------------------- /src/string/strpbrk.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* strpbrk(const char string[static 1], const char set[static 1]) 4 | { 5 | while (!strchr(set, *string)) 6 | ++string; 7 | 8 | return *string ? (char*)string : 0; 9 | } 10 | -------------------------------------------------------------------------------- /src/string/strrchr.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* strrchr(const char source[static 1], int character) 4 | { 5 | unsigned char c = character; 6 | 7 | if (!c) 8 | return (char*)(source + strlen(source)); 9 | 10 | char* found = 0; 11 | char* candidate; 12 | 13 | while ((candidate = strchr(source, character))) { 14 | found = candidate; 15 | source = candidate + 1; 16 | } 17 | 18 | return found; 19 | } 20 | -------------------------------------------------------------------------------- /src/string/strspn.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static const char* find_(const char source[static 1], char character) 4 | { 5 | for (; *source; ++source) 6 | if (*source == character) 7 | return source; 8 | 9 | return 0; 10 | } 11 | 12 | size_t strspn(const char string[static 1], const char accept[static 1]) 13 | { 14 | size_t count = 0; 15 | 16 | while (find_(accept, string[count])) 17 | ++count; 18 | 19 | return count; 20 | } 21 | -------------------------------------------------------------------------------- /src/string/strtok.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | char* strtok_r(char* restrict string, const char* restrict separators, char* state[static restrict 1]) 4 | { 5 | if (!(string || (string = *state))) 6 | return 0; 7 | 8 | string += strspn(string, separators); 9 | 10 | if (!*string) 11 | return *state = 0; 12 | 13 | *state = strpbrk(string, separators); 14 | 15 | if (*state) 16 | *(*state)++ = '\0'; 17 | 18 | return string; 19 | } 20 | 21 | char* strtok(char* restrict string, const char* restrict separators) 22 | { 23 | static char* state; 24 | 25 | return strtok_r(string, separators, &state); 26 | } 27 | -------------------------------------------------------------------------------- /src/sys/stat/fstat.c: -------------------------------------------------------------------------------- 1 | #include "../syscall.h" 2 | #include 3 | 4 | int __fstat(int, struct stat[static 1]); 5 | 6 | int fstat(int fd, struct stat result[static 1]) 7 | { 8 | return syscall_(__fstat(fd, result)); 9 | } 10 | -------------------------------------------------------------------------------- /src/sys/stat/lstat.c: -------------------------------------------------------------------------------- 1 | #include "../syscall.h" 2 | #include 3 | 4 | int __lstat(const char[restrict static 1], struct stat[restrict static 1]); 5 | 6 | int lstat(const char path[restrict static 1], struct stat result[restrict static 1]) 7 | { 8 | return syscall_(__lstat(path, result)); 9 | } 10 | -------------------------------------------------------------------------------- /src/sys/stat/stat.c: -------------------------------------------------------------------------------- 1 | #include "../syscall.h" 2 | #include 3 | 4 | int __stat(const char[restrict static 1], struct stat[restrict static 1]); 5 | 6 | int stat(const char path[restrict static 1], struct stat result[restrict static 1]) 7 | { 8 | return syscall_(__stat(path, result)); 9 | } 10 | -------------------------------------------------------------------------------- /src/sys/syscall.h: -------------------------------------------------------------------------------- 1 | #ifndef METALLIC_SYSCALL_H 2 | #define METALLIC_SYSCALL_H 3 | 4 | extern _Thread_local int errno; 5 | 6 | static long syscall_(long status) 7 | { 8 | if (status >= 0) 9 | return status; 10 | 11 | errno = -status; 12 | return -1; 13 | } 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/time/time.c: -------------------------------------------------------------------------------- 1 | #if _POSIX_C_SOURCE < 199309L 2 | #define _POSIX_C_SOURCE 199309L 3 | #endif 4 | 5 | #include 6 | 7 | extern _Thread_local int errno; 8 | 9 | int __clock_gettime(clockid_t, struct timespec*); 10 | 11 | time_t time(time_t* t) 12 | { 13 | struct timespec spec; 14 | int code = __clock_gettime(CLOCK_REALTIME, &spec); 15 | 16 | if (code < 0) { 17 | errno = -code; 18 | return -1; 19 | } 20 | 21 | if (t) 22 | *t = spec.tv_sec; 23 | 24 | return spec.tv_sec; 25 | } 26 | -------------------------------------------------------------------------------- /src/time/timespec_get.c: -------------------------------------------------------------------------------- 1 | #if _POSIX_C_SOURCE < 199309L 2 | #define _POSIX_C_SOURCE 199309L 3 | #endif 4 | 5 | #include 6 | 7 | int __clock_gettime(clockid_t, struct timespec*); 8 | 9 | int timespec_get(struct timespec* spec, int base) 10 | { 11 | return base * (base == TIME_UTC && __clock_gettime(CLOCK_REALTIME, spec) >= 0); 12 | } 13 | -------------------------------------------------------------------------------- /src/unistd/sbrk.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | uintptr_t __metallic_brk; 4 | 5 | void* __sbrk(intptr_t increment) 6 | { 7 | const uintptr_t pagesize = 64 * 1024; 8 | uintptr_t previous = __metallic_brk; 9 | uintptr_t capacity = pagesize * __builtin_wasm_memory_size(0); 10 | 11 | if (__metallic_brk + increment > capacity) { 12 | uintptr_t excess = __metallic_brk + increment - capacity; 13 | uintptr_t pages = (pagesize - 1 + excess) / pagesize; 14 | 15 | if (__builtin_wasm_memory_grow(0, pages) == -1) 16 | return (void*)-1; 17 | } 18 | __metallic_brk += increment; 19 | return (void*)previous; 20 | } 21 | -------------------------------------------------------------------------------- /test/native/assertf.h: -------------------------------------------------------------------------------- 1 | _Noreturn void abort(void); 2 | 3 | #define STRINGIFY0(x) #x 4 | #define STRINGIFY(x) STRINGIFY0(x) 5 | 6 | #define ASSERTF(cond, ...) do if (!(cond)) { \ 7 | fputs(__FILE__":"STRINGIFY(__LINE__)": ", stderr); \ 8 | fputs(__func__, stderr); \ 9 | fputs(": Assertion `"#cond"' failed: ", stderr); \ 10 | fprintf(stderr, __VA_ARGS__); \ 11 | abort(); \ 12 | } while (0) 13 | -------------------------------------------------------------------------------- /test/native/math/double/binary.h: -------------------------------------------------------------------------------- 1 | #include "unary.h" 2 | 3 | #define verify2(cond, x, y) ASSERTF(cond, "at (%a, %a)\n", (double)(x), (double)(y)) 4 | 5 | static inline void mirror(void f(double, double), double x, double y) 6 | { 7 | f(x, y); 8 | f(-x, y); 9 | } 10 | 11 | static inline void quadrants(void f(double, double), double x, double y) 12 | { 13 | f(x, y); 14 | f(-x, y); 15 | f(-x, -y); 16 | f(x, -y); 17 | } 18 | -------------------------------------------------------------------------------- /test/native/math/double/cbrt.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/cbrt.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | const uint64_t step = 0x000000157783F669; 8 | 9 | assert(cbrt(INFINITY) == INFINITY); 10 | assert(cbrt(-INFINITY) == -INFINITY); 11 | 12 | for (uint64_t i = 0x0010000000000000; i < 0x7FF0000000000000; i += step) { 13 | double x = reinterpret(double, i); 14 | double y = cbrt(x); 15 | verify(approx(y, cbrtl(x), 1), x); 16 | verify(-y == cbrt(-x), x); 17 | } 18 | 19 | for (uint64_t i = 0x7FF8000000000000; i < 0x8000000000000000; i += step) { 20 | double x = reinterpret(double, i); 21 | verify(isnan(cbrt(x)), i); 22 | verify(isnan(cbrt(-x)), i); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/native/math/double/ceil.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/ceil.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | const uint64_t inf = 0x7FF0000000000000; 8 | const uint64_t nan = 0x7FF8000000000000; 9 | const uint64_t sign = 0x8000000000000000; 10 | const uint64_t step = 0x00000005039A1D31; 11 | 12 | for (uint64_t i = 0; i < inf; i += step) { 13 | double x = reinterpret(double, i); 14 | verify(identical(ceil(x), ceil_(x)), x); 15 | verify(identical(ceil(-x), ceil_(-x)), x); 16 | } 17 | 18 | for (uint64_t i = nan; i < sign; i += step) { 19 | double x = reinterpret(double, i); 20 | verify(isnan(ceil_(x)), x); 21 | verify(isnan(ceil_(-x)), x); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/native/math/double/cos.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/cos.c" 2 | #include "src/math/double/rem_pio2.c" 3 | #include "unary.h" 4 | 5 | int main(void) 6 | { 7 | const uint64_t n0 = 0x8000000000000000; 8 | const uint64_t inf = 0x7FF0000000000000; 9 | const uint64_t nan = 0x7FF8000000000000; 10 | const uint64_t step = 0x000000244E2B736F; 11 | 12 | for (uint64_t i = 0; i < inf; i += step) { 13 | double x = reinterpret(double, i); 14 | double y = cos(x); 15 | verify(approx(y, cosl(x), 1), x); 16 | verify(identical(y, cos(-x)), x); 17 | } 18 | 19 | for (uint64_t i = nan; i < n0; i += step) { 20 | double x = reinterpret(double, i); 21 | verify(isnan(cos(x)), x); 22 | verify(isnan(cos(-x)), x); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/native/math/double/cosh.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/cosh.c" 2 | #include "unary.h" 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | const uint64_t step = 0x000000292482AD39; 9 | 10 | assert(cosh(INFINITY) == INFINITY); 11 | assert(cosh(-INFINITY) == INFINITY); 12 | 13 | for (uint64_t i = 0; i < 0x7FF0000000000000; i += step) { 14 | double x = reinterpret(double, i); 15 | double y = cosh(x); 16 | verify(approx(y, coshl(x), 1), x); 17 | verify(y == cosh(-x), x); 18 | } 19 | 20 | for (uint64_t i = 0x7FF8000000000000; i < 0x8000000000000000; i += step) { 21 | double x = reinterpret(double, i); 22 | verify(isnan(cosh(x)), i); 23 | verify(isnan(cosh(-x)), i); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/native/math/double/erf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/erf.c" 2 | #include "unary.h" 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | const uint64_t step = 0x00000004F2931D55; 9 | 10 | assert(erf(HUGE_VAL) == 1); 11 | assert(erf(-HUGE_VAL) == -1); 12 | 13 | for (uint64_t i = 0; i < 0x7FF0000000000000; i += step) { 14 | double x = reinterpret(double, i); 15 | double y = erf(x); 16 | verify(approx(y, erfl(x), 1), x); 17 | verify(identical(-y, erf(-x)), x); 18 | } 19 | 20 | for (uint64_t i = 0x7FF8000000000000; i < 0x8000000000000000; i += step) { 21 | double x = reinterpret(double, i); 22 | verify(isnan(erf(x)), x); 23 | verify(isnan(erf(-x)), x); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/native/math/double/erfc.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/erfc.c" 2 | #include "unary.h" 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | const uint64_t step = 0x00000000F2931D55; 9 | 10 | for (uint64_t i = 0; i < 0x3FEB000000000000; i += step) { 11 | double x = reinterpret(double, i); 12 | verify(approx(small_(x), erfcl(x), 1), x); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/native/math/double/floor.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/floor.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | const uint64_t inf = 0x7FF0000000000000; 8 | const uint64_t nan = 0x7FF8000000000000; 9 | const uint64_t sign = 0x8000000000000000; 10 | const uint64_t step = 0x00000005039A1D31; 11 | 12 | for (uint64_t i = 0; i < inf; i += step) { 13 | double x = reinterpret(double, i); 14 | verify(identical(floor(x), floor_(x)), x); 15 | verify(identical(floor(-x), floor_(-x)), x); 16 | } 17 | 18 | for (uint64_t i = nan; i < sign; i += step) { 19 | double x = reinterpret(double, i); 20 | verify(isnan(floor_(x)), x); 21 | verify(isnan(floor_(-x)), x); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/native/math/double/log.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/log.c" 2 | #include "log.h" 3 | 4 | int main(void) 5 | { 6 | test(log, logl); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/double/log10.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/log10.c" 2 | #include "log.h" 3 | 4 | int main(void) 5 | { 6 | test(log10, log10l); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/double/log2.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/log2.c" 2 | #include "log.h" 3 | 4 | int main(void) 5 | { 6 | test(log2, log2l); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/double/rint.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/rint.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int64_t i = 0; i <= 0x7FF0000000000000; i += 0x000000034E3F771F) { 8 | double x = reinterpret(double, i); 9 | verify(identical(rint(x), rint_(x)), x); 10 | verify(identical(rint(-x), rint_(-x)), x); 11 | } 12 | 13 | for (uint64_t i = 0x7FF8000000000000; i < 0x8000000000000000; i += 0x000000039C2344F9) { 14 | double x = reinterpret(double, i); 15 | assert(isnan(rint_(x))); 16 | assert(isnan(rint_(-x))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/double/sin.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/sin.c" 2 | #include "src/math/double/rem_pio2.c" 3 | #include "unary.h" 4 | 5 | int main(void) 6 | { 7 | const uint64_t n0 = 0x8000000000000000; 8 | const uint64_t inf = 0x7FF0000000000000; 9 | const uint64_t nan = 0x7FF8000000000000; 10 | const uint64_t step = 0x000000244E2B736F; 11 | 12 | for (uint64_t i = 0; i < inf; i += step) { 13 | double x = reinterpret(double, i); 14 | double y = sin(x); 15 | verify(approx(y, sinl(x), 1), x); 16 | verify(identical(-y, sin(-x)), x); 17 | } 18 | 19 | for (uint64_t i = nan; i < n0; i += step) { 20 | double x = reinterpret(double, i); 21 | verify(isnan(sin(x)), x); 22 | verify(isnan(sin(-x)), x); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/native/math/double/sinh.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/sinh.c" 2 | #include "unary.h" 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | const uint64_t step = 0x000000292482AD39; 9 | 10 | assert(sinh(INFINITY) == INFINITY); 11 | assert(sinh(-INFINITY) == -INFINITY); 12 | 13 | for (uint64_t i = 0; i < 0x7FF0000000000000; i += step) { 14 | double x = reinterpret(double, i); 15 | double y = sinh(x); 16 | verify(approx(y, sinhl(x), 1), x); 17 | verify(identical(-y, sinh(-x)), x); 18 | } 19 | 20 | for (uint64_t i = 0x7FF8000000000000; i < 0x8000000000000000; i += step) { 21 | double x = reinterpret(double, i); 22 | verify(isnan(sinh(x)), i); 23 | verify(isnan(sinh(-x)), i); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/native/math/double/tan.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/tan.c" 2 | #include "src/math/double/rem_pio2.c" 3 | #include "unary.h" 4 | 5 | int main(void) 6 | { 7 | const uint64_t n0 = 0x8000000000000000; 8 | const uint64_t inf = 0x7FF0000000000000; 9 | const uint64_t nan = 0x7FF8000000000000; 10 | const uint64_t step = 0x000000244E2B736F; 11 | 12 | for (uint64_t i = 0; i < inf; i += step) { 13 | double x = reinterpret(double, i); 14 | double y = tan(x); 15 | verify(approx(y, tanl(x), 3), x); 16 | verify(identical(-y, tan(-x)), x); 17 | } 18 | 19 | for (uint64_t i = nan; i < n0; i += step) { 20 | double x = reinterpret(double, i); 21 | verify(isnan(tan(x)), x); 22 | verify(isnan(tan(-x)), x); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/native/math/double/tanh.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/tanh.c" 2 | #include "unary.h" 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | const uint64_t step = 0x000000292482AD39; 9 | 10 | assert(tanh(HUGE_VAL) == 1); 11 | assert(tanh(-HUGE_VAL) == -1); 12 | 13 | for (uint64_t i = 0; i < 0x7FF0000000000000; i += step) { 14 | double x = reinterpret(double, i); 15 | double y = tanh(x); 16 | verify(approx(y, tanhl(x), 1), x); 17 | verify(identical(-y, tanh(-x)), x); 18 | } 19 | 20 | for (uint64_t i = 0x7FF8000000000000; i < 0x8000000000000000; i += step) { 21 | double x = reinterpret(double, i); 22 | verify(isnan(tanh(x)), i); 23 | verify(isnan(tanh(-x)), i); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /test/native/math/double/trunc.c: -------------------------------------------------------------------------------- 1 | #include "src/math/double/trunc.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | const uint64_t inf = 0x7FF0000000000000; 8 | const uint64_t nan = 0x7FF8000000000000; 9 | const uint64_t sign = 0x8000000000000000; 10 | const uint64_t step = 0x00000005039A1D31; 11 | 12 | for (uint64_t i = 0; i < inf; i += step) { 13 | double x = reinterpret(double, i); 14 | verify(identical(trunc(x), trunc_(x)), x); 15 | verify(identical(trunc(-x), trunc_(-x)), x); 16 | } 17 | 18 | for (uint64_t i = nan; i < sign; i += step) { 19 | double x = reinterpret(double, i); 20 | verify(isnan(trunc_(x)), x); 21 | verify(isnan(trunc_(-x)), x); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /test/native/math/double/unary.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include "assertf.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define verify(cond, x) ASSERTF(cond, "at %a\n", (double)(x)) 10 | 11 | static inline _Bool identical(double x, double y) 12 | { 13 | return reinterpret(uint64_t, x) == reinterpret(uint64_t, y); 14 | } 15 | 16 | static inline _Bool approx(long double x, long double y, long double tolerance) 17 | { 18 | return identical(x, y) || fabsl(y - x) < tolerance * fabs(nexttoward(x, y) - (double)x); 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/acosf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/acosf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | assert(acosf(0) * 2 == acosf(-1)); 8 | assert(acosf(0.5) == (float)acos(0.5)); 9 | 10 | for (int32_t i = 0; i < 0x3F800000; i += 81) { 11 | float x = reinterpret(float, i); 12 | verify(approx(acosf(x), acos(x), 1), x); 13 | verify(approx(acosf(-x), acos(-x), 1), x); 14 | } 15 | 16 | for (uint32_t i = 0x3F800100; i < 0x80000000; i += 0x100) { 17 | float x = reinterpret(float, i); 18 | assert(isnan(acosf(x))); 19 | assert(isnan(acosf(-x))); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/native/math/float/acoshf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/acoshf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0x3F800000; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | verify(approx(acoshf(x), acosh(x), 1), x); 10 | } 11 | 12 | for (uint32_t i = 0; i < 0x3F800000; i += 193) { 13 | float x = reinterpret(float, i); 14 | verify(isnan(acoshf(x)), x); 15 | } 16 | 17 | for (uint32_t i = 0x7FC00000; i; i += 256) { 18 | float x = reinterpret(float, i); 19 | verify(isnan(acoshf(x)), x); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/native/math/float/asinf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/asinf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x3F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | float y = asinf(x); 10 | verify(approx(y, asin(x), 1), x); 11 | verify(identical(-y, asinf(-x)), x); 12 | } 13 | 14 | for (uint32_t i = 0x3F800100; i < 0x80000000; i += 256) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(asinf(x))); 17 | assert(isnan(asinf(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/asinhf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/asinhf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | float y = asinhf(x); 10 | verify(approx(y, asinh(x), 1), x); 11 | verify(identical(-y, asinhf(-x)), x); 12 | } 13 | 14 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(asinhf(x))); 17 | assert(isnan(asinhf(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/atanf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/atanf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | double y = atan(x); 10 | verify(approx(atanf(x), y, 1), x); 11 | verify(approx(atanf(-x), -y, 1), x); 12 | } 13 | 14 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(atanf(x))); 17 | assert(isnan(atanf(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/atanhf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/atanhf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x3F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | double y = atanhf(x); 10 | verify(approx(y, atanh(x), 1), x); 11 | verify(identical(-y, atanhf(-x)), x); 12 | } 13 | 14 | for (uint32_t i = 0x3F800100; i < 0x80000000; i += 256) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(atanhf(x))); 17 | assert(isnan(atanhf(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/binary.h: -------------------------------------------------------------------------------- 1 | #include "unary.h" 2 | 3 | #define verify2(cond, x, y) ASSERTF(cond, "at (%a, %a)\n", (double)(x), (double)(y)) 4 | 5 | static inline void mirror(void f(float, float), float x, float y) 6 | { 7 | f(x, y); 8 | f(-x, y); 9 | } 10 | 11 | static inline void quadrants(void f(float, float), float x, float y) 12 | { 13 | f(x, y); 14 | f(-x, y); 15 | f(-x, -y); 16 | f(x, -y); 17 | } 18 | -------------------------------------------------------------------------------- /test/native/math/float/cbrtf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/cbrtf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (uint32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | float y = cbrtf(x); 10 | verify(approx(y, cbrt(x), 1), x); 11 | verify(identical(-y, cbrtf(-x)), x); 12 | } 13 | 14 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(cbrtf(x))); 17 | assert(isnan(cbrtf(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/ceilf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/ceilf.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | verify(identical(ceilf(x), ceilf_(x)), x); 10 | verify(identical(ceilf(-x), ceilf_(-x)), x); 11 | } 12 | 13 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 14 | float x = reinterpret(float, i); 15 | assert(isnan(ceilf_(x))); 16 | assert(isnan(ceilf_(-x))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/float/complex.h: -------------------------------------------------------------------------------- 1 | #include "binary.h" 2 | 3 | double cimag(double _Complex); 4 | 5 | static inline _Bool cidentical(float _Complex x, float _Complex y) 6 | { 7 | return reinterpret(uint64_t, x) == reinterpret(uint64_t, y); 8 | } 9 | 10 | static inline _Bool capprox(double _Complex x, double _Complex y, double re, double im) 11 | { 12 | return approx(x, y, re) && approx(cimag(x), cimag(y), im); 13 | } 14 | -------------------------------------------------------------------------------- /test/native/math/float/cosf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/cosf.c" 2 | #include "src/math/float/rem_pio2f.c" 3 | #include "unary.h" 4 | #include 5 | 6 | int main(void) 7 | { 8 | for (int32_t i = 0; i < 0x7F800000; i += 81) { 9 | float x = reinterpret(float, i); 10 | verify(approx(cosf(x), cos(x), 1), x); 11 | } 12 | 13 | for (uint32_t i = 0x7F800000; i < 0x80000000; i += 81) { 14 | float x = reinterpret(float, i); 15 | assert(isnan(cosf(x))); 16 | assert(isnan(cosf(-x))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/float/erfcf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/erfcf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | assert(erfcf(INFINITY) == 0); 8 | assert(erfcf(-INFINITY) == 2); 9 | 10 | for (uint32_t i = 0; i < 0x7F800000; i += 111) { 11 | float x = reinterpret(float, i); 12 | verify(approx(erfcf(x), erfc(x), 1), x); 13 | verify(approx(erfcf(-x), erfc(-x), 1), x); 14 | } 15 | 16 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 17 | float x = reinterpret(float, i); 18 | assert(isnan(erfcf(x))); 19 | assert(isnan(erfcf(-x))); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/native/math/float/erff.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/erff.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (uint32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | float y = erff(x); 10 | verify(approx(y, erf(x), 1), x); 11 | verify(identical(-y, erff(-x)), x); 12 | } 13 | 14 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(erff(x))); 17 | assert(isnan(erff(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/exp2f.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/exp2f.c" 2 | #include "exp.h" 3 | 4 | int main(void) 5 | { 6 | test(exp2f, exp2, -126, 128); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/float/expf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/expf.c" 2 | #include "exp.h" 3 | 4 | int main(void) 5 | { 6 | test(expf, exp, log(0x1p-126), log(0x1p+128)); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/float/floorf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/floorf.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | verify(identical(floorf(x), floorf_(x)), x); 10 | verify(identical(floorf(-x), floorf_(-x)), x); 11 | } 12 | 13 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 14 | float x = reinterpret(float, i); 15 | assert(isnan(floorf_(x))); 16 | assert(isnan(floorf_(-x))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/float/lgammaf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/lgammaf.c" 2 | #include "unary.h" 3 | 4 | int main(void) 5 | { 6 | for (uint32_t i = 0; i <= 0x7F800000; i += 128) { 7 | float x = reinterpret(float, i); 8 | verify(approx(lgammaf(x), lgamma(x), 1), x); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /test/native/math/float/log.h: -------------------------------------------------------------------------------- 1 | #include "unary.h" 2 | 3 | static void test(float f(float), double g(double)) 4 | { 5 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 6 | float x = reinterpret(float, i); 7 | verify(approx(f(x), g(x), 1), x); 8 | } 9 | 10 | for (uint32_t i = 0x7FC00000; i <= 0x7FFFFFFF; i += 81) { 11 | float x = reinterpret(float, i); 12 | verify(isnan(f(x)), x); 13 | verify(isnan(f(-x)), x); 14 | } 15 | 16 | for (uint32_t i = 0x80000100; i; i += 256) { 17 | float x = reinterpret(float, i); 18 | verify(isnan(f(x)), x); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/native/math/float/log10f.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/log10f.c" 2 | #include "log.h" 3 | 4 | int main(void) 5 | { 6 | test(log10f, log10); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/float/log2f.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/log2f.c" 2 | #include "log.h" 3 | 4 | int main(void) 5 | { 6 | test(log2f, log2); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/float/logf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/logf.c" 2 | #include "log.h" 3 | 4 | int main(void) 5 | { 6 | test(logf, log); 7 | } 8 | -------------------------------------------------------------------------------- /test/native/math/float/rintf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/rintf.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | verify(identical(rintf(x), rintf_(x)), x); 10 | verify(identical(rintf(-x), rintf_(-x)), x); 11 | } 12 | 13 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 14 | float x = reinterpret(float, i); 15 | assert(isnan(rintf_(x))); 16 | assert(isnan(rintf_(-x))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/float/roundf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/roundf.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | float y = roundf(x); 10 | verify(identical(y, roundf_(x)), x); 11 | verify(identical(-y, roundf_(-x)), x); 12 | } 13 | 14 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(roundf_(x))); 17 | assert(isnan(roundf_(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/sinf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/sinf.c" 2 | #include "src/math/float/rem_pio2f.c" 3 | #include "unary.h" 4 | #include 5 | 6 | int main(void) 7 | { 8 | for (int32_t i = 0; i < 0x7F800000; i += 81) { 9 | float x = reinterpret(float, i); 10 | verify(approx(sinf(x), sin(x), 1), x); 11 | } 12 | 13 | for (uint32_t i = 0x7F800000; i < 0x80000000; i += 81) { 14 | float x = reinterpret(float, i); 15 | assert(isnan(sinf(x))); 16 | assert(isnan(sinf(-x))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/float/tanf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/tanf.c" 2 | #include "src/math/float/rem_pio2f.c" 3 | #include "unary.h" 4 | #include 5 | 6 | int main(void) 7 | { 8 | for (int32_t i = 0; i < 0x7F800000; i += 81) { 9 | float x = reinterpret(float, i); 10 | verify(approx(tanf(x), tan(x), 1), x); 11 | } 12 | 13 | for (uint32_t i = 0x7F800000; i < 0x80000000; i += 81) { 14 | float x = reinterpret(float, i); 15 | assert(isnan(tanf(x))); 16 | assert(isnan(tanf(-x))); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/float/tanhf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/tanhf.c" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (uint32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | float y = tanhf(x); 10 | verify(approx(y, tanh(x), 1), x); 11 | verify(identical(-y, tanhf(-x)), x); 12 | } 13 | 14 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 15 | float x = reinterpret(float, i); 16 | assert(isnan(tanhf(x))); 17 | assert(isnan(tanhf(-x))); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/native/math/float/tgammaf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/tgammaf.c" 2 | #include "unary.h" 3 | 4 | int main(void) 5 | { 6 | for (uint32_t i = 0x00000000; i <= 0x7F800000; i += 128) { 7 | float x = reinterpret(float, i); 8 | verify(approx(tgammaf(x), tgamma(x), 1), x); 9 | verify(approx(tgammaf(-x), tgamma(-x), 1), x); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/native/math/float/truncf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/float/truncf.h" 2 | #include "unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | for (int32_t i = 0; i <= 0x7F800000; i += 64) { 8 | float x = reinterpret(float, i); 9 | verify(identical(truncf(x), truncf_(x)), x); 10 | verify(identical(truncf(-x), truncf_(-x)), x); 11 | } 12 | 13 | for (uint32_t i = 0x7FC00000; i < 0x80000000; i += 81) { 14 | float x = reinterpret(float, i); 15 | verify(isnan(truncf_(x)), x); 16 | verify(isnan(truncf_(-x)), x); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /test/native/math/float/unary.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include "assertf.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define verify(cond, x) ASSERTF(cond, "at %a\n", (double)(x)) 10 | 11 | static inline _Bool identical(float x, float y) 12 | { 13 | return reinterpret(uint32_t, x) == reinterpret(uint32_t, y); 14 | } 15 | 16 | static inline _Bool approx(double x, double y, double tolerance) 17 | { 18 | return identical(x, y) || fabs(y - x) < tolerance * fabsf(nexttowardf(x, y) - (float)x); 19 | } 20 | -------------------------------------------------------------------------------- /test/native/soft/float/isnanl.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/float/isnanl.h" 2 | #include "src/math/reinterpret.h" 3 | #include "unary.h" 4 | #include 5 | 6 | int main(void) 7 | { 8 | for (long i = 0; i < 1L << 27; ++i) { 9 | unsigned __int128 a = (unsigned __int128)i << 101; 10 | __float128 x = reinterpret(__float128, a); 11 | verify(isnanl_(a) == (x != x), a); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/native/soft/float/unary.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include "assertf.h" 3 | #include 4 | #include 5 | #include 6 | 7 | #define verify(cond, a) ASSERTF(cond, \ 8 | "at 0x%.16"PRIx64"%.16"PRIx64"\n", \ 9 | (uint64_t)((unsigned __int128)(a) >> 64), \ 10 | (uint64_t)(unsigned __int128)(a)) 11 | 12 | static inline _Bool approx(unsigned __int128 a, unsigned __int128 b, unsigned __int128 tolerance) 13 | { 14 | return a - b + tolerance <= 2 * tolerance; 15 | } 16 | -------------------------------------------------------------------------------- /test/native/soft/integer/fixdfti.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/fixdfti.h" 2 | #include "math/double/unary.h" 3 | 4 | int main(void) 5 | { 6 | for (int64_t i = 0; i < 0x47F0000000000000; i += 0x000000034E3F771E) { 7 | double x = reinterpret(double, i); 8 | __int128 y = x; 9 | verify(fixdfti_(x) == y, x); 10 | verify(fixdfti_(-x) == -y, x); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/native/soft/integer/fixsfti.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/fixsfti.h" 2 | #include "math/float/unary.h" 3 | 4 | int main(void) 5 | { 6 | for (uint32_t i = 0; i < 0x7F800000; i += 71) { 7 | float x = reinterpret(float, i); 8 | __int128 y = x; 9 | verify(fixsfti_(x) == y, x); 10 | verify(fixsfti_(-x) == -y, x); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /test/native/soft/integer/fixunsdfti.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/fixunsdfti.h" 2 | #include "math/double/unary.h" 3 | 4 | int main(void) 5 | { 6 | for (int64_t i = 0; i < 0x47F0000000000000; i += 0x000000034E3F771E) { 7 | double x = reinterpret(double, i); 8 | verify(fixunsdfti_(x) == (unsigned __int128)x, x); 9 | verify(!fixunsdfti_(-x), x); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/native/soft/integer/fixunssfti.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/fixunssfti.h" 2 | #include "math/float/unary.h" 3 | 4 | int main(void) 5 | { 6 | for (uint32_t i = 0; i < 0x7F800000; i += 71) { 7 | float x = reinterpret(float, i); 8 | verify(fixunssfti_(x) == (unsigned __int128)x, x); 9 | verify(!fixunssfti_(-x), x); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /test/native/soft/integer/floattidf.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/floattidf.h" 2 | #include "math/double/unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | const __int128 max = (unsigned __int128)-1 >> 1; 8 | const __int128 min = -max - 1; 9 | unsigned __int128 a = 0; 10 | 11 | assert(identical(floattidf_(min), min)); 12 | 13 | for (long i = 0; i < 1L << 26; ++i) { 14 | __int128 b = a & max; 15 | verify(identical(floattidf_(b), b), b); 16 | verify(identical(floattidf_(-b), -b), b); 17 | a = a + 1993 + (a >> 3); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /test/native/soft/integer/floattisf.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/floattisf.h" 2 | #include "math/float/unary.h" 3 | #include 4 | 5 | int main(void) 6 | { 7 | const __int128 max = (unsigned __int128)-1 >> 1; 8 | const __int128 min = -max - 1; 9 | unsigned __int128 a = 0; 10 | 11 | assert(identical(floattisf_(min), min)); 12 | 13 | for (long i = 0; i < 1L << 26; ++i) { 14 | __int128 b = a & max; 15 | verify(identical(floattisf_(b), b), b); 16 | verify(identical(floattisf_(-b), -b), b); 17 | a = a + 1993 + (a >> 3); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /test/native/soft/integer/floatuntidf.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/floatuntidf.h" 2 | #include "math/double/unary.h" 3 | 4 | int main(void) 5 | { 6 | unsigned __int128 a = 0; 7 | 8 | for (long i = 0; i < 1L << 26; ++i) { 9 | verify(identical(floatuntidf_(a), a), a); 10 | a = a + 1993 + (a >> 3); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /test/native/soft/integer/floatuntisf.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/floatuntisf.h" 2 | #include "math/float/unary.h" 3 | 4 | int main(void) 5 | { 6 | unsigned __int128 a = 0; 7 | 8 | for (long i = 0; i < 1L << 26; ++i) { 9 | verify(identical(floatuntisf_(a), a), a); 10 | a = a + 1993 + (a >> 3); 11 | } 12 | } 13 | 14 | -------------------------------------------------------------------------------- /test/native/soft/integer/umulti4.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/umulti4.h" 2 | #include 3 | 4 | static uint64_t sum2(uint64_t a, uint64_t b) 5 | { 6 | uint64_t s = a + b; 7 | return s + (s < a); 8 | } 9 | 10 | static uint64_t sum1(unsigned __int128 a) 11 | { 12 | return sum2(a >> 64, a); 13 | } 14 | 15 | int main(void) 16 | { 17 | unsigned __int128 a = 0; 18 | unsigned __int128 b = 0; 19 | 20 | for (long i = 0; i < 1L << 26; ++i) { 21 | unsigned __int128 high; 22 | unsigned __int128 low = umulti4_(a, b, &high); 23 | 24 | assert(low == a * b); 25 | assert(sum2(sum1(high), sum1(low)) == sum1((unsigned __int128)sum1(a) * sum1(b))); 26 | 27 | a = a + 1993 + (a >> 3); 28 | b = b + 2019 + (b >> 4); 29 | } 30 | } 31 | 32 | -------------------------------------------------------------------------------- /test/wasm/crt/argv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char** argv) 5 | { 6 | for (int i = 0; i < argc; ++i) 7 | printf("%p: %s\n", argv[i], argv[i]); 8 | 9 | assert(!argv[argc]); 10 | } 11 | -------------------------------------------------------------------------------- /test/wasm/math/double/fdim.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static void run(double x, double y) 7 | { 8 | assert(fdim(x, y) == x - y); 9 | assert(fdim(-y, -x) == x - y); 10 | assert(reinterpret(uint64_t, fdim(y, x)) == 0); 11 | assert(reinterpret(uint64_t, fdim(-x, -y)) == 0); 12 | } 13 | 14 | int main(void) 15 | { 16 | for (uint64_t j = 0; j < 0x7FF0000000000000; j += 0x000F357D41AFBD75) 17 | for (uint64_t i = j; i < 0x7FF0000000000000; i += 0x000EBE116CAB22F4) 18 | run(reinterpret(double, i), reinterpret(double, j)); 19 | 20 | assert(reinterpret(uint64_t, fdim(INFINITY, INFINITY)) == 0); 21 | assert(reinterpret(uint64_t, fdim(-INFINITY, -INFINITY)) == 0); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /test/wasm/math/double/identical.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | 4 | static _Bool identical(double x, double y) 5 | { 6 | return reinterpret(uint64_t, x) == reinterpret(uint64_t, y); 7 | } 8 | -------------------------------------------------------------------------------- /test/wasm/math/double/lround.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | int main(void) 8 | { 9 | const uint64_t max = 0x5000000000000000; 10 | const uint64_t step = 0x00000007BD058423; 11 | 12 | for (uint64_t i = 0; i < max; i += step) { 13 | double x = reinterpret(double, i); 14 | double y = round(x); 15 | 16 | if (y > LONG_MAX) 17 | break; 18 | 19 | assert(y == lround(x)); 20 | assert(-y == lround(-x)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /test/wasm/math/float/cabsf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | #include 5 | 6 | static void run(float x, float y) 7 | { 8 | assert(cidentical(cabsf(CMPLXF(x, y)), hypotf(x, y))); 9 | } 10 | 11 | int main(void) 12 | { 13 | for (uint32_t j = 0; j < 1 << 12; ++j) 14 | for (uint32_t i = 0; i < 1 << 12; ++i) 15 | run(reinterpret(float, i << 20), reinterpret(float, j << 20)); 16 | } 17 | -------------------------------------------------------------------------------- /test/wasm/math/float/cacosf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | 5 | static float _Complex rotate(float _Complex z) 6 | { 7 | return CMPLXF(-cimagf(z), z); 8 | } 9 | 10 | static void run(float _Complex z) 11 | { 12 | assert(cidentical(cacoshf(z), rotate(cacosf(z)))); 13 | assert(cidentical(conjf(cacosf(z)), cacosf(conjf(z)))); 14 | } 15 | 16 | int main(void) 17 | { 18 | for (uint32_t j = 0; j < 0x80000000; j += 0x00100000) 19 | for (uint32_t i = 0; i < 1 << 12; ++i) 20 | run(CMPLXF(reinterpret(float, i << 20), reinterpret(float, j))); 21 | } 22 | -------------------------------------------------------------------------------- /test/wasm/math/float/cargf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | #include 5 | 6 | static void run(float x, float y) 7 | { 8 | assert(cidentical(cargf(CMPLXF(x, y)), atan2f(y, x))); 9 | } 10 | 11 | int main(void) 12 | { 13 | for (uint32_t j = 0; j < 1 << 12; ++j) 14 | for (uint32_t i = 0; i < 1 << 12; ++i) 15 | run(reinterpret(float, i << 20), reinterpret(float, j << 20)); 16 | } 17 | -------------------------------------------------------------------------------- /test/wasm/math/float/casinf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | 5 | static float _Complex swap(float _Complex z) 6 | { 7 | return CMPLXF(cimagf(z), z); 8 | } 9 | 10 | static void run(float x, float y) 11 | { 12 | assert(cidentical(casinhf(CMPLXF(x, y)), swap(casinf(CMPLXF(y, x))))); 13 | } 14 | 15 | int main(void) 16 | { 17 | for (uint32_t j = 0; j < 1 << 12; ++j) 18 | for (uint32_t i = 0; i < 1 << 12; ++i) 19 | run(reinterpret(float, i << 20), reinterpret(float, j << 20)); 20 | } 21 | -------------------------------------------------------------------------------- /test/wasm/math/float/catanhf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | 5 | static float _Complex swap(float _Complex z) 6 | { 7 | return CMPLXF(cimagf(z), z); 8 | } 9 | 10 | static void run(float x, float y) 11 | { 12 | assert(cidentical(catanhf(CMPLXF(x, y)), swap(catanf(CMPLXF(y, x))))); 13 | } 14 | 15 | int main(void) 16 | { 17 | for (uint32_t j = 0; j < 1 << 12; ++j) 18 | for (uint32_t i = 0; i < 1 << 12; ++i) 19 | run(reinterpret(float, i << 20), reinterpret(float, j << 20)); 20 | } 21 | -------------------------------------------------------------------------------- /test/wasm/math/float/ccosf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | 5 | static void run(float x, float y) 6 | { 7 | assert(cidentical(ccoshf(CMPLXF(-y, x)), ccosf(CMPLXF(x, y)))); 8 | } 9 | 10 | int main(void) 11 | { 12 | for (uint32_t j = 0; j < 1 << 12; ++j) 13 | for (uint32_t i = 0; i < 1 << 12; ++i) 14 | run(reinterpret(float, i << 20), reinterpret(float, j << 20)); 15 | } 16 | -------------------------------------------------------------------------------- /test/wasm/math/float/cidentical.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | 4 | static _Bool cidentical(float _Complex x, float _Complex y) 5 | { 6 | return reinterpret(uint64_t, x) == reinterpret(uint64_t, y); 7 | } 8 | -------------------------------------------------------------------------------- /test/wasm/math/float/csinf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | 5 | static float _Complex swap(float _Complex z) 6 | { 7 | return CMPLXF(cimagf(z), z); 8 | } 9 | 10 | static void run(float x, float y) 11 | { 12 | assert(cidentical(csinhf(CMPLXF(x, y)), swap(csinf(CMPLXF(y, x))))); 13 | } 14 | 15 | int main(void) 16 | { 17 | for (uint32_t j = 0; j < 1 << 12; ++j) 18 | for (uint32_t i = 0; i < 1 << 12; ++i) 19 | run(reinterpret(float, i << 20), reinterpret(float, j << 20)); 20 | } 21 | -------------------------------------------------------------------------------- /test/wasm/math/float/ctanf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "cidentical.h" 3 | #include 4 | 5 | static float _Complex swap(float _Complex z) 6 | { 7 | return CMPLXF(cimagf(z), z); 8 | } 9 | 10 | static void run(float x, float y) 11 | { 12 | assert(cidentical(ctanhf(CMPLXF(x, y)), swap(ctanf(CMPLXF(y, x))))); 13 | } 14 | 15 | int main(void) 16 | { 17 | for (uint32_t j = 0; j < 1 << 12; ++j) 18 | for (uint32_t i = 0; i < 1 << 12; ++i) 19 | run(reinterpret(float, i << 20), reinterpret(float, j << 20)); 20 | } 21 | -------------------------------------------------------------------------------- /test/wasm/math/float/fdimf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | static void run(float x, float y) 7 | { 8 | assert(fdimf(x, y) == x - y); 9 | assert(fdimf(-y, -x) == x - y); 10 | assert(reinterpret(uint32_t, fdimf(y, x)) == 0); 11 | assert(reinterpret(uint32_t, fdimf(-x, -y)) == 0); 12 | } 13 | 14 | int main(void) 15 | { 16 | for (uint32_t j = 0; j < 0x7F800000; j += 0x000ABCDE) 17 | for (uint32_t i = j; i < 0x7F800000; i += 0x00098765) 18 | run(reinterpret(float, i), reinterpret(float, j)); 19 | 20 | assert(reinterpret(uint32_t, fdimf(INFINITY, INFINITY)) == 0); 21 | assert(reinterpret(uint32_t, fdimf(-INFINITY, -INFINITY)) == 0); 22 | } 23 | -------------------------------------------------------------------------------- /test/wasm/math/float/identical.h: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | 4 | static _Bool identical(float x, float y) 5 | { 6 | return reinterpret(uint32_t, x) == reinterpret(uint32_t, y); 7 | } 8 | -------------------------------------------------------------------------------- /test/wasm/math/float/nextafterf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "identical.h" 3 | #include 4 | 5 | static _Bool run(float from, float to) 6 | { 7 | float x = from ? from : copysignf(from, to); 8 | float y = nextafterf(from, to); 9 | _Bool near = reinterpret(uint32_t, x) - reinterpret(uint32_t, y) + 1 <= 2; 10 | 11 | if (from == to) 12 | return identical(to, y); 13 | 14 | if (from < to) 15 | return from < y && near; 16 | 17 | if (from > to) 18 | return from > y && near; 19 | 20 | return isnan(y); 21 | } 22 | 23 | int main(void) 24 | { 25 | for (uint32_t j = 0; j < 1 << 12; ++j) 26 | for (uint32_t i = 0; i < 1 << 12; ++i) 27 | assert(run(reinterpret(float, i << 20), reinterpret(float, j << 20))); 28 | } 29 | -------------------------------------------------------------------------------- /test/wasm/soft/float/extendsftf2.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | float __trunctfsf2(long double); 7 | 8 | static _Bool run(float x) 9 | { 10 | return reinterpret(uint32_t, x) == reinterpret(uint32_t, __trunctfsf2(x)); 11 | } 12 | 13 | int main(void) 14 | { 15 | assert(run(INFINITY)); 16 | assert(run(-INFINITY)); 17 | 18 | for (uint32_t i = 0; i < 0x7F800000; i += 29) { 19 | float x = reinterpret(float, i); 20 | assert(run(x)); 21 | assert(run(-x)); 22 | } 23 | 24 | for (uint32_t i = 0x7F800001; i < 0x80000000; i += 37) { 25 | float x = reinterpret(float, i); 26 | assert(isnan(__trunctfsf2(x))); 27 | assert(isnan(__trunctfsf2(-x))); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/wasm/soft/float/fixtfdi.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int64_t __fixtfdi(long double); 7 | 8 | int main(void) 9 | { 10 | const __int128 delta = (__int128)0x17E93193 << 64 | 0xC0605887B0E6B634; 11 | 12 | assert(__fixtfdi(INT64_MIN - 0.7L) == INT64_MIN); 13 | 14 | for (__int128 i = reinterpret(__int128, 0.9L); i < reinterpret(__int128, 0x1p63L); i += delta) { 15 | long double x = reinterpret(long double, i); 16 | long double y = truncl(x); 17 | assert(__fixtfdi(x) == y); 18 | assert(__fixtfdi(-x) == -y); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/wasm/soft/float/fixtfsi.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int32_t __fixtfsi(long double); 7 | 8 | int main(void) 9 | { 10 | const __int128 delta = (__int128)0x17E93193 << 64 | 0xC0605887B0E6B634; 11 | 12 | assert(__fixtfsi(INT32_MIN - 0.7L) == INT32_MIN); 13 | 14 | for (__int128 i = reinterpret(__int128, 0.9L); i < reinterpret(__int128, 0x1p31L); i += delta) { 15 | long double x = reinterpret(long double, i); 16 | long double y = truncl(x); 17 | assert(__fixtfsi(x) == y); 18 | assert(__fixtfsi(-x) == -y); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/wasm/soft/float/fixtfti.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | __int128 __fixtfti(long double); 6 | 7 | int main(void) 8 | { 9 | const __int128 delta = (__int128)0x17E93193 << 64 | 0xC0605887B0E6B634; 10 | 11 | assert(__fixtfti(-0x1p-127L - 0.7L) == (__int128)-0x1p-127); 12 | 13 | for (__int128 i = reinterpret(__int128, 0.9L); i < reinterpret(__int128, 0x1p127L); i += delta) { 14 | long double x = reinterpret(long double, i); 15 | long double y = truncl(x); 16 | assert(__fixtfti(x) == y); 17 | assert(__fixtfti(-x) == -y); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/wasm/soft/float/fixunstfdi.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | const __int128 delta = (__int128)0x17E93193 << 64 | 0xC0605887B0E6B634; 9 | 10 | for (__int128 i = reinterpret(__int128, 0.9L); i < reinterpret(__int128, 0x1p64L); i += delta) { 11 | long double x = reinterpret(long double, i); 12 | assert((uint64_t)x == truncl(x)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/wasm/soft/float/fixunstfsi.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | #include 5 | 6 | int main(void) 7 | { 8 | const __int128 delta = (__int128)0x17E93193 << 64 | 0xC0605887B0E6B634; 9 | 10 | for (__int128 i = reinterpret(__int128, 0.9L); i < reinterpret(__int128, 0x1p32L); i += delta) { 11 | long double x = reinterpret(long double, i); 12 | assert((uint32_t)x == truncl(x)); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/wasm/soft/float/fixunstfti.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { 7 | const __int128 delta = (__int128)0x17E93193 << 64 | 0xC0605887B0E6B634; 8 | 9 | for (__int128 i = reinterpret(__int128, 0.9L); i < reinterpret(__int128, 0x1p128L); i += delta) { 10 | long double x = reinterpret(long double, i); 11 | assert((unsigned __int128)x == truncl(x)); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /test/wasm/soft/float/floatditf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | int64_t __fixtfdi(long double); 6 | 7 | static _Bool run(int64_t a) 8 | { 9 | return a == __fixtfdi(a); 10 | } 11 | 12 | int main(void) 13 | { 14 | const int64_t delta = 0x0000002BA87B5A22; 15 | 16 | assert(run(INT64_MAX)); 17 | assert(run(INT64_MIN)); 18 | 19 | for (int64_t i = 0x3FFFFFFFFFFFFFFF; i < 0x4340000000000000; i += delta) { 20 | double x = reinterpret(double, i); 21 | assert(run(x)); 22 | assert(run(-x)); 23 | } 24 | 25 | for (int64_t i = 0; i <= INT64_MAX / delta; ++i) { 26 | assert(run(i * delta)); 27 | assert(run(i * -delta)); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /test/wasm/soft/float/floatsitf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | int32_t __fixtfsi(long double); 6 | 7 | static _Bool run(int32_t a) 8 | { 9 | return a == __fixtfsi(a); 10 | } 11 | 12 | int main(void) 13 | { 14 | const int64_t delta = 0x0000002BA87B5A22; 15 | 16 | assert(run(INT32_MAX)); 17 | assert(run(INT32_MIN)); 18 | 19 | for (int64_t i = 0x3FFFFFFFFFFFFFFF; i < 0x41E0000000000000; i += delta) { 20 | double x = reinterpret(double, i); 21 | assert(run(x)); 22 | assert(run(-x)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /test/wasm/soft/float/floatunditf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | uint64_t __fixunstfdi(long double); 6 | 7 | static _Bool run(uint64_t a) 8 | { 9 | return a == __fixunstfdi(a); 10 | } 11 | 12 | int main(void) 13 | { 14 | const uint64_t delta = 0x0000002BA87B5A22; 15 | 16 | for (uint64_t i = 0x3FFFFFFFFFFFFFFF; i < 0x4340000000000000; i += delta) 17 | assert(run(reinterpret(double, i))); 18 | 19 | for (uint64_t i = 0; i <= UINT64_MAX / delta; ++i) 20 | assert(run(i * delta)); 21 | } 22 | -------------------------------------------------------------------------------- /test/wasm/soft/float/floatunsitf.c: -------------------------------------------------------------------------------- 1 | #include "src/math/reinterpret.h" 2 | #include 3 | #include 4 | 5 | uint32_t __fixunstfsi(long double); 6 | 7 | static _Bool run(uint32_t a) 8 | { 9 | return a == __fixunstfsi(a); 10 | } 11 | 12 | int main(void) 13 | { 14 | const uint64_t delta = 0x0000002BA87B5A22; 15 | 16 | for (uint64_t i = 0x3FFFFFFFFFFFFFFF; i < 0x41F0000000000000; i += delta) 17 | assert(run(reinterpret(double, i))); 18 | } 19 | -------------------------------------------------------------------------------- /test/wasm/soft/integer/ashlti3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void run(unsigned __int128 x) 4 | { 5 | unsigned __int128 y = x; 6 | 7 | for (int shift = 0; shift < 128; ++shift) { 8 | assert(x << shift == y); 9 | y <<= 1; 10 | } 11 | } 12 | 13 | int main(void) 14 | { 15 | for (unsigned __int128 x = 1; x; x *= 2) 16 | run(x); 17 | 18 | for (unsigned __int128 x = 1; x >> 104 != 0x313370; x *= 3) 19 | run(x); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /test/wasm/soft/integer/ashrti3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void run(__int128 x) 4 | { 5 | __int128 y = x; 6 | 7 | for (int shift = 0; shift < 128; ++shift) { 8 | assert(x >> shift == y); 9 | y >>= 1; 10 | } 11 | } 12 | 13 | int main(void) 14 | { 15 | __int128 max = (unsigned __int128)-1 >> 1; 16 | 17 | for (unsigned __int128 x = 1; x; x *= 2) 18 | run(x); 19 | 20 | for (unsigned __int128 x = 1; x >> 104 != 0x313370; x *= 3) 21 | run(x & max); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /test/wasm/soft/integer/lshrti3.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | static void run(unsigned __int128 x) 4 | { 5 | unsigned __int128 y = x; 6 | 7 | for (int shift = 0; shift < 128; ++shift) { 8 | assert(x >> shift == y); 9 | y >>= 1; 10 | } 11 | } 12 | 13 | int main(void) 14 | { 15 | for (unsigned __int128 x = 1; x; x *= 2) 16 | run(x); 17 | 18 | for (unsigned __int128 x = 1; x >> 104 != 0x313370; x *= 3) 19 | run(x); 20 | } 21 | 22 | -------------------------------------------------------------------------------- /test/wasm/soft/integer/udivmodti4.c: -------------------------------------------------------------------------------- 1 | #include "src/soft/integer/udivmodti4.h" 2 | #include 3 | 4 | static void run(unsigned __int128 a, unsigned __int128 b) 5 | { 6 | unsigned __int128 r; 7 | unsigned __int128 q = udivmodti4_(a, b, &r); 8 | 9 | assert(a == b * q + r); 10 | } 11 | 12 | int main(void) 13 | { 14 | for (unsigned __int128 a = 1; a >> 116 != 0xFFF; a *= 3) 15 | for (unsigned __int128 b = 1; b >> 116 != 0xFFF; b *= 5) 16 | run(a, b); 17 | } 18 | 19 | 20 | -------------------------------------------------------------------------------- /test/wasm/stdio/feof.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char* argv[static 2]) 5 | { 6 | FILE* stream = fopen(argv[0], "rb"); 7 | 8 | assert(!fseek(stream, 0, SEEK_END)); 9 | assert(!feof(stream)); 10 | 11 | assert(getc(stream) == EOF); 12 | assert(feof(stream)); 13 | 14 | assert(!fseek(stream, 0, SEEK_END)); 15 | assert(!feof(stream)); 16 | 17 | fclose(stream); 18 | } 19 | -------------------------------------------------------------------------------- /test/wasm/stdio/fopen.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(int argc, char* argv[static 2]) 6 | { 7 | FILE* stream = fopen(argv[0], "rb"); 8 | assert(stream); 9 | assert(!fclose(stream)); 10 | assert(!errno); 11 | 12 | assert(!fopen(".", "rb+")); 13 | assert(errno == EISDIR); 14 | } 15 | -------------------------------------------------------------------------------- /test/wasm/stdio/fseek.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static long posix(const char path[static 1]) 7 | { 8 | struct stat metadata; 9 | 10 | assert(!stat(path, &metadata)); 11 | 12 | return metadata.st_size; 13 | } 14 | 15 | static long standard(const char path[static 1]) 16 | { 17 | FILE* stream = fopen(path, "rb"); 18 | 19 | fseek(stream, 0, SEEK_END); 20 | long position = ftell(stream); 21 | 22 | fclose(stream); 23 | return position; 24 | } 25 | 26 | int main(int argc, char* argv[static 2]) 27 | { 28 | assert(posix(argv[0]) == standard(argv[0])); 29 | assert(!errno); 30 | } 31 | -------------------------------------------------------------------------------- /test/wasm/stdio/ungetc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { 7 | ungetc('\0', stdin); 8 | ungetc('g', stdin); 9 | ungetc('o', stdin); 10 | ungetc('d', stdin); 11 | 12 | unsigned char buffer[4]; 13 | fread(buffer, 4, 1, stdin); 14 | assert(!memcmp(buffer, "dog", 4)); 15 | } 16 | -------------------------------------------------------------------------------- /test/wasm/time/timespec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | int main(void) 6 | { 7 | struct timespec spec; 8 | 9 | assert(timespec_get(&spec, TIME_UTC)); 10 | assert(printf("%lld.%.9ld\n", spec.tv_sec, spec.tv_nsec) >= 0); 11 | } 12 | --------------------------------------------------------------------------------