diff --git a/CMakeLists.txt b/CMakeLists.txt index f2bfb61b5..75884205c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7583,6 +7583,82 @@ set(ZIG_LIBC_FILES "include/x86_64-linux-musl/bits/user.h" "include/wasm32-freestanding-musl/bits/alltypes.h" "include/wasm32-freestanding-musl/errno.h" + "mingw/complex/_cabs.c" + "mingw/complex/cabs.c" + "mingw/complex/cabs.def.h" + "mingw/complex/cabsf.c" + "mingw/complex/cabsl.c" + "mingw/complex/cacos.c" + "mingw/complex/cacos.def.h" + "mingw/complex/cacosf.c" + "mingw/complex/cacosh.def.h" + "mingw/complex/cacosl.c" + "mingw/complex/carg.c" + "mingw/complex/carg.def.h" + "mingw/complex/cargf.c" + "mingw/complex/cargl.c" + "mingw/complex/casin.c" + "mingw/complex/casin.def.h" + "mingw/complex/casinf.c" + "mingw/complex/casinh.def.h" + "mingw/complex/casinl.c" + "mingw/complex/catan.c" + "mingw/complex/catan.def.h" + "mingw/complex/catanf.c" + "mingw/complex/catanh.def.h" + "mingw/complex/catanl.c" + "mingw/complex/ccos.c" + "mingw/complex/ccos.def.h" + "mingw/complex/ccosf.c" + "mingw/complex/ccosh.def.h" + "mingw/complex/ccosl.c" + "mingw/complex/cexp.c" + "mingw/complex/cexp.def.h" + "mingw/complex/cexpf.c" + "mingw/complex/cexpl.c" + "mingw/complex/cimag.c" + "mingw/complex/cimag.def.h" + "mingw/complex/cimagf.c" + "mingw/complex/cimagl.c" + "mingw/complex/clog.c" + "mingw/complex/clog.def.h" + "mingw/complex/clog10.c" + "mingw/complex/clog10.def.h" + "mingw/complex/clog10f.c" + "mingw/complex/clog10l.c" + "mingw/complex/clogf.c" + "mingw/complex/clogl.c" + "mingw/complex/complex_internal.h" + "mingw/complex/conj.c" + "mingw/complex/conj.def.h" + "mingw/complex/conjf.c" + "mingw/complex/conjl.c" + "mingw/complex/cpow.c" + "mingw/complex/cpow.def.h" + "mingw/complex/cpowf.c" + "mingw/complex/cpowl.c" + "mingw/complex/cproj.c" + "mingw/complex/cproj.def.h" + "mingw/complex/cprojf.c" + "mingw/complex/cprojl.c" + "mingw/complex/creal.c" + "mingw/complex/creal.def.h" + "mingw/complex/crealf.c" + "mingw/complex/creall.c" + "mingw/complex/csin.c" + "mingw/complex/csin.def.h" + "mingw/complex/csinf.c" + "mingw/complex/csinh.def.h" + "mingw/complex/csinl.c" + "mingw/complex/csqrt.c" + "mingw/complex/csqrt.def.h" + "mingw/complex/csqrtf.c" + "mingw/complex/csqrtl.c" + "mingw/complex/ctan.c" + "mingw/complex/ctan.def.h" + "mingw/complex/ctanf.c" + "mingw/complex/ctanh.def.h" + "mingw/complex/ctanl.c" "mingw/crt/CRT_fp10.c" "mingw/crt/_newmode.c" "mingw/crt/charmax.c" @@ -7595,6 +7671,8 @@ set(ZIG_LIBC_FILES "mingw/crt/cxa_atexit.c" "mingw/crt/dll_argv.c" "mingw/crt/dllargv.c" + "mingw/crt/dllentry.c" + "mingw/crt/dllmain.c" "mingw/crt/gccmain.c" "mingw/crt/gs_support.c" "mingw/crt/merr.c" @@ -7615,6 +7693,31 @@ set(ZIG_LIBC_FILES "mingw/crt/xtxtmode.c" "mingw/def-include/func.def.in" "mingw/def-include/msvcrt-common.def.in" + "mingw/gdtoa/arithchk.c" + "mingw/gdtoa/dmisc.c" + "mingw/gdtoa/dtoa.c" + "mingw/gdtoa/g__fmt.c" + "mingw/gdtoa/g_dfmt.c" + "mingw/gdtoa/g_ffmt.c" + "mingw/gdtoa/g_xfmt.c" + "mingw/gdtoa/gd_arith.h" + "mingw/gdtoa/gd_qnan.h" + "mingw/gdtoa/gdtoa.c" + "mingw/gdtoa/gdtoa.h" + "mingw/gdtoa/gdtoaimp.h" + "mingw/gdtoa/gethex.c" + "mingw/gdtoa/gmisc.c" + "mingw/gdtoa/hd_init.c" + "mingw/gdtoa/hexnan.c" + "mingw/gdtoa/misc.c" + "mingw/gdtoa/qnan.c" + "mingw/gdtoa/smisc.c" + "mingw/gdtoa/strtodg.c" + "mingw/gdtoa/strtodnrp.c" + "mingw/gdtoa/strtof.c" + "mingw/gdtoa/strtopx.c" + "mingw/gdtoa/sum.c" + "mingw/gdtoa/ulp.c" "mingw/include/config.h" "mingw/include/internal.h" "mingw/include/msvcrt.h" @@ -7622,18 +7725,334 @@ set(ZIG_LIBC_FILES "mingw/include/sect_attribs.h" "mingw/lib-common/kernel32.def.in" "mingw/lib-common/msvcrt.def.in" + "mingw/math/abs64.c" + "mingw/math/arm/_chgsignl.S" + "mingw/math/arm/ceil.S" + "mingw/math/arm/ceilf.S" + "mingw/math/arm/ceill.S" + "mingw/math/arm/copysignl.c" + "mingw/math/arm/exp2.c" + "mingw/math/arm/floor.S" + "mingw/math/arm/floorf.S" + "mingw/math/arm/floorl.S" + "mingw/math/arm/ldexpl.c" + "mingw/math/arm/log2.c" + "mingw/math/arm/nearbyint.S" + "mingw/math/arm/nearbyintf.S" + "mingw/math/arm/nearbyintl.S" + "mingw/math/arm/scalbn.c" + "mingw/math/arm/sincos.c" + "mingw/math/arm/trunc.S" + "mingw/math/arm/truncf.S" + "mingw/math/arm64/_chgsignl.S" + "mingw/math/arm64/ceil.S" + "mingw/math/arm64/ceilf.S" + "mingw/math/arm64/ceill.S" + "mingw/math/arm64/copysignl.c" + "mingw/math/arm64/exp2.S" + "mingw/math/arm64/exp2f.S" + "mingw/math/arm64/floor.S" + "mingw/math/arm64/floorf.S" + "mingw/math/arm64/floorl.S" + "mingw/math/arm64/ldexpl.c" + "mingw/math/arm64/log2.c" + "mingw/math/arm64/nearbyint.S" + "mingw/math/arm64/nearbyintf.S" + "mingw/math/arm64/nearbyintl.S" + "mingw/math/arm64/scalbn.c" + "mingw/math/arm64/sincos.c" + "mingw/math/arm64/trunc.S" + "mingw/math/arm64/truncf.S" + "mingw/math/cbrt.c" + "mingw/math/cbrtf.c" + "mingw/math/cbrtl.c" + "mingw/math/cephes_emath.c" + "mingw/math/cephes_emath.h" + "mingw/math/cephes_mconf.h" + "mingw/math/copysign.c" + "mingw/math/copysignf.c" + "mingw/math/coshf.c" + "mingw/math/coshl.c" + "mingw/math/erfl.c" + "mingw/math/expf.c" + "mingw/math/fabs.c" + "mingw/math/fabsf.c" + "mingw/math/fabsl.c" + "mingw/math/fdim.c" + "mingw/math/fdimf.c" + "mingw/math/fdiml.c" + "mingw/math/fma.c" + "mingw/math/fmaf.c" + "mingw/math/fmal.c" + "mingw/math/fmax.c" + "mingw/math/fmaxf.c" + "mingw/math/fmaxl.c" + "mingw/math/fmin.c" + "mingw/math/fminf.c" + "mingw/math/fminl.c" + "mingw/math/fp_consts.c" + "mingw/math/fp_consts.h" + "mingw/math/fp_constsf.c" + "mingw/math/fp_constsl.c" + "mingw/math/fpclassify.c" + "mingw/math/fpclassifyf.c" + "mingw/math/fpclassifyl.c" + "mingw/math/frexpf.c" + "mingw/math/hypot.c" + "mingw/math/hypotf.c" + "mingw/math/hypotl.c" + "mingw/math/isnan.c" + "mingw/math/isnanf.c" + "mingw/math/isnanl.c" + "mingw/math/ldexpf.c" + "mingw/math/lgamma.c" + "mingw/math/lgammaf.c" + "mingw/math/lgammal.c" + "mingw/math/llrint.c" + "mingw/math/llrintf.c" + "mingw/math/llrintl.c" + "mingw/math/llround.c" + "mingw/math/llroundf.c" + "mingw/math/llroundl.c" + "mingw/math/log10f.c" + "mingw/math/logf.c" + "mingw/math/lrint.c" + "mingw/math/lrintf.c" + "mingw/math/lrintl.c" + "mingw/math/lround.c" + "mingw/math/lroundf.c" + "mingw/math/lroundl.c" + "mingw/math/modf.c" + "mingw/math/modff.c" + "mingw/math/modfl.c" + "mingw/math/nextafterf.c" + "mingw/math/nextafterl.c" + "mingw/math/nexttoward.c" + "mingw/math/nexttowardf.c" + "mingw/math/powf.c" + "mingw/math/powi.c" + "mingw/math/powi.def.h" + "mingw/math/powif.c" + "mingw/math/powil.c" + "mingw/math/rint.c" + "mingw/math/rintf.c" + "mingw/math/rintl.c" + "mingw/math/round.c" + "mingw/math/roundf.c" + "mingw/math/roundl.c" + "mingw/math/s_erf.c" + "mingw/math/sf_erf.c" + "mingw/math/signbit.c" + "mingw/math/signbitf.c" + "mingw/math/signbitl.c" + "mingw/math/signgam.c" + "mingw/math/sinhf.c" + "mingw/math/sinhl.c" + "mingw/math/sqrt.c" + "mingw/math/sqrt.def.h" + "mingw/math/sqrtf.c" + "mingw/math/sqrtl.c" + "mingw/math/tanhf.c" + "mingw/math/tanhl.c" + "mingw/math/tgamma.c" + "mingw/math/tgammaf.c" + "mingw/math/tgammal.c" + "mingw/math/truncl.c" + "mingw/math/x86/_chgsignl.S" + "mingw/math/x86/acosf.c" + "mingw/math/x86/acosh.c" + "mingw/math/x86/acosh.def.h" + "mingw/math/x86/acoshf.c" + "mingw/math/x86/acoshl.c" + "mingw/math/x86/acosl.c" + "mingw/math/x86/asinf.c" + "mingw/math/x86/asinh.c" + "mingw/math/x86/asinhf.c" + "mingw/math/x86/asinhl.c" + "mingw/math/x86/asinl.c" + "mingw/math/x86/atan2.c" + "mingw/math/x86/atan2f.c" + "mingw/math/x86/atan2l.c" + "mingw/math/x86/atanf.c" + "mingw/math/x86/atanh.c" + "mingw/math/x86/atanhf.c" + "mingw/math/x86/atanhl.c" + "mingw/math/x86/atanl.c" + "mingw/math/x86/ceil.S" + "mingw/math/x86/ceilf.S" + "mingw/math/x86/ceill.S" + "mingw/math/x86/copysignl.S" + "mingw/math/x86/cos.c" + "mingw/math/x86/cos.def.h" + "mingw/math/x86/cosf.c" + "mingw/math/x86/cosl.c" + "mingw/math/x86/cosl_internal.S" + "mingw/math/x86/cossin.c" + "mingw/math/x86/exp.c" + "mingw/math/x86/exp.def.h" + "mingw/math/x86/exp2.S" + "mingw/math/x86/exp2f.S" + "mingw/math/x86/exp2l.S" + "mingw/math/x86/expl.c" + "mingw/math/x86/expm1.c" + "mingw/math/x86/expm1.def.h" + "mingw/math/x86/expm1f.c" + "mingw/math/x86/expm1l.c" + "mingw/math/x86/fastmath.h" + "mingw/math/x86/floor.S" + "mingw/math/x86/floorf.S" + "mingw/math/x86/floorl.S" + "mingw/math/x86/fmod.c" + "mingw/math/x86/fmodf.c" + "mingw/math/x86/fmodl.c" + "mingw/math/x86/frexpl.S" + "mingw/math/x86/fucom.c" + "mingw/math/x86/ilogb.S" + "mingw/math/x86/ilogbf.S" + "mingw/math/x86/ilogbl.S" + "mingw/math/x86/internal_logl.S" + "mingw/math/x86/ldexp.c" + "mingw/math/x86/ldexpl.c" + "mingw/math/x86/log.c" + "mingw/math/x86/log.def.h" + "mingw/math/x86/log10l.S" + "mingw/math/x86/log1p.S" + "mingw/math/x86/log1pf.S" + "mingw/math/x86/log1pl.S" + "mingw/math/x86/log2.S" + "mingw/math/x86/log2f.S" + "mingw/math/x86/log2l.S" + "mingw/math/x86/logb.c" + "mingw/math/x86/logbf.c" + "mingw/math/x86/logbl.c" + "mingw/math/x86/logl.c" + "mingw/math/x86/nearbyint.S" + "mingw/math/x86/nearbyintf.S" + "mingw/math/x86/nearbyintl.S" + "mingw/math/x86/pow.c" + "mingw/math/x86/pow.def.h" + "mingw/math/x86/powl.c" + "mingw/math/x86/remainder.S" + "mingw/math/x86/remainderf.S" + "mingw/math/x86/remainderl.S" + "mingw/math/x86/remquo.S" + "mingw/math/x86/remquof.S" + "mingw/math/x86/remquol.S" + "mingw/math/x86/scalbn.S" + "mingw/math/x86/scalbnf.S" + "mingw/math/x86/scalbnl.S" + "mingw/math/x86/sin.c" + "mingw/math/x86/sin.def.h" + "mingw/math/x86/sinf.c" + "mingw/math/x86/sinl.c" + "mingw/math/x86/sinl_internal.S" + "mingw/math/x86/tanf.c" + "mingw/math/x86/tanl.S" + "mingw/math/x86/trunc.S" + "mingw/math/x86/truncf.S" "mingw/misc/__p___argv.c" "mingw/misc/__p__acmdln.c" "mingw/misc/__p__fmode.c" "mingw/misc/__p__wcmdln.c" "mingw/misc/_configthreadlocale.c" "mingw/misc/_get_current_locale.c" + "mingw/misc/alarm.c" + "mingw/misc/assert.c" + "mingw/misc/basename.c" + "mingw/misc/btowc.c" + "mingw/misc/delay-f.c" + "mingw/misc/delay-n.c" + "mingw/misc/delayimp.c" + "mingw/misc/difftime.c" + "mingw/misc/difftime32.c" + "mingw/misc/difftime64.c" + "mingw/misc/dirent.c" + "mingw/misc/dirname.c" + "mingw/misc/execv.c" + "mingw/misc/execve.c" + "mingw/misc/execvp.c" + "mingw/misc/execvpe.c" + "mingw/misc/feclearexcept.c" + "mingw/misc/fegetenv.c" + "mingw/misc/fegetexceptflag.c" + "mingw/misc/fegetround.c" + "mingw/misc/feholdexcept.c" + "mingw/misc/feraiseexcept.c" + "mingw/misc/fesetenv.c" + "mingw/misc/fesetexceptflag.c" + "mingw/misc/fesetround.c" + "mingw/misc/fetestexcept.c" + "mingw/misc/feupdateenv.c" + "mingw/misc/ftruncate.c" + "mingw/misc/ftw.c" + "mingw/misc/ftw64.c" + "mingw/misc/fwide.c" + "mingw/misc/getlogin.c" + "mingw/misc/getopt.c" + "mingw/misc/gettimeofday.c" + "mingw/misc/imaxabs.c" + "mingw/misc/imaxdiv.c" "mingw/misc/invalid_parameter_handler.c" + "mingw/misc/isblank.c" + "mingw/misc/iswblank.c" "mingw/misc/lc_locale_func.c" + "mingw/misc/mb_wc_common.h" + "mingw/misc/mbrtowc.c" + "mingw/misc/mbsinit.c" + "mingw/misc/mempcpy.c" + "mingw/misc/mingw-aligned-malloc.c" + "mingw/misc/mingw-fseek.c" + "mingw/misc/mingw_getsp.S" + "mingw/misc/mingw_matherr.c" + "mingw/misc/mingw_mbwc_convert.c" + "mingw/misc/mingw_usleep.c" + "mingw/misc/mingw_wcstod.c" + "mingw/misc/mingw_wcstof.c" + "mingw/misc/mingw_wcstold.c" + "mingw/misc/mkstemp.c" "mingw/misc/onexit_table.c" "mingw/misc/output_format.c" "mingw/misc/purecall.c" "mingw/misc/register_tls_atexit.c" + "mingw/misc/seterrno.c" + "mingw/misc/sleep.c" + "mingw/misc/spawnv.c" + "mingw/misc/spawnve.c" + "mingw/misc/spawnvp.c" + "mingw/misc/spawnvpe.c" + "mingw/misc/strnlen.c" + "mingw/misc/strsafe.c" + "mingw/misc/strtoimax.c" + "mingw/misc/strtold.c" + "mingw/misc/strtoumax.c" + "mingw/misc/tdelete.c" + "mingw/misc/tfind.c" + "mingw/misc/tsearch.c" + "mingw/misc/twalk.c" + "mingw/misc/uchar_c16rtomb.c" + "mingw/misc/uchar_c32rtomb.c" + "mingw/misc/uchar_mbrtoc16.c" + "mingw/misc/uchar_mbrtoc32.c" + "mingw/misc/wassert.c" + "mingw/misc/wcrtomb.c" + "mingw/misc/wcsnlen.c" + "mingw/misc/wcstof.c" + "mingw/misc/wcstoimax.c" + "mingw/misc/wcstold.c" + "mingw/misc/wcstoumax.c" + "mingw/misc/wctob.c" + "mingw/misc/wctrans.c" + "mingw/misc/wctype.c" + "mingw/misc/wdirent.c" + "mingw/misc/winbs_uint64.c" + "mingw/misc/winbs_ulong.c" + "mingw/misc/winbs_ushort.c" + "mingw/misc/wmemchr.c" + "mingw/misc/wmemcmp.c" + "mingw/misc/wmemcpy.c" + "mingw/misc/wmemmove.c" + "mingw/misc/wmempcpy.c" + "mingw/misc/wmemset.c" "mingw/secapi/_access_s.c" "mingw/secapi/_cgets_s.c" "mingw/secapi/_cgetws_s.c" @@ -7677,8 +8096,91 @@ set(ZIG_LIBC_FILES "mingw/secapi/vsprintf_s.c" "mingw/secapi/wmemcpy_s.c" "mingw/secapi/wmemmove_s.c" + "mingw/stdio/_Exit.c" + "mingw/stdio/_findfirst64i32.c" + "mingw/stdio/_findnext64i32.c" + "mingw/stdio/_fstat.c" + "mingw/stdio/_fstat64i32.c" + "mingw/stdio/_ftime.c" + "mingw/stdio/_getc_nolock.c" + "mingw/stdio/_getwc_nolock.c" + "mingw/stdio/_putc_nolock.c" + "mingw/stdio/_putwc_nolock.c" + "mingw/stdio/_stat.c" + "mingw/stdio/_stat64i32.c" + "mingw/stdio/_wfindfirst64i32.c" + "mingw/stdio/_wfindnext64i32.c" + "mingw/stdio/_wstat.c" + "mingw/stdio/_wstat64i32.c" "mingw/stdio/acrt_iob_func.c" + "mingw/stdio/asprintf.c" + "mingw/stdio/atoll.c" + "mingw/stdio/fgetpos64.c" + "mingw/stdio/fopen64.c" + "mingw/stdio/fseeko32.c" + "mingw/stdio/fseeko64.c" + "mingw/stdio/fsetpos64.c" + "mingw/stdio/ftello.c" + "mingw/stdio/ftello64.c" + "mingw/stdio/ftruncate64.c" + "mingw/stdio/lltoa.c" + "mingw/stdio/lltow.c" + "mingw/stdio/lseek64.c" + "mingw/stdio/mingw_asprintf.c" + "mingw/stdio/mingw_fprintf.c" + "mingw/stdio/mingw_fprintfw.c" + "mingw/stdio/mingw_fscanf.c" + "mingw/stdio/mingw_fwscanf.c" "mingw/stdio/mingw_lock.c" + "mingw/stdio/mingw_pformat.c" + "mingw/stdio/mingw_pformat.h" + "mingw/stdio/mingw_pformatw.c" + "mingw/stdio/mingw_printf.c" + "mingw/stdio/mingw_printfw.c" + "mingw/stdio/mingw_scanf.c" + "mingw/stdio/mingw_snprintf.c" + "mingw/stdio/mingw_snprintfw.c" + "mingw/stdio/mingw_sprintf.c" + "mingw/stdio/mingw_sprintfw.c" + "mingw/stdio/mingw_sscanf.c" + "mingw/stdio/mingw_swscanf.c" + "mingw/stdio/mingw_vasprintf.c" + "mingw/stdio/mingw_vfprintf.c" + "mingw/stdio/mingw_vfprintfw.c" + "mingw/stdio/mingw_vfscanf.c" + "mingw/stdio/mingw_vprintf.c" + "mingw/stdio/mingw_vprintfw.c" + "mingw/stdio/mingw_vsnprintf.c" + "mingw/stdio/mingw_vsnprintfw.c" + "mingw/stdio/mingw_vsprintf.c" + "mingw/stdio/mingw_vsprintfw.c" + "mingw/stdio/mingw_wscanf.c" + "mingw/stdio/mingw_wvfscanf.c" + "mingw/stdio/scanf.S" + "mingw/stdio/scanf2-template.S" + "mingw/stdio/snprintf.c" + "mingw/stdio/snwprintf.c" + "mingw/stdio/strtof.c" + "mingw/stdio/strtok_r.c" + "mingw/stdio/truncate.c" + "mingw/stdio/ulltoa.c" + "mingw/stdio/ulltow.c" + "mingw/stdio/vasprintf.c" + "mingw/stdio/vfscanf.c" + "mingw/stdio/vfscanf2.S" + "mingw/stdio/vfwscanf.c" + "mingw/stdio/vfwscanf2.S" + "mingw/stdio/vscanf.c" + "mingw/stdio/vscanf2.S" + "mingw/stdio/vsnprintf.c" + "mingw/stdio/vsnwprintf.c" + "mingw/stdio/vsscanf.c" + "mingw/stdio/vsscanf2.S" + "mingw/stdio/vswscanf.c" + "mingw/stdio/vswscanf2.S" + "mingw/stdio/vwscanf.c" + "mingw/stdio/vwscanf2.S" + "mingw/stdio/wtoll.c" "musl/arch/aarch64/atomic_arch.h" "musl/arch/aarch64/bits/alltypes.h.in" "musl/arch/aarch64/bits/endian.h" diff --git a/libc/mingw/complex/_cabs.c b/libc/mingw/complex/_cabs.c new file mode 100644 index 000000000..736e788c2 --- /dev/null +++ b/libc/mingw/complex/_cabs.c @@ -0,0 +1,61 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +/* We implement this function to make sure we use always the C99 compatible + routine. By this we fix an issue about 32-bit and 64-bit version of + msvcrt, which differs in some corner-cases. */ + +double __cdecl +_cabs (struct _complex _ComplexA) +{ + double _Complex a; + + __real__ a = _ComplexA.x; + __imag__ a = _ComplexA.y; + + return cabs (a); +} diff --git a/libc/mingw/complex/cabs.c b/libc/mingw/complex/cabs.c new file mode 100644 index 000000000..81eb7a15e --- /dev/null +++ b/libc/mingw/complex/cabs.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "cabs.def.h" diff --git a/libc/mingw/complex/cabs.def.h b/libc/mingw/complex/cabs.def.h new file mode 100644 index 000000000..b3ea09764 --- /dev/null +++ b/libc/mingw/complex/cabs.def.h @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __cdecl +__FLT_ABI(cabs) (__FLT_TYPE __complex__ z) +{ + return __FLT_ABI(hypot) (__real__ z, __imag__ z); +} diff --git a/libc/mingw/complex/cabsf.c b/libc/mingw/complex/cabsf.c new file mode 100644 index 000000000..ad2992117 --- /dev/null +++ b/libc/mingw/complex/cabsf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "cabs.def.h" diff --git a/libc/mingw/complex/cabsl.c b/libc/mingw/complex/cabsl.c new file mode 100644 index 000000000..c750e877d --- /dev/null +++ b/libc/mingw/complex/cabsl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "cabs.def.h" diff --git a/libc/mingw/complex/cacos.c b/libc/mingw/complex/cacos.c new file mode 100644 index 000000000..dbeb0b6d1 --- /dev/null +++ b/libc/mingw/complex/cacos.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" + +#include "cacosh.def.h" +#include "cacos.def.h" diff --git a/libc/mingw/complex/cacos.def.h b/libc/mingw/complex/cacos.def.h new file mode 100644 index 000000000..300faffac --- /dev/null +++ b/libc/mingw/complex/cacos.def.h @@ -0,0 +1,57 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(cacos) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE x; + __complex__ __FLT_TYPE ret; + + x = __FLT_ABI(casin) (z); + + __real__ ret = (__FLT_TYPE) __FLT_PI_2 - __real__ x; + __imag__ ret = -__imag__ x; + + return ret; +} diff --git a/libc/mingw/complex/cacosf.c b/libc/mingw/complex/cacosf.c new file mode 100644 index 000000000..eba04efb2 --- /dev/null +++ b/libc/mingw/complex/cacosf.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" + +#include "cacosh.def.h" +#include "cacos.def.h" diff --git a/libc/mingw/complex/cacosh.def.h b/libc/mingw/complex/cacosh.def.h new file mode 100644 index 000000000..f4ea2da07 --- /dev/null +++ b/libc/mingw/complex/cacosh.def.h @@ -0,0 +1,100 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(cacosh) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __complex__ __FLT_TYPE x; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (i_class == FP_INFINITE) + { + __real__ ret = __FLT_HUGE_VAL; + __imag__ ret = (r_class == FP_NAN ? __FLT_NAN : __FLT_ABI(copysign) ( + (r_class == FP_INFINITE ? (__real__ z < __FLT_CST(0.0) ? __FLT_PI_3_4 : __FLT_PI_4) : __FLT_PI_2), __imag__ z)); + return ret; + } + + if (r_class == FP_INFINITE) + { + __real__ ret = __FLT_HUGE_VAL; + __imag__ ret = ((i_class != FP_NAN && i_class != FP_INFINITE) + ? __FLT_ABI(copysign) (signbit (__real__ z) ? __FLT_PI : __FLT_CST(0.0), __imag__ z) : __FLT_NAN); + return ret; + } + + if (r_class == FP_NAN || i_class == FP_NAN) + { + __real__ ret = __FLT_NAN; + __imag__ ret = __FLT_NAN; + return ret; + } + + if (r_class == FP_ZERO && i_class == FP_ZERO) + { + __real__ ret = __FLT_CST(0.0); + __imag__ ret = __FLT_ABI(copysign) (__FLT_PI_2, __imag__ z); + return ret; + } + + __real__ x = (__real__ z - __imag__ z) * (__real__ z + __imag__ z) - __FLT_CST(1.0); + __imag__ x = __FLT_CST(2.0) * __real__ z * __imag__ z; + + x = __FLT_ABI(csqrt) (x); + + if (__real__ z < __FLT_CST(0.0)) + x = -x; + + __real__ x += __real__ z; + __imag__ x += __imag__ z; + + ret = __FLT_ABI(clog) (x); + + if (__real__ ret < __FLT_CST(0.0)) + ret = -ret; + + return ret; +} diff --git a/libc/mingw/complex/cacosl.c b/libc/mingw/complex/cacosl.c new file mode 100644 index 000000000..7a8df652d --- /dev/null +++ b/libc/mingw/complex/cacosl.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" + +#include "cacosh.def.h" +#include "cacos.def.h" diff --git a/libc/mingw/complex/carg.c b/libc/mingw/complex/carg.c new file mode 100644 index 000000000..76354aa80 --- /dev/null +++ b/libc/mingw/complex/carg.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "carg.def.h" diff --git a/libc/mingw/complex/carg.def.h b/libc/mingw/complex/carg.def.h new file mode 100644 index 000000000..2ccf84189 --- /dev/null +++ b/libc/mingw/complex/carg.def.h @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __cdecl +__FLT_ABI(carg) (__FLT_TYPE __complex__ z) +{ + return __FLT_ABI(atan2) (__imag__ z, __real__ z); +} diff --git a/libc/mingw/complex/cargf.c b/libc/mingw/complex/cargf.c new file mode 100644 index 000000000..e1fe90496 --- /dev/null +++ b/libc/mingw/complex/cargf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "carg.def.h" diff --git a/libc/mingw/complex/cargl.c b/libc/mingw/complex/cargl.c new file mode 100644 index 000000000..e70f580ea --- /dev/null +++ b/libc/mingw/complex/cargl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "carg.def.h" diff --git a/libc/mingw/complex/casin.c b/libc/mingw/complex/casin.c new file mode 100644 index 000000000..b6075312c --- /dev/null +++ b/libc/mingw/complex/casin.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" + +#include "casinh.def.h" +#include "casin.def.h" diff --git a/libc/mingw/complex/casin.def.h b/libc/mingw/complex/casin.def.h new file mode 100644 index 000000000..808c1bef0 --- /dev/null +++ b/libc/mingw/complex/casin.def.h @@ -0,0 +1,61 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(casin) (__FLT_TYPE __complex__ z) +{ + /* Annex G.6: casin(z) = -i casinh (iz) */ + __complex__ __FLT_TYPE ret; + __complex__ __FLT_TYPE x; + + __real__ x = -__imag__ z; + __imag__ x = __real__ z; + + x = __FLT_ABI(casinh) (x); + + __real__ ret = __imag__ x; + __imag__ ret = -__real__ x; + + return ret; +} diff --git a/libc/mingw/complex/casinf.c b/libc/mingw/complex/casinf.c new file mode 100644 index 000000000..5f495a27d --- /dev/null +++ b/libc/mingw/complex/casinf.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" + +#include "casinh.def.h" +#include "casin.def.h" diff --git a/libc/mingw/complex/casinh.def.h b/libc/mingw/complex/casinh.def.h new file mode 100644 index 000000000..050d885a0 --- /dev/null +++ b/libc/mingw/complex/casinh.def.h @@ -0,0 +1,99 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(casinh) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __complex__ __FLT_TYPE x; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (i_class == FP_INFINITE) + { + __real__ ret = __FLT_ABI(copysign) (__FLT_HUGE_VAL, __real__ z); + __imag__ ret = (r_class == FP_NAN + ? __FLT_NAN + : (__FLT_ABI(copysign) ((r_class != FP_NAN && r_class != FP_INFINITE) ? __FLT_PI_2 : __FLT_PI_4, __imag__ z))); + return ret; + } + + if (r_class == FP_INFINITE) + { + __real__ ret = __real__ z; + __imag__ ret = (i_class != FP_NAN + ? __FLT_ABI(copysign) (__FLT_CST(0.0), __imag__ z) + : __FLT_NAN); + return ret; + } + + if (r_class == FP_NAN) + { + __real__ ret = __real__ z; + __imag__ ret = (i_class == FP_ZERO + ? __FLT_ABI(copysign) (__FLT_CST(0.0), __imag__ z) + : __FLT_NAN); + return ret; + } + + if (i_class == FP_NAN) + { + __real__ ret = __FLT_NAN; + __imag__ ret = __FLT_NAN; + return ret; + } + + if (r_class == FP_ZERO && i_class == FP_ZERO) + return z; + + __real__ x = (__real__ z - __imag__ z) * (__real__ z + __imag__ z) + __FLT_CST(1.0); + __imag__ x = __FLT_CST(2.0) * __real__ z * __imag__ z; + + x = __FLT_ABI(csqrt) (x); + + __real__ x += __real__ z; + __imag__ x += __imag__ z; + + return __FLT_ABI(clog) (x); +} diff --git a/libc/mingw/complex/casinl.c b/libc/mingw/complex/casinl.c new file mode 100644 index 000000000..1d7e24785 --- /dev/null +++ b/libc/mingw/complex/casinl.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" + +#include "casinh.def.h" +#include "casin.def.h" diff --git a/libc/mingw/complex/catan.c b/libc/mingw/complex/catan.c new file mode 100644 index 000000000..a3c180442 --- /dev/null +++ b/libc/mingw/complex/catan.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" + +#include "catanh.def.h" +#include "catan.def.h" diff --git a/libc/mingw/complex/catan.def.h b/libc/mingw/complex/catan.def.h new file mode 100644 index 000000000..19db6b78b --- /dev/null +++ b/libc/mingw/complex/catan.def.h @@ -0,0 +1,61 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(catan) (__FLT_TYPE __complex__ z) +{ + /* Annex G.6: catan(z) = -i catanh (iz) */ + __complex__ __FLT_TYPE ret; + __complex__ __FLT_TYPE x; + + __real__ x = -__imag__ z; + __imag__ x = __real__ z; + + x = __FLT_ABI(catanh) (x); + + __real__ ret = __imag__ x; + __imag__ ret = -__real__ x; + + return ret; +} diff --git a/libc/mingw/complex/catanf.c b/libc/mingw/complex/catanf.c new file mode 100644 index 000000000..1a71ce3d6 --- /dev/null +++ b/libc/mingw/complex/catanf.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" + +#include "catanh.def.h" +#include "catan.def.h" diff --git a/libc/mingw/complex/catanh.def.h b/libc/mingw/complex/catanh.def.h new file mode 100644 index 000000000..68949d139 --- /dev/null +++ b/libc/mingw/complex/catanh.def.h @@ -0,0 +1,93 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(catanh) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __FLT_TYPE i2, n, d; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (r_class == FP_INFINITE || r_class == FP_NAN || i_class == FP_INFINITE || i_class == FP_NAN) + { + if (i_class == FP_INFINITE) + { + __real__ ret = __FLT_ABI(copysign) (__FLT_CST(0.0), __real__ z); + __imag__ ret = __FLT_ABI(copysign) (__FLT_PI_2, __imag__ z); + return ret; + } + + if (r_class == FP_INFINITE || r_class == FP_ZERO) + { + __real__ ret = __FLT_ABI(copysign) (__FLT_CST(0.0), __real__ z); + __imag__ ret = ((i_class != FP_NAN && i_class != FP_INFINITE) + ? __FLT_ABI(copysign) (__FLT_PI_2, __imag__ z) : __FLT_NAN); + return ret; + } + + __real__ ret = __FLT_NAN; + __imag__ ret = __FLT_NAN; + return ret; + } + + if (r_class == FP_ZERO && i_class == FP_ZERO) + return z; + + i2 = __imag__ z * __imag__ z; + + n = __FLT_CST(1.0) + __real__ z; + n = i2 + n * n; + + d = __FLT_CST(1.0) - __real__ z; + d = i2 + d * d; + + __real__ ret = __FLT_CST(0.25) * (__FLT_ABI(log) (n) - __FLT_ABI(log) (d)); + + d = 1 - __real__ z * __real__ z - i2; + + __imag__ ret = __FLT_CST(0.5) * __FLT_ABI(atan2) (__FLT_CST(2.0) * __imag__ z, d); + + return ret; +} diff --git a/libc/mingw/complex/catanl.c b/libc/mingw/complex/catanl.c new file mode 100644 index 000000000..9c1ccdfcb --- /dev/null +++ b/libc/mingw/complex/catanl.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" + +#include "catanh.def.h" +#include "catan.def.h" diff --git a/libc/mingw/complex/ccos.c b/libc/mingw/complex/ccos.c new file mode 100644 index 000000000..fb7f3567e --- /dev/null +++ b/libc/mingw/complex/ccos.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" + +#include "ccosh.def.h" +#include "ccos.def.h" diff --git a/libc/mingw/complex/ccos.def.h b/libc/mingw/complex/ccos.def.h new file mode 100644 index 000000000..2e7472cd9 --- /dev/null +++ b/libc/mingw/complex/ccos.def.h @@ -0,0 +1,54 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(ccos) (__FLT_TYPE __complex__ z) +{ + /* Annex G.6, ccos(z) = ccosh(iz) */ + __complex__ __FLT_TYPE x; + __real__ x = -__imag__ z; + __imag__ x = __real__ z; + + return __FLT_ABI(ccosh) (x); +} diff --git a/libc/mingw/complex/ccosf.c b/libc/mingw/complex/ccosf.c new file mode 100644 index 000000000..3089f6071 --- /dev/null +++ b/libc/mingw/complex/ccosf.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" + +#include "ccosh.def.h" +#include "ccos.def.h" diff --git a/libc/mingw/complex/ccosh.def.h b/libc/mingw/complex/ccosh.def.h new file mode 100644 index 000000000..c18d657bf --- /dev/null +++ b/libc/mingw/complex/ccosh.def.h @@ -0,0 +1,95 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(ccosh) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __FLT_TYPE s_x, c_x; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (r_class == FP_NAN) + { + __real__ ret = __FLT_NAN; + __imag__ ret = __imag__ z == __FLT_CST(0.0) ? __imag__ z : __FLT_NAN; + return ret; + } + + if (r_class == FP_INFINITE) + { + if (i_class == FP_ZERO) + { + __real__ ret = __FLT_HUGE_VAL; + __imag__ ret = __imag__ z * __FLT_ABI(copysign) (__FLT_CST(1.0), __real__ z); + return ret; + } + + if (i_class == FP_NAN || i_class == FP_INFINITE) + { + __real__ ret = __FLT_HUGE_VAL; + __imag__ ret = __FLT_NAN + __FLT_NAN; + return ret; + } + + __FLT_ABI(sincos) (__imag__ z, &s_x, &c_x); + + __real__ ret = __FLT_ABI(copysign) (__FLT_HUGE_VAL, c_x); + __imag__ ret = (__FLT_ABI(copysign) (__FLT_HUGE_VAL, s_x) * __FLT_ABI(copysign) (__FLT_CST(1.0), __real__ z)); + return ret; + } + + if (i_class == FP_NAN || i_class == FP_INFINITE) + { + __imag__ ret = __real__ z == __FLT_CST(0.0) ? __FLT_CST(0.0) : __FLT_NAN; + __real__ ret = __FLT_NAN + __FLT_NAN; + return ret; + } + + __FLT_ABI(sincos) (__imag__ z, &s_x, &c_x); + + __real__ ret = __FLT_ABI(cosh) (__real__ z) * c_x; + __imag__ ret = __FLT_ABI(sinh) (__real__ z) * s_x; + return ret; +} diff --git a/libc/mingw/complex/ccosl.c b/libc/mingw/complex/ccosl.c new file mode 100644 index 000000000..594a4d1de --- /dev/null +++ b/libc/mingw/complex/ccosl.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" + +#include "ccosh.def.h" +#include "ccos.def.h" diff --git a/libc/mingw/complex/cexp.c b/libc/mingw/complex/cexp.c new file mode 100644 index 000000000..154fa89ce --- /dev/null +++ b/libc/mingw/complex/cexp.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "cexp.def.h" diff --git a/libc/mingw/complex/cexp.def.h b/libc/mingw/complex/cexp.def.h new file mode 100644 index 000000000..c0c97b70f --- /dev/null +++ b/libc/mingw/complex/cexp.def.h @@ -0,0 +1,111 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(cexp) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __FLT_TYPE s_x, c_x, exp_val, v; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (r_class == FP_INFINITE) + { + if (i_class != FP_NAN && i_class != FP_INFINITE) + { + v = signbit (__real__ z) ? __FLT_CST(0.0) : __FLT_HUGE_VAL; + + if (i_class == FP_ZERO) + { + __real__ ret = v; + __imag__ ret = __imag__ z; + return ret; + } + + __FLT_ABI(sincos) (__imag__ z, &s_x, &c_x); + + __real__ ret = __FLT_ABI(copysign) (v, c_x); + __imag__ ret = __FLT_ABI(copysign) (v, s_x); + return ret; + } + + if (signbit (__real__ z) == 0) + { + __real__ ret = __FLT_HUGE_VAL; + __imag__ ret = __FLT_NAN; + } + else + { + __real__ ret = __FLT_CST(0.0); + __imag__ ret = __FLT_ABI(copysign) (__FLT_CST(0.0), __imag__ z); + } + return ret; + } + + if (r_class == FP_NAN || i_class == FP_NAN || i_class == FP_INFINITE) + { + __real__ ret = __FLT_NAN; + if (i_class == FP_ZERO) + __imag__ ret = __FLT_ABI(copysign) (__FLT_CST(0.0), __imag__ z); + else + __imag__ ret = __FLT_NAN; + return ret; + } + + exp_val = __FLT_ABI(exp) (__real__ z); + + __FLT_ABI(sincos) (__imag__ z, &s_x, &c_x); + + if (isfinite (exp_val)) + { + __real__ ret = exp_val * c_x; + __imag__ ret = exp_val * s_x; + } + else + { + __real__ ret = __FLT_ABI(copysign) (exp_val, c_x); + __imag__ ret = __FLT_ABI(copysign) (exp_val, s_x); + } + return ret; +} diff --git a/libc/mingw/complex/cexpf.c b/libc/mingw/complex/cexpf.c new file mode 100644 index 000000000..5ab6c3824 --- /dev/null +++ b/libc/mingw/complex/cexpf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "cexp.def.h" diff --git a/libc/mingw/complex/cexpl.c b/libc/mingw/complex/cexpl.c new file mode 100644 index 000000000..9c33bc05c --- /dev/null +++ b/libc/mingw/complex/cexpl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "cexp.def.h" diff --git a/libc/mingw/complex/cimag.c b/libc/mingw/complex/cimag.c new file mode 100644 index 000000000..0b196b149 --- /dev/null +++ b/libc/mingw/complex/cimag.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "cimag.def.h" diff --git a/libc/mingw/complex/cimag.def.h b/libc/mingw/complex/cimag.def.h new file mode 100644 index 000000000..0212d9390 --- /dev/null +++ b/libc/mingw/complex/cimag.def.h @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __cdecl +__FLT_ABI(cimag) (__FLT_TYPE __complex z) +{ + return __imag__ z; +} diff --git a/libc/mingw/complex/cimagf.c b/libc/mingw/complex/cimagf.c new file mode 100644 index 000000000..a96db3b03 --- /dev/null +++ b/libc/mingw/complex/cimagf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "cimag.def.h" diff --git a/libc/mingw/complex/cimagl.c b/libc/mingw/complex/cimagl.c new file mode 100644 index 000000000..94835d745 --- /dev/null +++ b/libc/mingw/complex/cimagl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "cimag.def.h" diff --git a/libc/mingw/complex/clog.c b/libc/mingw/complex/clog.c new file mode 100644 index 000000000..36ebb9178 --- /dev/null +++ b/libc/mingw/complex/clog.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "clog.def.h" diff --git a/libc/mingw/complex/clog.def.h b/libc/mingw/complex/clog.def.h new file mode 100644 index 000000000..604c3f321 --- /dev/null +++ b/libc/mingw/complex/clog.def.h @@ -0,0 +1,71 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(clog) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (r_class == FP_ZERO && i_class == FP_ZERO) + { + __imag__ ret = signbit (__real__ z) ? __FLT_PI : __FLT_CST(0.0); + __imag__ ret = __FLT_ABI(copysign) (__imag__ ret, __imag__ z); + __real__ ret = -__FLT_CST(1.0) / __FLT_ABI(fabs) (__real__ z); + return ret; + } + + if (r_class == FP_NAN || i_class == FP_NAN) + { + __imag__ ret = __FLT_NAN; + __real__ ret = ((r_class == FP_INFINITE || i_class == FP_INFINITE) ? __FLT_HUGE_VAL : __FLT_NAN); + + return ret; + } + + __real__ ret = __FLT_ABI(log) (__FLT_ABI(hypot) (__real__ z, __imag__ z)); + __imag__ ret = __FLT_ABI(atan2) (__imag__ z, __real__ z); + return ret; +} diff --git a/libc/mingw/complex/clog10.c b/libc/mingw/complex/clog10.c new file mode 100644 index 000000000..8553e00e6 --- /dev/null +++ b/libc/mingw/complex/clog10.c @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#define _GNU_SOURCE +#include "complex_internal.h" +#include "clog10.def.h" diff --git a/libc/mingw/complex/clog10.def.h b/libc/mingw/complex/clog10.def.h new file mode 100644 index 000000000..cdd4eb6b5 --- /dev/null +++ b/libc/mingw/complex/clog10.def.h @@ -0,0 +1,71 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(clog10) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (r_class == FP_ZERO && i_class == FP_ZERO) + { + __imag__ ret = signbit (__real__ z) ? __FLT_PI : __FLT_CST(0.0); + __imag__ ret = __FLT_ABI(copysign) (__imag__ ret, __imag__ z); + __real__ ret = -__FLT_CST(1.0) / __FLT_ABI(fabs) (__real__ z); + return ret; + } + + if (r_class == FP_NAN || i_class == FP_NAN) + { + __imag__ ret = __FLT_NAN; + __real__ ret = ((r_class == FP_INFINITE || i_class == FP_INFINITE) ? __FLT_HUGE_VAL : __FLT_NAN); + + return ret; + } + + __real__ ret = __FLT_ABI(log10) (__FLT_ABI(hypot) (__real__ z, __imag__ z)); + __imag__ ret = __FLT_LOG10E * __FLT_ABI(atan2) (__imag__ z, __real__ z); + return ret; +} diff --git a/libc/mingw/complex/clog10f.c b/libc/mingw/complex/clog10f.c new file mode 100644 index 000000000..8ce97d32d --- /dev/null +++ b/libc/mingw/complex/clog10f.c @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#define _GNU_SOURCE +#include "complex_internal.h" +#include "clog10.def.h" diff --git a/libc/mingw/complex/clog10l.c b/libc/mingw/complex/clog10l.c new file mode 100644 index 000000000..11d85c79a --- /dev/null +++ b/libc/mingw/complex/clog10l.c @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#define _GNU_SOURCE +#include "complex_internal.h" +#include "clog10.def.h" diff --git a/libc/mingw/complex/clogf.c b/libc/mingw/complex/clogf.c new file mode 100644 index 000000000..87c407c54 --- /dev/null +++ b/libc/mingw/complex/clogf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "clog.def.h" diff --git a/libc/mingw/complex/clogl.c b/libc/mingw/complex/clogl.c new file mode 100644 index 000000000..383fcfa0f --- /dev/null +++ b/libc/mingw/complex/clogl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "clog.def.h" diff --git a/libc/mingw/complex/complex_internal.h b/libc/mingw/complex/complex_internal.h new file mode 100644 index 000000000..cd23c0af1 --- /dev/null +++ b/libc/mingw/complex/complex_internal.h @@ -0,0 +1,128 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include + +/* Define some PI constants for long double, as they are not defined in math.h */ +#ifndef M_PI_4l +#define M_PI_4l 0.7853981633974483096156608458198757L +#define M_PI_2l 1.5707963267948966192313216916397514L +#define M_PIl 3.1415926535897932384626433832795029L +#endif + +/* NAN builtins for gcc, as they are not part of math.h */ +#ifndef NANF +#define NANF __builtin_nanf ("") +#endif +#ifndef NANL +#define NANL __builtin_nanl ("") +#endif + +/* Some more helpers. */ +#define M_PI_3_4 (M_PI - M_PI_4) +#define M_PI_3_4l (M_PIl - M_PI_4l) + +#if defined(_NEW_COMPLEX_FLOAT) +# define __FLT_TYPE float +# define __FLT_ABI(N) N##f +# define __FLT_CST(N) N##F +# define __FLT_EPSILON __FLT_EPSILON__ +# define __FLT_NAN NANF +# define __FLT_HUGE_VAL HUGE_VALF +# define __FLT_PI M_PI +# define __FLT_PI_2 M_PI_2 +# define __FLT_PI_4 M_PI_4 +# define __FLT_PI_3_4 M_PI_3_4 +# define __FLT_MAXLOG 88.72283905206835F +# define __FLT_MINLOG -103.278929903431851103F +# define __FLT_LOGE2 0.693147180559945309F +# define __FLT_LOG10E 0.434294481903251828F +# define __FLT_REPORT(NAME) NAME "f" +#elif defined(_NEW_COMPLEX_DOUBLE) +# define __FLT_TYPE double +# define __FLT_ABI(N) N +# define __FLT_EPSILON __DBL_EPSILON__ +# define __FLT_CST(N) N +# define __FLT_NAN NAN +# define __FLT_HUGE_VAL HUGE_VAL +# define __FLT_PI M_PI +# define __FLT_PI_2 M_PI_2 +# define __FLT_PI_4 M_PI_4 +# define __FLT_PI_3_4 M_PI_3_4 +# define __FLT_MAXLOG 7.09782712893383996843E2 +# define __FLT_MINLOG -7.45133219101941108420E2 +# define __FLT_LOGE2 6.93147180559945309417E-1 +# define __FLT_LOG10E 4.34294481903251827651E-1 +# define __FLT_REPORT(NAME) NAME +#elif defined(_NEW_COMPLEX_LDOUBLE) +# define __FLT_TYPE long double +# define __FLT_ABI(N) N##l +# define __FLT_CST(N) N##L +# define __FLT_EPSILON __LDBL_EPSILON__ +# define __FLT_NAN NANL +# define __FLT_HUGE_VAL HUGE_VALL +# define __FLT_PI M_PIl +# define __FLT_PI_2 M_PI_2l +# define __FLT_PI_4 M_PI_4l +# define __FLT_PI_3_4 M_PI_3_4l +# define __FLT_MAXLOG 1.1356523406294143949492E4L +# define __FLT_MINLOG -1.1355137111933024058873E4L +# define __FLT_LOGE2 6.9314718055994530941723E-1L +# define __FLT_LOG10E 4.3429448190325182765113E-1L +# define __FLT_REPORT(NAME) NAME "l" +#else +# error "Unknown complex number type" +#endif + +#define __FLT_RPT_DOMAIN(NAME, ARG1, ARG2, RSLT) \ + errno = EDOM, \ + __mingw_raise_matherr (_DOMAIN, __FLT_REPORT(NAME), (double) (ARG1), \ + (double) (ARG2), (double) (RSLT)) +#define __FLT_RPT_ERANGE(NAME, ARG1, ARG2, RSLT, OVL) \ + errno = ERANGE, \ + __mingw_raise_matherr (((OVL) ? _OVERFLOW : _UNDERFLOW), \ + __FLT_REPORT(NAME), (double) (ARG1), \ + (double) (ARG2), (double) (RSLT)) + diff --git a/libc/mingw/complex/conj.c b/libc/mingw/complex/conj.c new file mode 100644 index 000000000..be9d8fe35 --- /dev/null +++ b/libc/mingw/complex/conj.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "conj.def.h" diff --git a/libc/mingw/complex/conj.def.h b/libc/mingw/complex/conj.def.h new file mode 100644 index 000000000..35fa8989d --- /dev/null +++ b/libc/mingw/complex/conj.def.h @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(conj) (__FLT_TYPE __complex__ z) +{ + return ~z; +} diff --git a/libc/mingw/complex/conjf.c b/libc/mingw/complex/conjf.c new file mode 100644 index 000000000..1ac7cc453 --- /dev/null +++ b/libc/mingw/complex/conjf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "conj.def.h" diff --git a/libc/mingw/complex/conjl.c b/libc/mingw/complex/conjl.c new file mode 100644 index 000000000..52e32e65a --- /dev/null +++ b/libc/mingw/complex/conjl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "conj.def.h" diff --git a/libc/mingw/complex/cpow.c b/libc/mingw/complex/cpow.c new file mode 100644 index 000000000..53b7df422 --- /dev/null +++ b/libc/mingw/complex/cpow.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "cpow.def.h" diff --git a/libc/mingw/complex/cpow.def.h b/libc/mingw/complex/cpow.def.h new file mode 100644 index 000000000..984224b96 --- /dev/null +++ b/libc/mingw/complex/cpow.def.h @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(cpow) (__FLT_TYPE __complex__ z, __FLT_TYPE __complex__ x) +{ + return __FLT_ABI(cexp) (x * __FLT_ABI(clog) (z)); +} diff --git a/libc/mingw/complex/cpowf.c b/libc/mingw/complex/cpowf.c new file mode 100644 index 000000000..7930fad3e --- /dev/null +++ b/libc/mingw/complex/cpowf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "cpow.def.h" diff --git a/libc/mingw/complex/cpowl.c b/libc/mingw/complex/cpowl.c new file mode 100644 index 000000000..42edb7996 --- /dev/null +++ b/libc/mingw/complex/cpowl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "cpow.def.h" diff --git a/libc/mingw/complex/cproj.c b/libc/mingw/complex/cproj.c new file mode 100644 index 000000000..e90b9bee7 --- /dev/null +++ b/libc/mingw/complex/cproj.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "cproj.def.h" diff --git a/libc/mingw/complex/cproj.def.h b/libc/mingw/complex/cproj.def.h new file mode 100644 index 000000000..e15d779f7 --- /dev/null +++ b/libc/mingw/complex/cproj.def.h @@ -0,0 +1,58 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(cproj) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + + if (isinf (__real__ z) || isinf (__imag__ z)) + { + __real__ ret = INFINITY; + __imag__ ret = __FLT_ABI(copysign) (__FLT_CST(0.0), __imag__ z); + return ret; + } + + return z; +} diff --git a/libc/mingw/complex/cprojf.c b/libc/mingw/complex/cprojf.c new file mode 100644 index 000000000..b928effde --- /dev/null +++ b/libc/mingw/complex/cprojf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "cproj.def.h" diff --git a/libc/mingw/complex/cprojl.c b/libc/mingw/complex/cprojl.c new file mode 100644 index 000000000..d48d10877 --- /dev/null +++ b/libc/mingw/complex/cprojl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "cproj.def.h" diff --git a/libc/mingw/complex/creal.c b/libc/mingw/complex/creal.c new file mode 100644 index 000000000..8961d3a31 --- /dev/null +++ b/libc/mingw/complex/creal.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "creal.def.h" diff --git a/libc/mingw/complex/creal.def.h b/libc/mingw/complex/creal.def.h new file mode 100644 index 000000000..554c99d8c --- /dev/null +++ b/libc/mingw/complex/creal.def.h @@ -0,0 +1,49 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE +__FLT_ABI(creal) (__FLT_TYPE __complex__ z) +{ + return __real__ z; +} diff --git a/libc/mingw/complex/crealf.c b/libc/mingw/complex/crealf.c new file mode 100644 index 000000000..73be9ad51 --- /dev/null +++ b/libc/mingw/complex/crealf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "creal.def.h" diff --git a/libc/mingw/complex/creall.c b/libc/mingw/complex/creall.c new file mode 100644 index 000000000..e46c8ea37 --- /dev/null +++ b/libc/mingw/complex/creall.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "creal.def.h" diff --git a/libc/mingw/complex/csin.c b/libc/mingw/complex/csin.c new file mode 100644 index 000000000..2b2da6781 --- /dev/null +++ b/libc/mingw/complex/csin.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" + +#include "csinh.def.h" +#include "csin.def.h" diff --git a/libc/mingw/complex/csin.def.h b/libc/mingw/complex/csin.def.h new file mode 100644 index 000000000..cf9cfe108 --- /dev/null +++ b/libc/mingw/complex/csin.def.h @@ -0,0 +1,61 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(csin) (__FLT_TYPE __complex__ z) +{ + /* Annex G.6: csin(z) = -i csinh (iz) */ + __complex__ __FLT_TYPE ret; + __complex__ __FLT_TYPE x; + + __real__ x = -__imag__ z; + __imag__ x = __real__ z; + + x = __FLT_ABI(csinh) (x); + + __real__ ret = __imag__ x; + __imag__ ret = -__real__ x; + + return ret; +} diff --git a/libc/mingw/complex/csinf.c b/libc/mingw/complex/csinf.c new file mode 100644 index 000000000..6bad87350 --- /dev/null +++ b/libc/mingw/complex/csinf.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" + +#include "csinh.def.h" +#include "csin.def.h" diff --git a/libc/mingw/complex/csinh.def.h b/libc/mingw/complex/csinh.def.h new file mode 100644 index 000000000..3e07d2bab --- /dev/null +++ b/libc/mingw/complex/csinh.def.h @@ -0,0 +1,107 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(csinh) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __FLT_TYPE s_x, c_x; + int negate = signbit (__real__ z); + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + __real__ z = __FLT_ABI(fabs) (__real__ z); + + if (r_class == FP_NAN) + { + __real__ ret = __FLT_NAN; + __imag__ ret = __imag__ z == __FLT_CST(0.0) ? __imag__ z : __FLT_NAN; + + return ret; + } + + if (r_class == FP_INFINITE) + { + if (i_class == FP_ZERO) + { + __real__ ret = negate ? -__FLT_HUGE_VAL : __FLT_HUGE_VAL; + __imag__ ret = __imag__ z; + return ret; + } + + if (i_class == FP_NAN || i_class == FP_INFINITE) + { + __real__ ret = __FLT_HUGE_VAL; + __imag__ ret = __FLT_NAN + __FLT_NAN; + + return ret; + } + __FLT_ABI(sincos) (__imag__ z, &s_x, &c_x); + + __real__ ret = __FLT_ABI(copysign) (__FLT_HUGE_VAL, c_x); + __imag__ ret = __FLT_ABI(copysign) (__FLT_HUGE_VAL, s_x); + + if (negate) + __real__ ret = -__real__ ret; + return ret; + } + + if (i_class == FP_NAN || i_class == FP_INFINITE) + { + __real__ ret = (r_class == FP_ZERO + ? (__FLT_ABI(copysign) (__FLT_CST(0.0), negate ? -__FLT_CST(1.0) : __FLT_CST(1.0))) : __FLT_NAN); + __imag__ ret = (r_class == FP_ZERO ? (__FLT_NAN + __FLT_NAN) : __FLT_NAN); + + return ret; + } + + __FLT_ABI(sincos) (__imag__ z, &s_x, &c_x); + + __real__ ret = __FLT_ABI(sinh) (__real__ z) * c_x; + __imag__ ret = __FLT_ABI(cosh) (__real__ z) * s_x; + + if (negate) + __real__ ret = -__real__ ret; + return ret; +} diff --git a/libc/mingw/complex/csinl.c b/libc/mingw/complex/csinl.c new file mode 100644 index 000000000..de04104c8 --- /dev/null +++ b/libc/mingw/complex/csinl.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" + +#include "csinh.def.h" +#include "csin.def.h" diff --git a/libc/mingw/complex/csqrt.c b/libc/mingw/complex/csqrt.c new file mode 100644 index 000000000..83599a0ba --- /dev/null +++ b/libc/mingw/complex/csqrt.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" +#include "csqrt.def.h" diff --git a/libc/mingw/complex/csqrt.def.h b/libc/mingw/complex/csqrt.def.h new file mode 100644 index 000000000..714f303c1 --- /dev/null +++ b/libc/mingw/complex/csqrt.def.h @@ -0,0 +1,122 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(csqrt) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __FLT_TYPE d, r, s; + int r_class = fpclassify (__real__ z); + int i_class = fpclassify (__imag__ z); + + if (r_class == FP_INFINITE || r_class == FP_NAN || i_class == FP_INFINITE || i_class == FP_NAN) + { + if (i_class == FP_INFINITE) + { + __real__ ret = __FLT_HUGE_VAL; + __imag__ ret = __imag__ z; + return ret; + } + + if (r_class == FP_INFINITE) + { + if (__real__ z < __FLT_CST(0.0)) + { + __real__ ret = i_class == FP_NAN ? __FLT_NAN : __FLT_CST(0.0); + __imag__ ret = __FLT_ABI(copysign) (__FLT_HUGE_VAL, __imag__ z); + return ret; + } + + __real__ ret = __real__ z; + __imag__ ret = (i_class == FP_NAN + ? __FLT_NAN : __FLT_ABI(copysign) (__FLT_CST(0.0), __imag__ z)); + return ret; + } + + __real__ ret = __FLT_NAN; + __imag__ ret = __FLT_NAN; + return ret; + } + + if (i_class == FP_ZERO) + { + if (__real__ z < __FLT_CST(0.0)) + { + __real__ ret = __FLT_CST(0.0); + __imag__ ret = __FLT_ABI(copysign) (__FLT_ABI(sqrt) (-__real__ z), __imag__ z); + } + else + { + __real__ ret = __FLT_ABI(fabs) (__FLT_ABI(sqrt) (__real__ z)); + __imag__ ret = __FLT_ABI(copysign) (__FLT_CST(0.0), __imag__ z); + } + return ret; + } + + if (r_class == FP_ZERO) + { + r = __FLT_ABI(sqrt) (__FLT_CST(0.5) * __FLT_ABI(fabs) (__imag__ z)); + + __real__ ret = r; + __imag__ ret = __FLT_ABI(copysign) (r, __imag__ z); + return ret; + } + + d = __FLT_ABI(hypot) (__real__ z, __imag__ z); + if (__real__ z > __FLT_CST(0.0)) + { + r = __FLT_ABI(sqrt) (__FLT_CST(0.5) * d + __FLT_CST(0.5) * __real__ z); + s = (__FLT_CST(0.5) * __imag__ z) / r; + } + else + { + s = __FLT_ABI(sqrt) (__FLT_CST(0.5) * d - __FLT_CST(0.5) * __real__ z); + r = __FLT_ABI(fabs) ((__FLT_CST(0.5) * __imag__ z) / s); + } + + __real__ ret = r; + __imag__ ret = __FLT_ABI(copysign) (s, __imag__ z); + + return ret; +} diff --git a/libc/mingw/complex/csqrtf.c b/libc/mingw/complex/csqrtf.c new file mode 100644 index 000000000..5d41bf261 --- /dev/null +++ b/libc/mingw/complex/csqrtf.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" +#include "csqrt.def.h" diff --git a/libc/mingw/complex/csqrtl.c b/libc/mingw/complex/csqrtl.c new file mode 100644 index 000000000..1993289b5 --- /dev/null +++ b/libc/mingw/complex/csqrtl.c @@ -0,0 +1,48 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" +#include "csqrt.def.h" diff --git a/libc/mingw/complex/ctan.c b/libc/mingw/complex/ctan.c new file mode 100644 index 000000000..e4abcbbcc --- /dev/null +++ b/libc/mingw/complex/ctan.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* double version of the functions. */ +#define _NEW_COMPLEX_DOUBLE 1 +#include "complex_internal.h" + +#include "ctanh.def.h" +#include "ctan.def.h" diff --git a/libc/mingw/complex/ctan.def.h b/libc/mingw/complex/ctan.def.h new file mode 100644 index 000000000..28df5f330 --- /dev/null +++ b/libc/mingw/complex/ctan.def.h @@ -0,0 +1,61 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(ctan) (__FLT_TYPE __complex__ z) +{ + /* Annex G.6: ctan(z) = -i ctanh (iz) */ + __complex__ __FLT_TYPE ret; + __complex__ __FLT_TYPE x; + + __real__ x = -__imag__ z; + __imag__ x = __real__ z; + + x = __FLT_ABI(ctanh) (x); + + __real__ ret = __imag__ x; + __imag__ ret = -__real__ x; + + return ret; +} diff --git a/libc/mingw/complex/ctanf.c b/libc/mingw/complex/ctanf.c new file mode 100644 index 000000000..10e697893 --- /dev/null +++ b/libc/mingw/complex/ctanf.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Float version of the functions. */ +#define _NEW_COMPLEX_FLOAT 1 +#include "complex_internal.h" + +#include "ctanh.def.h" +#include "ctan.def.h" diff --git a/libc/mingw/complex/ctanh.def.h b/libc/mingw/complex/ctanh.def.h new file mode 100644 index 000000000..11a183648 --- /dev/null +++ b/libc/mingw/complex/ctanh.def.h @@ -0,0 +1,94 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +__FLT_TYPE __complex__ __cdecl +__FLT_ABI(ctanh) (__FLT_TYPE __complex__ z) +{ + __complex__ __FLT_TYPE ret; + __FLT_TYPE s, c, d; + + if (!isfinite (__real__ z) || !isfinite (__imag__ z)) + { + if (isinf (__real__ z)) + { + __real__ ret = __FLT_ABI(copysign) (__FLT_CST(1.0), __real__ z); + + /* fmod will return NaN if __imag__ z is infinity. This is actually + OK, because imaginary infinity returns a + or - zero (unspecified). + For +x, sin (x) is negative if fmod (x, 2pi) > pi. + For -x, sin (x) is positive if fmod (x, 2pi) < pi. + We use epsilon to ensure that the zeros are detected properly with + float and long double comparisons. */ + s = __FLT_ABI(fmod) (__imag__ z, __FLT_PI); + if (signbit (__imag__ z)) + __imag__ ret = s + __FLT_PI_2 < -__FLT_EPSILON ? 0.0 : -0.0; + else + __imag__ ret = s - __FLT_PI_2 > __FLT_EPSILON ? -0.0 : 0.0; + return ret; + } + + if (__imag__ z == __FLT_CST(0.0)) + return z; + + __real__ ret = __FLT_NAN; + __imag__ ret = __FLT_NAN; + return ret; + } + + __FLT_ABI(sincos) (__FLT_CST(2.0) * __imag__ z, &s, &c); + + d = (__FLT_ABI(cosh) (__FLT_CST(2.0) * __real__ z) + c); + + if (d == __FLT_CST(0.0)) + { + __complex__ __FLT_TYPE ez = __FLT_ABI(cexp) (z); + __complex__ __FLT_TYPE emz = __FLT_ABI(cexp) (-z); + + return (ez - emz) / (ez + emz); + } + + __real__ ret = __FLT_ABI(sinh) (__FLT_CST(2.0) * __real__ z) / d; + __imag__ ret = s / d; + return ret; +} diff --git a/libc/mingw/complex/ctanl.c b/libc/mingw/complex/ctanl.c new file mode 100644 index 000000000..eb7e37807 --- /dev/null +++ b/libc/mingw/complex/ctanl.c @@ -0,0 +1,50 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* long double version of the functions. */ +#define _NEW_COMPLEX_LDOUBLE 1 +#include "complex_internal.h" + +#include "ctanh.def.h" +#include "ctan.def.h" diff --git a/libc/mingw/crt/dllentry.c b/libc/mingw/crt/dllentry.c new file mode 100644 index 000000000..0e3581ba6 --- /dev/null +++ b/libc/mingw/crt/dllentry.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#define _DECL_DLLMAIN +#include + +BOOL WINAPI DllEntryPoint (HANDLE, DWORD, LPVOID); + +BOOL WINAPI DllEntryPoint (HANDLE __UNUSED_PARAM(hDllHandle), + DWORD __UNUSED_PARAM(dwReason), + LPVOID __UNUSED_PARAM(lpreserved)) +{ + return TRUE; +} diff --git a/libc/mingw/crt/dllmain.c b/libc/mingw/crt/dllmain.c new file mode 100644 index 000000000..7f97b0a89 --- /dev/null +++ b/libc/mingw/crt/dllmain.c @@ -0,0 +1,10 @@ +#include +#define _DECL_DLLMAIN +#include + +BOOL WINAPI DllMain (HANDLE __UNUSED_PARAM(hDllHandle), + DWORD __UNUSED_PARAM(dwReason), + LPVOID __UNUSED_PARAM(lpreserved)) +{ + return TRUE; +} diff --git a/libc/mingw/gdtoa/arithchk.c b/libc/mingw/gdtoa/arithchk.c new file mode 100644 index 000000000..f008fe16a --- /dev/null +++ b/libc/mingw/gdtoa/arithchk.c @@ -0,0 +1,186 @@ +/**************************************************************** +Copyright (C) 1997, 1998 Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. +****************************************************************/ + +/* Try to deduce arith.h from arithmetic properties. */ +#ifdef MINGW_BUILD_GEN + +#include + + static int dalign; + typedef struct +Akind { + char *name; + int kind; + } Akind; + + static Akind +IEEE_8087 = { "IEEE_8087", 1 }, +IEEE_MC68k = { "IEEE_MC68k", 2 }, +IBM = { "IBM", 3 }, +VAX = { "VAX", 4 }, +CRAY = { "CRAY", 5}; + + static Akind * +Lcheck() +{ + union { + double d; + long L[2]; + } u; + struct { + double d; + long L; + } x[2]; + + if (sizeof(x) > 2*(sizeof(double) + sizeof(long))) + dalign = 1; + u.L[0] = u.L[1] = 0; + u.d = 1e13; + if (u.L[0] == 1117925532 && u.L[1] == -448790528) + return &IEEE_MC68k; + if (u.L[1] == 1117925532 && u.L[0] == -448790528) + return &IEEE_8087; + if (u.L[0] == -2065213935 && u.L[1] == 10752) + return &VAX; + if (u.L[0] == 1267827943 && u.L[1] == 704643072) + return &IBM; + return 0; + } + + static Akind * +icheck() +{ + union { + double d; + int L[2]; + } u; + struct { + double d; + int L; + } x[2]; + + if (sizeof(x) > 2*(sizeof(double) + sizeof(int))) + dalign = 1; + u.L[0] = u.L[1] = 0; + u.d = 1e13; + if (u.L[0] == 1117925532 && u.L[1] == -448790528) + return &IEEE_MC68k; + if (u.L[1] == 1117925532 && u.L[0] == -448790528) + return &IEEE_8087; + if (u.L[0] == -2065213935 && u.L[1] == 10752) + return &VAX; + if (u.L[0] == 1267827943 && u.L[1] == 704643072) + return &IBM; + return 0; + } + +char *emptyfmt = ""; /* avoid possible warning message with printf("") */ + + static Akind * +ccheck() +{ + union { + double d; + long L; + } u; + long Cray1; + + /* Cray1 = 4617762693716115456 -- without overflow on non-Crays */ + Cray1 = printf(emptyfmt) < 0 ? 0 : 4617762; + if (printf(emptyfmt, Cray1) >= 0) + Cray1 = 1000000*Cray1 + 693716; + if (printf(emptyfmt, Cray1) >= 0) + Cray1 = 1000000*Cray1 + 115456; + u.d = 1e13; + if (u.L == Cray1) + return &CRAY; + return 0; + } + + static int +fzcheck() +{ + double a, b; + int i; + + a = 1.; + b = .1; + for(i = 155;; b *= b, i >>= 1) { + if (i & 1) { + a *= b; + if (i == 1) + break; + } + } + b = a * a; + return b == 0.; + } + + int +main() +{ + Akind *a = 0; + int Ldef = 0; + FILE *f; + +#ifdef WRITE_ARITH_H /* for Symantec's buggy "make" */ + f = fopen("arith.h", "w"); + if (!f) { + printf("Cannot open arith.h\n"); + return 1; + } +#else + f = stdout; +#endif + + if (sizeof(double) == 2*sizeof(long)) + a = Lcheck(); + else if (sizeof(double) == 2*sizeof(int)) { + Ldef = 1; + a = icheck(); + } + else if (sizeof(double) == sizeof(long)) + a = ccheck(); + if (a) { + fprintf(f, "#define %s\n#define Arith_Kind_ASL %d\n", + a->name, a->kind); + if (Ldef) + fprintf(f, "#define Long int\n#define Intcast (int)(long)\n"); + if (dalign) + fprintf(f, "#define Double_Align\n"); + if (sizeof(char*) == 8) + fprintf(f, "#define X64_bit_pointers\n"); +#ifndef NO_LONG_LONG + if (sizeof(long long) < 8) +#endif + fprintf(f, "#define NO_LONG_LONG\n"); + if (a->kind <= 2 && fzcheck()) + fprintf(f, "#define Sudden_Underflow\n"); + return 0; + } + fprintf(f, "/* Unknown arithmetic */\n"); + return 1; + } +#endif /* MINGW_BUILD_GEN */ + diff --git a/libc/mingw/gdtoa/dmisc.c b/libc/mingw/gdtoa/dmisc.c new file mode 100644 index 000000000..c61e9fa8a --- /dev/null +++ b/libc/mingw/gdtoa/dmisc.c @@ -0,0 +1,196 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +#ifndef MULTIPLE_THREADS +char *dtoa_result; +#endif + +char *rv_alloc (int i) +{ + int j, k, *r; + + j = sizeof(ULong); + for(k = 0; + (int) (sizeof(Bigint) - sizeof(ULong) - sizeof(int)) + j <= i; + j <<= 1) + k++; + r = (int*)Balloc(k); + *r = k; + return +#ifndef MULTIPLE_THREADS + dtoa_result = +#endif + (char *)(r+1); +} + +char *nrv_alloc (char *s, char **rve, int n) +{ + char *rv, *t; + + t = rv = rv_alloc(n); + while((*t = *s++) !=0) + t++; + if (rve) + *rve = t; + return rv; +} + +/* freedtoa(s) must be used to free values s returned by dtoa + * when MULTIPLE_THREADS is #defined. It should be used in all cases, + * but for consistency with earlier versions of dtoa, it is optional + * when MULTIPLE_THREADS is not defined. + */ + +void __freedtoa (char *s) +{ + Bigint *b = (Bigint *)((int *)s - 1); + b->maxwds = 1 << (b->k = *(int*)b); + Bfree(b); +#ifndef MULTIPLE_THREADS + if (s == dtoa_result) + dtoa_result = 0; +#endif +} + +int quorem (Bigint *b, Bigint *S) +{ + int n; + ULong *bx, *bxe, q, *sx, *sxe; +#ifdef ULLong + ULLong borrow, carry, y, ys; +#else + ULong borrow, carry, y, ys; +#ifdef Pack_32 + ULong si, z, zs; +#endif +#endif + + n = S->wds; +#ifdef DEBUG + /*debug*/ if (b->wds > n) + /*debug*/ Bug("oversize b in quorem"); +#endif + if (b->wds < n) + return 0; + sx = S->x; + sxe = sx + --n; + bx = b->x; + bxe = bx + n; + q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ +#ifdef DEBUG + /*debug*/ if (q > 9) + /*debug*/ Bug("oversized quotient in quorem"); +#endif + if (q) { + borrow = 0; + carry = 0; + do { +#ifdef ULLong + ys = *sx++ * (ULLong)q + carry; + carry = ys >> 32; + y = *bx - (ys & 0xffffffffUL) - borrow; + borrow = y >> 32 & 1UL; + *bx++ = y & 0xffffffffUL; +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) * q + carry; + zs = (si >> 16) * q + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ * q + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } while(sx <= sxe); + + if (!*bxe) { + bx = b->x; + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + + if (cmp(b, S) >= 0) { + q++; + borrow = 0; + carry = 0; + bx = b->x; + sx = S->x; + do { +#ifdef ULLong + ys = *sx++ + carry; + carry = ys >> 32; + y = *bx - (ys & 0xffffffffUL) - borrow; + borrow = y >> 32 & 1UL; + *bx++ = y & 0xffffffffUL; +#else +#ifdef Pack_32 + si = *sx++; + ys = (si & 0xffff) + carry; + zs = (si >> 16) + (ys >> 16); + carry = zs >> 16; + y = (*bx & 0xffff) - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*bx >> 16) - (zs & 0xffff) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(bx, z, y); +#else + ys = *sx++ + carry; + carry = ys >> 16; + y = *bx - (ys & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + *bx++ = y & 0xffff; +#endif +#endif + } while(sx <= sxe); + + bx = b->x; + bxe = bx + n; + if (!*bxe) { + while(--bxe > bx && !*bxe) + --n; + b->wds = n; + } + } + return q; +} diff --git a/libc/mingw/gdtoa/dtoa.c b/libc/mingw/gdtoa/dtoa.c new file mode 100644 index 000000000..2906bd99f --- /dev/null +++ b/libc/mingw/gdtoa/dtoa.c @@ -0,0 +1,750 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 1999 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the Long + * calculation. + */ + +#ifdef Honor_FLT_ROUNDS +#undef Check_FLT_ROUNDS +#define Check_FLT_ROUNDS +#else +#define Rounding Flt_Rounds +#endif + +char *__dtoa (double d0, int mode, int ndigits, int *decpt, int *sign, char **rve) +{ + /* Arguments ndigits, decpt, sign are similar to those + of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4,5 ==> similar to 2 and 3, respectively, but (in + round-nearest mode) with the tests of mode 0 to + possibly return a shorter string that rounds to d. + With IEEE arithmetic and compilation with + -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same + as modes 2 and 3 when FLT_ROUNDS != 1. + 6-9 ==> Debugging modes similar to mode - 4: don't try + fast floating-point estimate (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, + j, j2, k, k0, k_check, leftright, m2, m5, s2, s5, + spec_case, try_quick; + Long L; +#ifndef Sudden_Underflow + int denorm; + ULong x; +#endif + Bigint *b, *b1, *delta, *mlo, *mhi, *S; + union _dbl_union d, d2, eps; + double ds; + char *s, *s0; +#ifdef SET_INEXACT + int inexact, oldinexact; +#endif +#ifdef Honor_FLT_ROUNDS /*{*/ + int Rounding; +#ifdef Trust_FLT_ROUNDS /*{{ only define this if FLT_ROUNDS really works! */ + Rounding = Flt_Rounds; +#else /*}{*/ + Rounding = 1; + switch(fegetround()) { + case FE_TOWARDZERO: Rounding = 0; break; + case FE_UPWARD: Rounding = 2; break; + case FE_DOWNWARD: Rounding = 3; + } +#endif /*}}*/ +#endif /*}*/ + +#ifndef MULTIPLE_THREADS + if (dtoa_result) { + __freedtoa(dtoa_result); + dtoa_result = 0; + } +#endif + d.d = d0; + if (word0(&d) & Sign_bit) { + /* set sign for everything, including 0's and NaNs */ + *sign = 1; + word0(&d) &= ~Sign_bit; /* clear sign bit */ + } + else + *sign = 0; + + if ((word0(&d) & Exp_mask) == Exp_mask) + { + /* Infinity or NaN */ + *decpt = 9999; + if (!word1(&d) && !(word0(&d) & 0xfffff)) + return nrv_alloc("Infinity", rve, 8); + return nrv_alloc("NaN", rve, 3); + } + if (!dval(&d)) { + *decpt = 1; + return nrv_alloc("0", rve, 1); + } + +#ifdef SET_INEXACT + try_quick = oldinexact = get_inexact(); + inexact = 1; +#endif +#ifdef Honor_FLT_ROUNDS + if (Rounding >= 2) { + if (*sign) + Rounding = Rounding == 2 ? 0 : 2; + else + if (Rounding != 2) + Rounding = 0; + } +#endif + + b = d2b(dval(&d), &be, &bbits); +#ifdef Sudden_Underflow + i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); +#else + if (( i = (int)(word0(&d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)) )!=0) { +#endif + dval(&d2) = dval(&d); + word0(&d2) &= Frac_mask1; + word0(&d2) |= Exp_11; + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(&d) = (i-Bias)*log(2)/log(10) + log10(&d2) + * + * This suggests computing an approximation k to log10(&d) by + * + * k = (i - Bias)*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + + i -= Bias; +#ifndef Sudden_Underflow + denorm = 0; + } + else { + /* d is denormalized */ + + i = bbits + be + (Bias + (P-1) - 1); + x = i > 32 ? word0(&d) << (64 - i) | word1(&d) >> (i - 32) + : word1(&d) << (32 - i); + dval(&d2) = x; + word0(&d2) -= 31*Exp_msk1; /* adjust exponent */ + i -= (Bias + (P-1) - 1) + 1; + denorm = 1; + } +#endif + ds = (dval(&d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + if (k >= 0 && k <= Ten_pmax) { + if (dval(&d) < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + +#ifndef SET_INEXACT +#ifdef Check_FLT_ROUNDS + try_quick = Rounding == 1; +#else + try_quick = 1; +#endif +#endif /*SET_INEXACT*/ + + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ + switch(mode) { + case 0: + case 1: + i = 18; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + s = s0 = rv_alloc(i); + +#ifdef Honor_FLT_ROUNDS + if (mode > 1 && Rounding != 1) + leftright = 0; +#endif + + if (ilim >= 0 && ilim <= Quick_max && try_quick) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + dval(&d2) = dval(&d); + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + dval(&d) /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + dval(&d) /= ds; + } + else if (( j2 = -k )!=0) { + dval(&d) *= tens[j2 & 0xf]; + for(j = j2 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + dval(&d) *= bigtens[i]; + } + } + if (k_check && dval(&d) < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + dval(&d) *= 10.; + ieps++; + } + dval(&eps) = ieps*dval(&d) + 7.; + word0(&eps) -= (P-1)*Exp_msk1; + if (ilim == 0) { + S = mhi = 0; + dval(&d) -= 5.; + if (dval(&d) > dval(&eps)) + goto one_digit; + if (dval(&d) < -dval(&eps)) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + dval(&eps) = 0.5/tens[ilim-1] - dval(&eps); + for(i = 0;;) { + L = dval(&d); + dval(&d) -= L; + *s++ = '0' + (int)L; + if (dval(&d) < dval(&eps)) + goto ret1; + if (1. - dval(&d) < dval(&eps)) + goto bump_up; + if (++i >= ilim) + break; + dval(&eps) *= 10.; + dval(&d) *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + dval(&eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d)); + if (!(dval(&d) -= L)) + ilim = i; + *s++ = '0' + (int)L; + if (i == ilim) { + if (dval(&d) > 0.5 + dval(&eps)) + goto bump_up; + else if (dval(&d) < 0.5 - dval(&eps)) { + while(*--s == '0'); + s++; + goto ret1; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + dval(&d) = dval(&d2); + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= Int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + S = mhi = 0; + if (ilim < 0 || dval(&d) <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++, dval(&d) *= 10.) { + L = (Long)(dval(&d) / ds); + dval(&d) -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (dval(&d) < 0) { + L--; + dval(&d) += ds; + } +#endif + *s++ = '0' + (int)L; + if (!dval(&d)) { +#ifdef SET_INEXACT + inexact = 0; +#endif + break; + } + if (i == ilim) { +#ifdef Honor_FLT_ROUNDS + if (mode > 1) + switch(Rounding) { + case 0: goto ret1; + case 2: goto bump_up; + } +#endif + dval(&d) += dval(&d); +#ifdef ROUND_BIASED + if (dval(&d) >= ds) +#else + if (dval(&d) > ds || (dval(&d) == ds && L & 1)) +#endif + { + bump_up: + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + break; + } + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) { + i = +#ifndef Sudden_Underflow + denorm ? be + (Bias + (P-1) - 1 + 1) : +#endif + 1 + P - bbits; + b2 += i; + s2 += i; + mhi = i2b(1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + mhi = pow5mult(mhi, m5); + b1 = mult(mhi, b); + Bfree(b); + b = b1; + } + if (( j = b5 - m5 )!=0) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + spec_case = 0; + if ((mode < 2 || leftright) +#ifdef Honor_FLT_ROUNDS + && Rounding == 1 +#endif + ) { + if (!word1(&d) && !(word0(&d) & Bndry_mask) +#ifndef Sudden_Underflow + && word0(&d) & (Exp_mask & ~Exp_msk1) +#endif + ) { + /* The special case */ + b2 += Log2P; + s2 += Log2P; + spec_case = 1; + } + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ +#ifdef Pack_32 + if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f )!=0) + i = 32 - i; +#else + if (( i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf )!=0) + i = 16 - i; +#endif + if (i > 4) { + i -= 4; + b2 += i; + m2 += i; + s2 += i; + } + else if (i < 4) { + i += 28; + b2 += i; + m2 += i; + s2 += i; + } + if (b2 > 0) + b = lshift(b, b2); + if (s2 > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && (mode == 3 || mode == 5)) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + goto ret; + } + one_digit: + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) { + mhi = Balloc(mhi->k); + Bcopy(mhi, mlo); + mhi = lshift(mhi, Log2P); + } + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + delta = diff(S, mhi); + j2 = delta->sign ? 1 : cmp(b, delta); + Bfree(delta); +#ifndef ROUND_BIASED + if (j2 == 0 && mode != 1 && !(word1(&d) & 1) +#ifdef Honor_FLT_ROUNDS + && Rounding >= 1 +#endif + ) { + if (dig == '9') + goto round_9_up; + if (j > 0) + dig++; +#ifdef SET_INEXACT + else if (!b->x[0] && b->wds <= 1) + inexact = 0; +#endif + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && mode != 1 +#ifndef ROUND_BIASED + && !(word1(&d) & 1) +#endif + )) { + if (!b->x[0] && b->wds <= 1) { +#ifdef SET_INEXACT + inexact = 0; +#endif + goto accept_dig; + } +#ifdef Honor_FLT_ROUNDS + if (mode > 1) + switch(Rounding) { + case 0: goto accept_dig; + case 2: goto keep_dig; + } +#endif /*Honor_FLT_ROUNDS*/ + if (j2 > 0) { + b = lshift(b, 1); + j2 = cmp(b, S); +#ifdef ROUND_BIASED + if (j2 >= 0 /*)*/ +#else + if ((j2 > 0 || (j2 == 0 && dig & 1)) +#endif + && dig++ == '9') + goto round_9_up; + } + accept_dig: + *s++ = dig; + goto ret; + } + if (j2 > 0) { +#ifdef Honor_FLT_ROUNDS + if (!Rounding) + goto accept_dig; +#endif + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + goto roundoff; + } + *s++ = dig + 1; + goto ret; + } +#ifdef Honor_FLT_ROUNDS + keep_dig: +#endif + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (!b->x[0] && b->wds <= 1) { +#ifdef SET_INEXACT + inexact = 0; +#endif + goto ret; + } + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + +#ifdef Honor_FLT_ROUNDS + switch(Rounding) { + case 0: goto trimzeros; + case 2: goto roundoff; + } +#endif + b = lshift(b, 1); + j = cmp(b, S); +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { + roundoff: + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { +#ifdef Honor_FLT_ROUNDS + trimzeros: +#endif + while(*--s == '0'); + s++; + } + ret: + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: +#ifdef SET_INEXACT + if (inexact) { + if (!oldinexact) { + word0(&d) = Exp_1 + (70 << Exp_shift); + word1(&d) = 0; + dval(&d) += 1.; + } + } + else if (!oldinexact) + clear_inexact(); +#endif + Bfree(b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + return s0; +} diff --git a/libc/mingw/gdtoa/g__fmt.c b/libc/mingw/gdtoa/g__fmt.c new file mode 100644 index 000000000..49bd95a84 --- /dev/null +++ b/libc/mingw/gdtoa/g__fmt.c @@ -0,0 +1,142 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +#ifdef USE_LOCALE +#include "locale.h" +#endif + +char *__g__fmt (char *b, char *s, char *se, int decpt, ULong sign, size_t blen) +{ + int i, j, k; + char *be, *s0; + size_t len; +#ifdef USE_LOCALE +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + size_t dlen = strlen(decimalpoint); +#else + char *decimalpoint; + static char *decimalpoint_cache; + static size_t dlen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + dlen = strlen(s0); + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; +#endif +#else +#define dlen 0 +#endif + s0 = s; + len = (se-s) + dlen + 6; /* 6 = sign + e+dd + trailing null */ + if (blen < len) + goto ret0; + be = b + blen - 1; + if (sign) + *b++ = '-'; + if (decpt <= -4 || decpt > se - s + 5) { + *b++ = *s++; + if (*s) { +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif + while((*b = *s++) !=0) + b++; + } + *b++ = 'e'; + /* sprintf(b, "%+.2d", decpt - 1); */ + if (--decpt < 0) { + *b++ = '-'; + decpt = -decpt; + } + else + *b++ = '+'; + for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){} + for(;;) { + i = decpt / k; + if (b >= be) + goto ret0; + *b++ = i + '0'; + if (--j <= 0) + break; + decpt -= i*k; + decpt *= 10; + } + *b = 0; + } + else if (decpt <= 0) { +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif + if (be < b - decpt + (se - s)) + goto ret0; + for(; decpt < 0; decpt++) + *b++ = '0'; + while((*b = *s++) != 0) + b++; + } + else { + while((*b = *s++) != 0) { + b++; + if (--decpt == 0 && *s) { +#ifdef USE_LOCALE + while((*b = *decimalpoint++)) + ++b; +#else + *b++ = '.'; +#endif + } + } + if (b + decpt > be) { + ret0: + b = 0; + goto ret; + } + for(; decpt > 0; decpt--) + *b++ = '0'; + *b = 0; + } + ret: + __freedtoa(s0); + return b; +} diff --git a/libc/mingw/gdtoa/g_dfmt.c b/libc/mingw/gdtoa/g_dfmt.c new file mode 100644 index 000000000..50ed708a6 --- /dev/null +++ b/libc/mingw/gdtoa/g_dfmt.c @@ -0,0 +1,90 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +char *__g_dfmt (char *buf, double *d, int ndig, size_t bufsize) +{ + static FPI fpi0 = { 53, 1-1023-53+1, 2046-1023-53+1, 1, 0, Int_max }; + char *b, *s, *se; + ULong bits[2], *L, sign; + int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif + + if (ndig < 0) + ndig = 0; + if ((int) bufsize < ndig + 10) + return 0; + + L = (ULong*)d; + sign = L[_0] & 0x80000000L; + if ((L[_0] & 0x7ff00000) == 0x7ff00000) { + /* Infinity or NaN */ + if (bufsize < 10) + return 0; + if (L[_0] & 0xfffff || L[_1]) { + return strcp(buf, "NaN"); + } + b = buf; + if (sign) + *b++ = '-'; + return strcp(b, "Infinity"); + } + if (L[_1] == 0 && (L[_0] ^ sign) == 0 /*d == 0.*/) { + b = buf; +#ifndef IGNORE_ZERO_SIGN + if (L[_0] & 0x80000000L) + *b++ = '-'; +#endif + *b++ = '0'; + *b = 0; + return b; + } + bits[0] = L[_1]; + bits[1] = L[_0] & 0xfffff; + if ( (ex = (L[_0] >> 20) & 0x7ff) !=0) + bits[1] |= 0x100000; + else + ex = 1; + ex -= 0x3ff + 52; + mode = 2; + if (ndig <= 0) + mode = 0; + i = STRTOG_Normal; + if (sign) + i = STRTOG_Normal | STRTOG_Neg; + s = __gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return __g__fmt(buf, s, se, decpt, sign, bufsize); +} diff --git a/libc/mingw/gdtoa/g_ffmt.c b/libc/mingw/gdtoa/g_ffmt.c new file mode 100644 index 000000000..f3f7c2419 --- /dev/null +++ b/libc/mingw/gdtoa/g_ffmt.c @@ -0,0 +1,88 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +char *__g_ffmt (char *buf, float *f, int ndig, size_t bufsize) +{ + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, 0, 6 }; + char *b, *s, *se; + ULong bits[1], *L, sign; + int decpt, ex, i, mode; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif + + if (ndig < 0) + ndig = 0; + if ((int) bufsize < ndig + 10) + return 0; + + L = (ULong*)f; + sign = L[0] & 0x80000000L; + if ((L[0] & 0x7f800000) == 0x7f800000) { + /* Infinity or NaN */ + if (L[0] & 0x7fffff) { + return strcp(buf, "NaN"); + } + b = buf; + if (sign) + *b++ = '-'; + return strcp(b, "Infinity"); + } + if (*f == 0.) { + b = buf; +#ifndef IGNORE_ZERO_SIGN + if (L[0] & 0x80000000L) + *b++ = '-'; +#endif + *b++ = '0'; + *b = 0; + return b; + } + bits[0] = L[0] & 0x7fffff; + if ( (ex = (L[0] >> 23) & 0xff) !=0) + bits[0] |= 0x800000; + else + ex = 1; + ex -= 0x7f + 23; + mode = 2; + if (ndig <= 0) { + if (bufsize < 16) + return 0; + mode = 0; + } + i = STRTOG_Normal; + s = __gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return __g__fmt(buf, s, se, decpt, sign, bufsize); +} diff --git a/libc/mingw/gdtoa/g_xfmt.c b/libc/mingw/gdtoa/g_xfmt.c new file mode 100644 index 000000000..da11a5881 --- /dev/null +++ b/libc/mingw/gdtoa/g_xfmt.c @@ -0,0 +1,143 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +#undef _0 +#undef _1 + +/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ + +#ifdef IEEE_MC68k +#define _0 0 +#define _1 1 +#define _2 2 +#define _3 3 +#define _4 4 +#endif +#ifdef IEEE_8087 +#define _0 4 +#define _1 3 +#define _2 2 +#define _3 1 +#define _4 0 +#endif + +char *__g_xfmt (char *buf, void *V, int ndig, size_t bufsize) +{ + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, 0, Int_max }; + char *b, *s, *se; + ULong bits[2], sign; + UShort *L; + int decpt, ex, i, mode; +#if defined(__MINGW32__) || defined(__MINGW64__) + int fptype = __fpclassifyl (*(long double*) V); +#endif /* MinGW */ +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif + + if (ndig < 0) + ndig = 0; + if ((int) bufsize < ndig + 10) + return 0; + + L = (UShort *)V; + sign = L[_0] & 0x8000; + ex = L[_0] & 0x7fff; + bits[1] = (L[_1] << 16) | L[_2]; + bits[0] = (L[_3] << 16) | L[_4]; + +#if defined(__MINGW32__) || defined(__MINGW64__) + if (fptype & FP_NAN) { + /* NaN or Inf */ + if (fptype & FP_NORMAL) { + b = buf; + *b++ = sign ? '-': '+'; + strncpy (b, "Infinity", ndig ? ndig : 8); + return (buf + strlen (buf)); + } + strncpy (buf, "NaN", ndig ? ndig : 3); + return (buf + strlen (buf)); + } + else if (fptype & FP_NORMAL) { + /* Normal or subnormal */ + if (fptype & FP_ZERO) { + i = STRTOG_Denormal; + ex = 1; + } + else + i = STRTOG_Normal; + } +#else + if (ex != 0) { + if (ex == 0x7fff) { + /* Infinity or NaN */ + if (bits[0] | bits[1]) + b = strcp(buf, "NaN"); + else { + b = buf; + if (sign) + *b++ = '-'; + b = strcp(b, "Infinity"); + } + return b; + } + i = STRTOG_Normal; + } + else if (bits[0] | bits[1]) { + i = STRTOG_Denormal; + ex = 1; + } +#endif + else { + /* i = STRTOG_Zero; */ + b = buf; +#ifndef IGNORE_ZERO_SIGN + if (sign) + *b++ = '-'; +#endif + *b++ = '0'; + *b = 0; + return b; + } + ex -= 0x3fff + 63; + mode = 2; + if (ndig <= 0) { + if (bufsize < 32) + return 0; + mode = 0; + } + s = __gdtoa(fpi, ex, bits, &i, mode, ndig, &decpt, &se); + return __g__fmt(buf, s, se, decpt, sign, bufsize); +} diff --git a/libc/mingw/gdtoa/gd_arith.h b/libc/mingw/gdtoa/gd_arith.h new file mode 100644 index 000000000..f86e633b3 --- /dev/null +++ b/libc/mingw/gdtoa/gd_arith.h @@ -0,0 +1,6 @@ +#define IEEE_8087 +#define Arith_Kind_ASL 1 +#define Double_Align +#ifdef _WIN64 +#define X64_bit_pointers +#endif /* w64 */ diff --git a/libc/mingw/gdtoa/gd_qnan.h b/libc/mingw/gdtoa/gd_qnan.h new file mode 100644 index 000000000..0b468c492 --- /dev/null +++ b/libc/mingw/gdtoa/gd_qnan.h @@ -0,0 +1,12 @@ +#define f_QNAN 0x7fc00000 +#define d_QNAN0 0x0 +#define d_QNAN1 0x7ff80000 +#define ld_QNAN0 0x0 +#define ld_QNAN1 0xc0000000 +#define ld_QNAN2 0x7fff +#define ld_QNAN3 0x0 +#define ldus_QNAN0 0x0 +#define ldus_QNAN1 0x0 +#define ldus_QNAN2 0x0 +#define ldus_QNAN3 0xc000 +#define ldus_QNAN4 0x7fff diff --git a/libc/mingw/gdtoa/gdtoa.c b/libc/mingw/gdtoa/gdtoa.c new file mode 100644 index 000000000..cf9c290fb --- /dev/null +++ b/libc/mingw/gdtoa/gdtoa.c @@ -0,0 +1,733 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 1999 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +static Bigint *bitstob (ULong *bits, int nbits, int *bbits) +{ + int i, k; + Bigint *b; + ULong *be, *x, *x0; + + i = ULbits; + k = 0; + while(i < nbits) { + i <<= 1; + k++; + } +#ifndef Pack_32 + if (!k) + k = 1; +#endif + b = Balloc(k); + be = bits + ((nbits - 1) >> kshift); + x = x0 = b->x; + do { + *x++ = *bits & ALL_ON; +#ifdef Pack_16 + *x++ = (*bits >> 16) & ALL_ON; +#endif + } while(++bits <= be); + i = x - x0; + while(!x0[--i]) + if (!i) { + b->wds = 0; + *bbits = 0; + goto ret; + } + b->wds = i + 1; + *bbits = i*ULbits + 32 - hi0bits(b->x[i]); + ret: + return b; +} + +/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. + * + * Inspired by "How to Print Floating-Point Numbers Accurately" by + * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. + * + * Modifications: + * 1. Rather than iterating, we use a simple numeric overestimate + * to determine k = floor(log10(d)). We scale relevant + * quantities using O(log2(k)) rather than O(k) multiplications. + * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't + * try to generate digits strictly left to right. Instead, we + * compute with fewer bits and propagate the carry if necessary + * when rounding the final digit up. This is often faster. + * 3. Under the assumption that input will be rounded nearest, + * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. + * That is, we allow equality in stopping tests when the + * round-nearest rule will give the same floating-point value + * as would satisfaction of the stopping test with strict + * inequality. + * 4. We remove common factors of powers of 2 from relevant + * quantities. + * 5. When converting floating-point integers less than 1e16, + * we use floating-point arithmetic rather than resorting + * to multiple-precision integers. + * 6. When asked to produce fewer than 15 digits, we first try + * to get by with floating-point arithmetic; we resort to + * multiple-precision integer arithmetic only if we cannot + * guarantee that the floating-point calculation has given + * the correctly rounded result. For k requested digits and + * "uniformly" distributed input, the probability is + * something like 10^(k-15) that we must resort to the Long + * calculation. + */ + +char *__gdtoa (FPI *fpi, int be, ULong *bits, int *kindp, int mode, int ndigits, + int *decpt, char **rve) +{ + /* Arguments ndigits and decpt are similar to the second and third + arguments of ecvt and fcvt; trailing zeros are suppressed from + the returned string. If not null, *rve is set to point + to the end of the return value. If d is +-Infinity or NaN, + then *decpt is set to 9999. + be = exponent: value = (integer represented by bits) * (2 to the power of be). + + mode: + 0 ==> shortest string that yields d when read in + and rounded to nearest. + 1 ==> like 0, but with Steele & White stopping rule; + e.g. with IEEE P754 arithmetic , mode 0 gives + 1e23 whereas mode 1 gives 9.999999999999999e22. + 2 ==> max(1,ndigits) significant digits. This gives a + return value similar to that of ecvt, except + that trailing zeros are suppressed. + 3 ==> through ndigits past the decimal point. This + gives a return value similar to that from fcvt, + except that trailing zeros are suppressed, and + ndigits can be negative. + 4-9 should give the same return values as 2-3, i.e., + 4 <= mode <= 9 ==> same return as mode + 2 + (mode & 1). These modes are mainly for + debugging; often they run slower but sometimes + faster than modes 2-3. + 4,5,8,9 ==> left-to-right digit generation. + 6-9 ==> don't try fast floating-point estimate + (if applicable). + + Values of mode other than 0-9 are treated as mode 0. + + Sufficient space is allocated to the return value + to hold the suppressed trailing zeros. + */ + + int bbits, b2, b5, be0, dig, i, ieps, ilim, ilim0, ilim1, inex; + int j, j2, k, k0, k_check, kind, leftright, m2, m5, nbits; + int rdir, s2, s5, spec_case, try_quick; + Long L; + Bigint *b, *b1, *delta, *mlo, *mhi, *mhi1, *S; + double d2, ds; + char *s, *s0; + union _dbl_union d, eps; + +#ifndef MULTIPLE_THREADS + if (dtoa_result) { + __freedtoa(dtoa_result); + dtoa_result = 0; + } +#endif + inex = 0; + kind = *kindp &= ~STRTOG_Inexact; + switch(kind & STRTOG_Retmask) { + case STRTOG_Zero: + goto ret_zero; + case STRTOG_Normal: + case STRTOG_Denormal: + break; + case STRTOG_Infinite: + *decpt = -32768; + return nrv_alloc("Infinity", rve, 8); + case STRTOG_NaN: + *decpt = -32768; + return nrv_alloc("NaN", rve, 3); + default: + return 0; + } + b = bitstob(bits, nbits = fpi->nbits, &bbits); + be0 = be; + if ( (i = trailz(b)) !=0) { + rshift(b, i); + be += i; + bbits -= i; + } + if (!b->wds) { + Bfree(b); + ret_zero: + *decpt = 1; + return nrv_alloc("0", rve, 1); + } + + dval(&d) = b2d(b, &i); + i = be + bbits - 1; + word0(&d) &= Frac_mask1; + word0(&d) |= Exp_11; + + /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 + * log10(x) = log(x) / log(10) + * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) + * log10(&d) = (i-Bias)*log(2)/log(10) + log10(d2) + * + * This suggests computing an approximation k to log10(&d) by + * + * k = (i - Bias)*0.301029995663981 + * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); + * + * We want k to be too large rather than too small. + * The error in the first-order Taylor series approximation + * is in our favor, so we just round up the constant enough + * to compensate for any error in the multiplication of + * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, + * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, + * adding 1e-13 to the constant term more than suffices. + * Hence we adjust the constant term to 0.1760912590558. + * (We could get a more accurate k by invoking log10, + * but this is probably not worthwhile.) + */ + ds = (dval(&d)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; + + /* correct assumption about exponent range */ + if ((j = i) < 0) + j = -j; + if ((j -= 1077) > 0) + ds += j * 7e-17; + + k = (int)ds; + if (ds < 0. && ds != k) + k--; /* want k = floor(ds) */ + k_check = 1; + word0(&d) += (be + bbits - 1) << Exp_shift; + if (k >= 0 && k <= Ten_pmax) { + if (dval(&d) < tens[k]) + k--; + k_check = 0; + } + j = bbits - i - 1; + if (j >= 0) { + b2 = 0; + s2 = j; + } + else { + b2 = -j; + s2 = 0; + } + if (k >= 0) { + b5 = 0; + s5 = k; + s2 += k; + } + else { + b2 -= k; + b5 = -k; + s5 = 0; + } + if (mode < 0 || mode > 9) + mode = 0; + try_quick = 1; + if (mode > 5) { + mode -= 4; + try_quick = 0; + } + else if (i >= -4 - Emin || i < Emin) + try_quick = 0; + leftright = 1; + ilim = ilim1 = -1; /* Values for cases 0 and 1; done here to */ + /* silence erroneous "gcc -Wall" warning. */ + switch(mode) { + case 0: + case 1: + i = (int)(nbits * .30103) + 3; + ndigits = 0; + break; + case 2: + leftright = 0; + /* no break */ + case 4: + if (ndigits <= 0) + ndigits = 1; + ilim = ilim1 = i = ndigits; + break; + case 3: + leftright = 0; + /* no break */ + case 5: + i = ndigits + k + 1; + ilim = i; + ilim1 = i - 1; + if (i <= 0) + i = 1; + } + s = s0 = rv_alloc(i); + + if ( (rdir = fpi->rounding - 1) !=0) { + if (rdir < 0) + rdir = 2; + if (kind & STRTOG_Neg) + rdir = 3 - rdir; + } + + /* Now rdir = 0 ==> round near, 1 ==> round up, 2 ==> round down. */ + + if (ilim >= 0 && ilim <= Quick_max && try_quick && !rdir +#ifndef IMPRECISE_INEXACT + && k == 0 +#endif + ) { + + /* Try to get by with floating-point arithmetic. */ + + i = 0; + d2 = dval(&d); + k0 = k; + ilim0 = ilim; + ieps = 2; /* conservative */ + if (k > 0) { + ds = tens[k&0xf]; + j = k >> 4; + if (j & Bletch) { + /* prevent overflows */ + j &= Bletch - 1; + dval(&d) /= bigtens[n_bigtens-1]; + ieps++; + } + for(; j; j >>= 1, i++) + if (j & 1) { + ieps++; + ds *= bigtens[i]; + } + } + else { + ds = 1.; + if ( (j2 = -k) !=0) { + dval(&d) *= tens[j2 & 0xf]; + for(j = j2 >> 4; j; j >>= 1, i++) + if (j & 1) { + ieps++; + dval(&d) *= bigtens[i]; + } + } + } + if (k_check && dval(&d) < 1. && ilim > 0) { + if (ilim1 <= 0) + goto fast_failed; + ilim = ilim1; + k--; + dval(&d) *= 10.; + ieps++; + } + dval(&eps) = ieps*dval(&d) + 7.; + word0(&eps) -= (P-1)*Exp_msk1; + if (ilim == 0) { + S = mhi = 0; + dval(&d) -= 5.; + if (dval(&d) > dval(&eps)) + goto one_digit; + if (dval(&d) < -dval(&eps)) + goto no_digits; + goto fast_failed; + } +#ifndef No_leftright + if (leftright) { + /* Use Steele & White method of only + * generating digits needed. + */ + dval(&eps) = ds*0.5/tens[ilim-1] - dval(&eps); + for(i = 0;;) { + L = (Long)(dval(&d)/ds); + dval(&d) -= L*ds; + *s++ = '0' + (int)L; + if (dval(&d) < dval(&eps)) { + if (dval(&d)) + inex = STRTOG_Inexlo; + goto ret1; + } + if (ds - dval(&d) < dval(&eps)) + goto bump_up; + if (++i >= ilim) + break; + dval(&eps) *= 10.; + dval(&d) *= 10.; + } + } + else { +#endif + /* Generate ilim digits, then fix them up. */ + dval(&eps) *= tens[ilim-1]; + for(i = 1;; i++, dval(&d) *= 10.) { + if ( (L = (Long)(dval(&d)/ds)) !=0) + dval(&d) -= L*ds; + *s++ = '0' + (int)L; + if (i == ilim) { + ds *= 0.5; + if (dval(&d) > ds + dval(&eps)) + goto bump_up; + else if (dval(&d) < ds - dval(&eps)) { + if (dval(&d)) + inex = STRTOG_Inexlo; + goto clear_trailing0; + } + break; + } + } +#ifndef No_leftright + } +#endif + fast_failed: + s = s0; + dval(&d) = d2; + k = k0; + ilim = ilim0; + } + + /* Do we have a "small" integer? */ + + if (be >= 0 && k <= fpi->int_max) { + /* Yes. */ + ds = tens[k]; + if (ndigits < 0 && ilim <= 0) { + S = mhi = 0; + if (ilim < 0 || dval(&d) <= 5*ds) + goto no_digits; + goto one_digit; + } + for(i = 1;; i++, dval(&d) *= 10.) { + L = dval(&d) / ds; + dval(&d) -= L*ds; +#ifdef Check_FLT_ROUNDS + /* If FLT_ROUNDS == 2, L will usually be high by 1 */ + if (dval(&d) < 0) { + L--; + dval(&d) += ds; + } +#endif + *s++ = '0' + (int)L; + if (dval(&d) == 0.) + break; + if (i == ilim) { + if (rdir) { + if (rdir == 1) + goto bump_up; + inex = STRTOG_Inexlo; + goto ret1; + } + dval(&d) += dval(&d); +#ifdef ROUND_BIASED + if (dval(&d) >= ds) +#else + if (dval(&d) > ds || (dval(&d) == ds && L & 1)) +#endif + { + bump_up: + inex = STRTOG_Inexhi; + while(*--s == '9') + if (s == s0) { + k++; + *s = '0'; + break; + } + ++*s++; + } + else { + inex = STRTOG_Inexlo; + clear_trailing0: + while(*--s == '0'){} + ++s; + } + break; + } + } + goto ret1; + } + + m2 = b2; + m5 = b5; + mhi = mlo = 0; + if (leftright) { + i = nbits - bbits; + if (be - i++ < fpi->emin && mode != 3 && mode != 5) { + /* denormal */ + i = be - fpi->emin + 1; + if (mode >= 2 && ilim > 0 && ilim < i) + goto small_ilim; + } + else if (mode >= 2) { + small_ilim: + j = ilim - 1; + if (m5 >= j) + m5 -= j; + else { + s5 += j -= m5; + b5 += j; + m5 = 0; + } + if ((i = ilim) < 0) { + m2 -= i; + i = 0; + } + } + b2 += i; + s2 += i; + mhi = i2b(1); + } + if (m2 > 0 && s2 > 0) { + i = m2 < s2 ? m2 : s2; + b2 -= i; + m2 -= i; + s2 -= i; + } + if (b5 > 0) { + if (leftright) { + if (m5 > 0) { + mhi = pow5mult(mhi, m5); + b1 = mult(mhi, b); + Bfree(b); + b = b1; + } + if ( (j = b5 - m5) !=0) + b = pow5mult(b, j); + } + else + b = pow5mult(b, b5); + } + S = i2b(1); + if (s5 > 0) + S = pow5mult(S, s5); + + /* Check for special case that d is a normalized power of 2. */ + + spec_case = 0; + if (mode < 2) { + if (bbits == 1 && be0 > fpi->emin + 1) { + /* The special case */ + b2++; + s2++; + spec_case = 1; + } + } + + /* Arrange for convenient computation of quotients: + * shift left if necessary so divisor has 4 leading 0 bits. + * + * Perhaps we should just compute leading 28 bits of S once + * and for all and pass them and a shift to quorem, so it + * can do shifts and ors to compute the numerator for q. + */ + i = ((s5 ? hi0bits(S->x[S->wds-1]) : ULbits - 1) - s2 - 4) & kmask; + m2 += i; + if ((b2 += i) > 0) + b = lshift(b, b2); + if ((s2 += i) > 0) + S = lshift(S, s2); + if (k_check) { + if (cmp(b,S) < 0) { + k--; + b = multadd(b, 10, 0); /* we botched the k estimate */ + if (leftright) + mhi = multadd(mhi, 10, 0); + ilim = ilim1; + } + } + if (ilim <= 0 && mode > 2) { + if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { + /* no digits, fcvt style */ + no_digits: + k = -1 - ndigits; + inex = STRTOG_Inexlo; + goto ret; + } + one_digit: + inex = STRTOG_Inexhi; + *s++ = '1'; + k++; + goto ret; + } + if (leftright) { + if (m2 > 0) + mhi = lshift(mhi, m2); + + /* Compute mlo -- check for special case + * that d is a normalized power of 2. + */ + + mlo = mhi; + if (spec_case) { + mhi = Balloc(mhi->k); + Bcopy(mhi, mlo); + mhi = lshift(mhi, 1); + } + + for(i = 1;;i++) { + dig = quorem(b,S) + '0'; + /* Do we yet have the shortest decimal string + * that will round to d? + */ + j = cmp(b, mlo); + delta = diff(S, mhi); + j2 = delta->sign ? 1 : cmp(b, delta); + Bfree(delta); +#ifndef ROUND_BIASED + if (j2 == 0 && !mode && !(bits[0] & 1) && !rdir) { + if (dig == '9') + goto round_9_up; + if (j <= 0) { + if (b->wds > 1 || b->x[0]) + inex = STRTOG_Inexlo; + } + else { + dig++; + inex = STRTOG_Inexhi; + } + *s++ = dig; + goto ret; + } +#endif + if (j < 0 || (j == 0 && !mode +#ifndef ROUND_BIASED + && !(bits[0] & 1) +#endif + )) { + if (rdir && (b->wds > 1 || b->x[0])) { + if (rdir == 2) { + inex = STRTOG_Inexlo; + goto accept; + } + while (cmp(S,mhi) > 0) { + *s++ = dig; + mhi1 = multadd(mhi, 10, 0); + if (mlo == mhi) + mlo = mhi1; + mhi = mhi1; + b = multadd(b, 10, 0); + dig = quorem(b,S) + '0'; + } + if (dig++ == '9') + goto round_9_up; + inex = STRTOG_Inexhi; + goto accept; + } + if (j2 > 0) { + b = lshift(b, 1); + j2 = cmp(b, S); +#ifdef ROUND_BIASED + if (j2 >= 0 /*)*/ +#else + if ((j2 > 0 || (j2 == 0 && dig & 1)) +#endif + && dig++ == '9') + goto round_9_up; + inex = STRTOG_Inexhi; + } + if (b->wds > 1 || b->x[0]) + inex = STRTOG_Inexlo; + accept: + *s++ = dig; + goto ret; + } + if (j2 > 0 && rdir != 2) { + if (dig == '9') { /* possible if i == 1 */ + round_9_up: + *s++ = '9'; + inex = STRTOG_Inexhi; + goto roundoff; + } + inex = STRTOG_Inexhi; + *s++ = dig + 1; + goto ret; + } + *s++ = dig; + if (i == ilim) + break; + b = multadd(b, 10, 0); + if (mlo == mhi) + mlo = mhi = multadd(mhi, 10, 0); + else { + mlo = multadd(mlo, 10, 0); + mhi = multadd(mhi, 10, 0); + } + } + } + else + for(i = 1;; i++) { + *s++ = dig = quorem(b,S) + '0'; + if (i >= ilim) + break; + b = multadd(b, 10, 0); + } + + /* Round off last digit */ + + if (rdir) { + if (rdir == 2 || (b->wds <= 1 && !b->x[0])) + goto chopzeros; + goto roundoff; + } + b = lshift(b, 1); + j = cmp(b, S); +#ifdef ROUND_BIASED + if (j >= 0) +#else + if (j > 0 || (j == 0 && dig & 1)) +#endif + { + roundoff: + inex = STRTOG_Inexhi; + while(*--s == '9') + if (s == s0) { + k++; + *s++ = '1'; + goto ret; + } + ++*s++; + } + else { + chopzeros: + if (b->wds > 1 || b->x[0]) + inex = STRTOG_Inexlo; + while(*--s == '0'){} + ++s; + } + ret: + Bfree(S); + if (mhi) { + if (mlo && mlo != mhi) + Bfree(mlo); + Bfree(mhi); + } + ret1: + Bfree(b); + *s = 0; + *decpt = k + 1; + if (rve) + *rve = s; + *kindp |= inex; + return s0; +} diff --git a/libc/mingw/gdtoa/gdtoa.h b/libc/mingw/gdtoa/gdtoa.h new file mode 100644 index 000000000..c5c6f8d72 --- /dev/null +++ b/libc/mingw/gdtoa/gdtoa.h @@ -0,0 +1,119 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +/* Modified by Danny Smith for inclusion in libmingwex.a + Aug 2006 */ + +#ifndef GDTOA_H_INCLUDED +#define GDTOA_H_INCLUDED + +#include "gd_arith.h" +#include /* for size_t */ + +#if defined(__MINGW32__) || defined(__MINGW64__) +/* keep the 'Long' definition as 'long' for compatibility + * with older/other software. long in w64 is 32 bits anyway.. + */ +#define Long long /* Windows long is 32 bit */ +#undef NO_LONG_LONG /* we have long long type */ +#endif /* MinGW */ + +#ifndef Long +#define Long int +#endif +#ifndef ULong +typedef unsigned Long ULong; +#endif +#ifndef UShort +typedef unsigned short UShort; +#endif + +enum { /* return values from strtodg */ + STRTOG_Zero = 0, + STRTOG_Normal = 1, + STRTOG_Denormal = 2, + STRTOG_Infinite = 3, + STRTOG_NaN = 4, + STRTOG_NaNbits = 5, + STRTOG_NoNumber = 6, + STRTOG_Retmask = 7, + + /* The following may be or-ed into one of the above values. */ + + STRTOG_Neg = 0x08, /* does not affect STRTOG_Inexlo or STRTOG_Inexhi */ + STRTOG_Inexlo = 0x10, /* returned result rounded toward zero */ + STRTOG_Inexhi = 0x20, /* returned result rounded away from zero */ + STRTOG_Inexact = 0x30, + STRTOG_Underflow= 0x40, + STRTOG_Overflow = 0x80 +}; + +typedef struct +FPI { + int nbits; + int emin; + int emax; + int rounding; + int sudden_underflow; + int int_max; +} FPI; + +enum { /* FPI.rounding values: same as FLT_ROUNDS */ + FPI_Round_zero = 0, + FPI_Round_near = 1, + FPI_Round_up = 2, + FPI_Round_down = 3 +}; + +#ifdef __cplusplus +extern "C" { +#endif + +extern char* __dtoa (double d, int mode, int ndigits, int *decpt, + int *sign, char **rve); +extern char* __gdtoa (FPI *fpi, int be, ULong *bits, int *kindp, + int mode, int ndigits, int *decpt, char **rve); +extern void __freedtoa (char *); + +extern float __strtof (const char *, char **); +extern double __strtod (const char *, char **); +extern long double __strtold (const char *, char **); +extern int __strtodg (const char *, char **, FPI *, Long *, ULong *); + +extern char* __g__fmt (char*, char*, char*, int, ULong, size_t); +extern char* __g_dfmt (char*, double*, int, size_t); +extern char* __g_ffmt (char*, float*, int, size_t); +extern char* __g_xfmt (char*, void*, int, size_t); + +#ifdef __cplusplus +} +#endif +#endif /* GDTOA_H_INCLUDED */ diff --git a/libc/mingw/gdtoa/gdtoaimp.h b/libc/mingw/gdtoa/gdtoaimp.h new file mode 100644 index 000000000..49b9ce05b --- /dev/null +++ b/libc/mingw/gdtoa/gdtoaimp.h @@ -0,0 +1,641 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998-2000 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* This is a variation on dtoa.c that converts arbitary binary + floating-point formats to and from decimal notation. It uses + double-precision arithmetic internally, so there are still + various #ifdefs that adapt the calculations to the native + double-precision arithmetic (any of IEEE, VAX D_floating, + or IBM mainframe arithmetic). + + Please send bug reports to David M. Gay (dmg at acm dot org, + with " at " changed at "@" and " dot " changed to "."). + */ + +/* On a machine with IEEE extended-precision registers, it is + * necessary to specify double-precision (53-bit) rounding precision + * before invoking strtod or dtoa. If the machine uses (the equivalent + * of) Intel 80x87 arithmetic, the call + * _control87(PC_53, MCW_PC); + * does this with many compilers. Whether this or another call is + * appropriate depends on the compiler; for this to work, it may be + * necessary to #include "float.h" or another system-dependent header + * file. + */ + +/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. + * + * This strtod returns a nearest machine number to the input decimal + * string (or sets errno to ERANGE). With IEEE arithmetic, ties are + * broken by the IEEE round-even rule. Otherwise ties are broken by + * biased rounding (add half and chop). + * + * Inspired loosely by William D. Clinger's paper "How to Read Floating + * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 112-126]. + * + * Modifications: + * + * 1. We only require IEEE, IBM, or VAX double-precision + * arithmetic (not IEEE double-extended). + * 2. We get by with floating-point arithmetic in a case that + * Clinger missed -- when we're computing d * 10^n + * for a small integer d and the integer n is not too + * much larger than 22 (the maximum integer k for which + * we can represent 10^k exactly), we may be able to + * compute (d*10^k) * 10^(e-k) with just one roundoff. + * 3. Rather than a bit-at-a-time adjustment of the binary + * result in the hard case, we use floating-point + * arithmetic to determine the adjustment to within + * one bit; only in really hard cases do we need to + * compute a second residual. + * 4. Because of 3., we don't need a large table of powers of 10 + * for ten-to-e (just some small tables, e.g. of 10^k + * for 0 <= k <= 22). + */ + +/* + * #define IEEE_8087 for IEEE-arithmetic machines where the least + * significant byte has the lowest address. + * #define IEEE_MC68k for IEEE-arithmetic machines where the most + * significant byte has the lowest address. + * #define Long int on machines with 32-bit ints and 64-bit longs. + * #define Sudden_Underflow for IEEE-format machines without gradual + * underflow (i.e., that flush to zero on underflow). + * #define IBM for IBM mainframe-style floating-point arithmetic. + * #define VAX for VAX-style floating-point arithmetic (D_floating). + * #define No_leftright to omit left-right logic in fast floating-point + * computation of dtoa and gdtoa. This will cause modes 4 and 5 to be + * treated the same as modes 2 and 3 for some inputs. + * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3. + * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines + * that use extended-precision instructions to compute rounded + * products and quotients) with IBM. + * #define ROUND_BIASED for IEEE-format with biased rounding and arithmetic + * that rounds toward +Infinity. + * #define ROUND_BIASED_without_Round_Up for IEEE-format with biased + * rounding when the underlying floating-point arithmetic uses + * unbiased rounding. This prevent using ordinary floating-point + * arithmetic when the result could be computed with one rounding error. + * #define Inaccurate_Divide for IEEE-format with correctly rounded + * products but inaccurate quotients, e.g., for Intel i860. + * #define NO_LONG_LONG on machines that do not have a "long long" + * integer type (of >= 64 bits). On such machines, you can + * #define Just_16 to store 16 bits per 32-bit Long when doing + * high-precision integer arithmetic. Whether this speeds things + * up or slows things down depends on the machine and the number + * being converted. If long long is available and the name is + * something other than "long long", #define Llong to be the name, + * and if "unsigned Llong" does not work as an unsigned version of + * Llong, #define #ULLong to be the corresponding unsigned type. + * #define KR_headers for old-style C function headers. + * #define Bad_float_h if your system lacks a float.h or if it does not + * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, + * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. + * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) + * if memory is available and otherwise does something you deem + * appropriate. If MALLOC is undefined, malloc will be invoked + * directly -- and assumed always to succeed. + * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making + * memory allocations from a private pool of memory when possible. + * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, + * unless #defined to be a different length. This default length + * suffices to get rid of MALLOC calls except for unusual cases, + * such as decimal-to-binary conversion of a very long string of + * digits. When converting IEEE double precision values, the + * longest string gdtoa can return is about 751 bytes long. For + * conversions by strtod of strings of 800 digits and all gdtoa + * conversions of IEEE doubles in single-threaded executions with + * 8-byte pointers, PRIVATE_MEM >= 7400 appears to suffice; with + * 4-byte pointers, PRIVATE_MEM >= 7112 appears adequate. + * #define NO_INFNAN_CHECK if you do not wish to have INFNAN_CHECK + * #defined automatically on IEEE systems. On such systems, + * when INFNAN_CHECK is #defined, strtod checks + * for Infinity and NaN (case insensitively). + * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, + * strtodg also accepts (case insensitively) strings of the form + * NaN(x), where x is a string of hexadecimal digits (optionally + * preceded by 0x or 0X) and spaces; if there is only one string + * of hexadecimal digits, it is taken for the fraction bits of the + * resulting NaN; if there are two or more strings of hexadecimal + * digits, each string is assigned to the next available sequence + * of 32-bit words of fractions bits (starting with the most + * significant), right-aligned in each sequence. + * Unless GDTOA_NON_PEDANTIC_NANCHECK is #defined, input "NaN(...)" + * is consumed even when ... has the wrong form (in which case the + * "(...)" is consumed but ignored). + * #define MULTIPLE_THREADS if the system offers preemptively scheduled + * multiple threads. In this case, you must provide (or suitably + * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed + * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed + * in pow5mult, ensures lazy evaluation of only one copy of high + * powers of 5; omitting this lock would introduce a small + * probability of wasting memory, but would otherwise be harmless.) + * You must also invoke freedtoa(s) to free the value s returned by + * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. + * #define IMPRECISE_INEXACT if you do not care about the setting of + * the STRTOG_Inexact bits in the special case of doing IEEE double + * precision conversions (which could also be done by the strtog in + * dtoa.c). + * #define NO_HEX_FP to disable recognition of C9x's hexadecimal + * floating-point constants. + * #define -DNO_ERRNO to suppress setting errno (in strtod.c and + * strtodg.c). + * #define NO_STRING_H to use private versions of memcpy. + * On some K&R systems, it may also be necessary to + * #define DECLARE_SIZE_T in this case. + * #define USE_LOCALE to use the current locale's decimal_point value. + */ + +#ifndef GDTOAIMP_H_INCLUDED +#define GDTOAIMP_H_INCLUDED +#include "gdtoa.h" +#include "gd_qnan.h" + +#if defined(__MINGW32__) || defined(__MINGW64__) +#define MULTIPLE_THREADS 1 +#define USE_LOCALE 1 +#define NO_LOCALE_CACHE 1 +#endif /* MinGW */ + +#ifdef Honor_FLT_ROUNDS +#include +#endif + +#ifdef DEBUG +#include +#define Bug(x) {fprintf(stderr, "%s\n", x); exit(1);} +#endif + +#include +#include + +#ifdef MALLOC +extern void *MALLOC (size_t); +#else +#define MALLOC malloc +#endif + +#undef IEEE_Arith +#undef Avoid_Underflow +#ifdef IEEE_MC68k +#define IEEE_Arith +#endif +#ifdef IEEE_8087 +#define IEEE_Arith +#endif + +#include + +#ifdef NO_ERRNO +#define SET_ERRNO(x) +#else +#define SET_ERRNO(x) \ + errno = (x) +#endif + +#ifdef Bad_float_h + +#ifdef IEEE_Arith +#define DBL_DIG 15 +#define DBL_MAX_10_EXP 308 +#define DBL_MAX_EXP 1024 +#define FLT_RADIX 2 +#define DBL_MAX 1.7976931348623157e+308 +#endif + +#ifdef IBM +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 75 +#define DBL_MAX_EXP 63 +#define FLT_RADIX 16 +#define DBL_MAX 7.2370055773322621e+75 +#endif + +#ifdef VAX +#define DBL_DIG 16 +#define DBL_MAX_10_EXP 38 +#define DBL_MAX_EXP 127 +#define FLT_RADIX 2 +#define DBL_MAX 1.7014118346046923e+38 +#define n_bigtens 2 +#endif + +#ifndef LONG_MAX +#define LONG_MAX 2147483647 +#endif + +#else /* ifndef Bad_float_h */ +#include +#endif /* Bad_float_h */ + +#ifdef IEEE_Arith +#define Scale_Bit 0x10 +#define n_bigtens 5 +#endif + +#ifdef IBM +#define n_bigtens 3 +#endif + +#ifdef VAX +#define n_bigtens 2 +#endif + +#ifndef __MATH_H__ +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(IEEE_8087) + defined(IEEE_MC68k) + defined(VAX) + defined(IBM) != 1 +Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined. +#endif + +typedef union _dbl_union { double d; ULong L[2]; } dbl_union; + +#ifdef IEEE_8087 +#define word0(x) (x)->L[1] +#define word1(x) (x)->L[0] +#else +#define word0(x) (x)->L[0] +#define word1(x) (x)->L[1] +#endif +#define dval(x) (x)->d + +/* The following definition of Storeinc is appropriate for MIPS processors. + * An alternative that might be better on some machines is + * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) + */ +#if defined(IEEE_8087) + defined(VAX) +#define Storeinc(a,b,c) (((unsigned short *)a)[1] = (unsigned short)b, \ +((unsigned short *)a)[0] = (unsigned short)c, a++) +#else +#define Storeinc(a,b,c) (((unsigned short *)a)[0] = (unsigned short)b, \ +((unsigned short *)a)[1] = (unsigned short)c, a++) +#endif + +/* #define P DBL_MANT_DIG */ +/* Ten_pmax = floor(P*log(2)/log(5)) */ +/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ +/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ +/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ + +#ifdef IEEE_Arith +#define Exp_shift 20 +#define Exp_shift1 20 +#define Exp_msk1 0x100000 +#define Exp_msk11 0x100000 +#define Exp_mask 0x7ff00000 +#define P 53 +#define Bias 1023 +#define Emin (-1022) +#define Exp_1 0x3ff00000 +#define Exp_11 0x3ff00000 +#define Ebits 11 +#define Frac_mask 0xfffff +#define Frac_mask1 0xfffff +#define Ten_pmax 22 +#define Bletch 0x10 +#define Bndry_mask 0xfffff +#define Bndry_mask1 0xfffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 1 +#define Tiny0 0 +#define Tiny1 1 +#define Quick_max 14 +#define Int_max 14 + +#ifndef Flt_Rounds +#ifdef FLT_ROUNDS +#define Flt_Rounds FLT_ROUNDS +#else +#define Flt_Rounds 1 +#endif +#endif /*Flt_Rounds*/ + +#else /* ifndef IEEE_Arith */ +#undef Sudden_Underflow +#define Sudden_Underflow +#ifdef IBM +#undef Flt_Rounds +#define Flt_Rounds 0 +#define Exp_shift 24 +#define Exp_shift1 24 +#define Exp_msk1 0x1000000 +#define Exp_msk11 0x1000000 +#define Exp_mask 0x7f000000 +#define P 14 +#define Bias 65 +#define Exp_1 0x41000000 +#define Exp_11 0x41000000 +#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ +#define Frac_mask 0xffffff +#define Frac_mask1 0xffffff +#define Bletch 4 +#define Ten_pmax 22 +#define Bndry_mask 0xefffff +#define Bndry_mask1 0xffffff +#define LSB 1 +#define Sign_bit 0x80000000 +#define Log2P 4 +#define Tiny0 0x100000 +#define Tiny1 0 +#define Quick_max 14 +#define Int_max 15 +#else /* VAX */ +#undef Flt_Rounds +#define Flt_Rounds 1 +#define Exp_shift 23 +#define Exp_shift1 7 +#define Exp_msk1 0x80 +#define Exp_msk11 0x800000 +#define Exp_mask 0x7f80 +#define P 56 +#define Bias 129 +#define Exp_1 0x40800000 +#define Exp_11 0x4080 +#define Ebits 8 +#define Frac_mask 0x7fffff +#define Frac_mask1 0xffff007f +#define Ten_pmax 24 +#define Bletch 2 +#define Bndry_mask 0xffff007f +#define Bndry_mask1 0xffff007f +#define LSB 0x10000 +#define Sign_bit 0x8000 +#define Log2P 1 +#define Tiny0 0x80 +#define Tiny1 0 +#define Quick_max 15 +#define Int_max 15 +#endif /* IBM, VAX */ +#endif /* IEEE_Arith */ + +#ifndef IEEE_Arith +#define ROUND_BIASED +#else +#ifdef ROUND_BIASED_without_Round_Up +#undef ROUND_BIASED +#define ROUND_BIASED +#endif +#endif + +#ifdef RND_PRODQUOT +#define rounded_product(a,b) a = rnd_prod(a, b) +#define rounded_quotient(a,b) a = rnd_quot(a, b) +extern double rnd_prod(double, double), rnd_quot(double, double); +#else +#define rounded_product(a,b) a *= b +#define rounded_quotient(a,b) a /= b +#endif + +#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) +#define Big1 0xffffffff + +#undef Pack_16 +#ifndef Pack_32 +#define Pack_32 +#endif + +#ifdef NO_LONG_LONG +#undef ULLong +#ifdef Just_16 +#undef Pack_32 +#define Pack_16 +/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. + * This makes some inner loops simpler and sometimes saves work + * during multiplications, but it often seems to make things slightly + * slower. Hence the default is now to store 32 bits per Long. + */ +#endif +#else /* long long available */ +#ifndef Llong +#define Llong long long +#endif +#ifndef ULLong +#define ULLong unsigned Llong +#endif +#endif /* NO_LONG_LONG */ + +#ifdef Pack_32 +#define ULbits 32 +#define kshift 5 +#define kmask 31 +#define ALL_ON 0xffffffff +#else +#define ULbits 16 +#define kshift 4 +#define kmask 15 +#define ALL_ON 0xffff +#endif + +#ifndef MULTIPLE_THREADS +#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ +#define FREE_DTOA_LOCK(n) /*nothing*/ +#endif + +#define Kmax 9 + +#define Bigint __Bigint +struct +Bigint { + struct Bigint *next; + int k, maxwds, sign, wds; + ULong x[1]; +}; +typedef struct Bigint Bigint; + +#ifdef NO_STRING_H +#ifdef DECLARE_SIZE_T +typedef unsigned int size_t; +#endif +extern void memcpy_D2A (void*, const void*, size_t); +#define Bcopy(x,y) memcpy_D2A(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) +#else /* !NO_STRING_H */ +#define Bcopy(x,y) memcpy(&x->sign,&y->sign,y->wds*sizeof(ULong) + 2*sizeof(int)) +#endif /* NO_STRING_H */ + +#ifdef __GNUC__ +static inline int +__lo0bits_D2A (ULong *y) +{ + int ret = __builtin_ctz(*y); + *y = *y >> ret; + return ret; +} + +static inline int +__hi0bits_D2A (ULong y) +{ + return __builtin_clz(y); +} +#endif + +#define Balloc __Balloc_D2A +#define Bfree __Bfree_D2A +#define ULtoQ __ULtoQ_D2A +#define ULtof __ULtof_D2A +#define ULtod __ULtod_D2A +#define ULtodd __ULtodd_D2A +#define ULtox __ULtox_D2A +#define ULtoxL __ULtoxL_D2A +#define any_on __any_on_D2A +#define b2d __b2d_D2A +#define bigtens __bigtens_D2A +#define cmp __cmp_D2A +#define copybits __copybits_D2A +#define d2b __d2b_D2A +#define decrement __decrement_D2A +#define diff __diff_D2A +#define dtoa_result __dtoa_result_D2A +#define gethex __gethex_D2A +#define hexdig __hexdig_D2A +#define hexnan __hexnan_D2A +#define hi0bits_D2A __hi0bits_D2A +#define hi0bits(x) __hi0bits_D2A((ULong)(x)) +#define i2b __i2b_D2A +#define increment __increment_D2A +#define lo0bits __lo0bits_D2A +#define lshift __lshift_D2A +#define match __match_D2A +#define mult __mult_D2A +#define multadd __multadd_D2A +#define nrv_alloc __nrv_alloc_D2A +#define pow5mult __pow5mult_D2A +#define quorem __quorem_D2A +#define ratio __ratio_D2A +#define rshift __rshift_D2A +#define rv_alloc __rv_alloc_D2A +#define s2b __s2b_D2A +#define set_ones __set_ones_D2A +#define strcp_D2A __strcp_D2A +#define strcp __strcp_D2A +#define strtoIg __strtoIg_D2A +#define sum __sum_D2A +#define tens __tens_D2A +#define tinytens __tinytens_D2A +#define tinytens __tinytens_D2A +#define trailz __trailz_D2A +#define ulp __ulp_D2A + +#define hexdig_init_D2A __mingw_hexdig_init_D2A + +extern char *dtoa_result; +extern const double bigtens[], tens[], tinytens[]; +extern unsigned char hexdig[]; + +extern Bigint *Balloc (int); +extern void Bfree (Bigint*); +extern void ULtof (ULong*, ULong*, Long, int); +extern void ULtod (ULong*, ULong*, Long, int); +extern void ULtodd (ULong*, ULong*, Long, int); +extern void ULtoQ (ULong*, ULong*, Long, int); +extern void ULtox (UShort*, ULong*, Long, int); +extern void ULtoxL (ULong*, ULong*, Long, int); +extern ULong any_on (Bigint*, int); +extern double b2d (Bigint*, int*); +extern int cmp (Bigint*, Bigint*); +extern void copybits (ULong*, int, Bigint*); +extern Bigint *d2b (double, int*, int*); +extern void decrement (Bigint*); +extern Bigint *diff (Bigint*, Bigint*); +extern int gethex (const char**, FPI*, Long*, Bigint**, int); +extern void hexdig_init_D2A(void); +extern int hexnan (const char**, FPI*, ULong*); +extern int hi0bits_D2A (ULong); +extern Bigint *i2b (int); +extern Bigint *increment (Bigint*); +extern int lo0bits (ULong*); +extern Bigint *lshift (Bigint*, int); +extern int match (const char**, char*); +extern Bigint *mult (Bigint*, Bigint*); +extern Bigint *multadd (Bigint*, int, int); +extern char *nrv_alloc (char*, char **, int); +extern Bigint *pow5mult (Bigint*, int); +extern int quorem (Bigint*, Bigint*); +extern double ratio (Bigint*, Bigint*); +extern void rshift (Bigint*, int); +extern char *rv_alloc (int); +extern Bigint *s2b (const char*, int, int, ULong, int); +extern Bigint *set_ones (Bigint*, int); +extern char *strcp (char*, const char*); +extern Bigint *sum (Bigint*, Bigint*); +extern int trailz (Bigint*); +extern double ulp (dbl_union *); + +#ifdef __cplusplus +} +#endif +/* + * NAN_WORD0 and NAN_WORD1 are only referenced in strtod.c. Prior to + * 20050115, they used to be hard-wired here (to 0x7ff80000 and 0, + * respectively), but now are determined by compiling and running + * qnan.c to generate gd_qnan.h, which specifies d_QNAN0 and d_QNAN1. + * Formerly gdtoaimp.h recommended supplying suitable -DNAN_WORD0=... + * and -DNAN_WORD1=... values if necessary. This should still work. + * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) + */ +#ifdef IEEE_Arith +#ifndef NO_INFNAN_CHECK +#undef INFNAN_CHECK +#define INFNAN_CHECK +#endif +#ifdef IEEE_MC68k +#define _0 0 +#define _1 1 +#ifndef NAN_WORD0 +#define NAN_WORD0 d_QNAN0 +#endif +#ifndef NAN_WORD1 +#define NAN_WORD1 d_QNAN1 +#endif +#else +#define _0 1 +#define _1 0 +#ifndef NAN_WORD0 +#define NAN_WORD0 d_QNAN1 +#endif +#ifndef NAN_WORD1 +#define NAN_WORD1 d_QNAN0 +#endif +#endif +#else +#undef INFNAN_CHECK +#endif + +#undef SI +#ifdef Sudden_Underflow +#define SI 1 +#else +#define SI 0 +#endif + +#endif /* GDTOAIMP_H_INCLUDED */ diff --git a/libc/mingw/gdtoa/gethex.c b/libc/mingw/gdtoa/gethex.c new file mode 100644 index 000000000..276175453 --- /dev/null +++ b/libc/mingw/gdtoa/gethex.c @@ -0,0 +1,340 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +#ifdef USE_LOCALE +#include "locale.h" +#endif + +int gethex (const char **sp, FPI *fpi, Long *expo, Bigint **bp, int sign) +{ + Bigint *b; + const unsigned char *decpt, *s0, *s, *s1; + int big, esign, havedig, irv, j, k, n, n0, nbits, up, zret; + ULong L, lostbits, *x; + Long e, e1; +#ifdef USE_LOCALE + int i; + const unsigned char *decimalpoint; +#ifdef NO_LOCALE_CACHE + decimalpoint = (unsigned char *)localeconv()->decimal_point; +#else + static unsigned char *decimalpoint_cache; + if (!(s0 = decimalpoint_cache)) { + s0 = (unsigned char *)localeconv()->decimal_point; + decimalpoint_cache = (unsigned char *) + MALLOC(strlen((char *)s0) + 1); + if (decimalpoint_cache) { + strcpy((char *)decimalpoint_cache, (char *)s0); + s0 = decimalpoint_cache; + } + } + decimalpoint = s0; +#endif +#endif + + if (!hexdig['0']) + hexdig_init_D2A(); + *bp = 0; + havedig = 0; + s0 = *(const unsigned char **)sp + 2; + while(s0[havedig] == '0') + havedig++; + s0 += havedig; + s = s0; + decpt = 0; + zret = 0; + e = 0; + if (hexdig[*s]) + havedig++; + else { + zret = 1; +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s != '.') + goto pcheck; + decpt = ++s; +#endif + if (!hexdig[*s]) + goto pcheck; + while(*s == '0') + s++; + if (hexdig[*s]) + zret = 0; + havedig = 1; + s0 = s; + } + while(hexdig[*s]) + s++; +#ifdef USE_LOCALE + if (*s == *decimalpoint && !decpt) { + for(i = 1; decimalpoint[i]; ++i) { + if (s[i] != decimalpoint[i]) + goto pcheck; + } + decpt = s += i; +#else + if (*s == '.' && !decpt) { + decpt = ++s; +#endif + while(hexdig[*s]) + s++; + }/*}*/ + if (decpt) + e = -(((Long)(s-decpt)) << 2); + pcheck: + s1 = s; + big = esign = 0; + switch(*s) { + case 'p': + case 'P': + switch(*++s) { + case '-': + esign = 1; + /* no break */ + case '+': + s++; + } + if ((n = hexdig[*s]) == 0 || n > 0x19) { + s = s1; + break; + } + e1 = n - 0x10; + while((n = hexdig[*++s]) !=0 && n <= 0x19) { + if (e1 & 0xf8000000) + big = 1; + e1 = 10*e1 + n - 0x10; + } + if (esign) + e1 = -e1; + e += e1; + } + *sp = (char*)s; + if (!havedig) + *sp = (char*)s0 - 1; + if (zret) + return STRTOG_Zero; + if (big) { + if (esign) { + switch(fpi->rounding) { + case FPI_Round_up: + if (sign) + break; + goto ret_tiny; + case FPI_Round_down: + if (!sign) + break; + goto ret_tiny; + } + goto retz; + ret_tiny: + b = Balloc(0); + b->wds = 1; + b->x[0] = 1; + goto dret; + } + switch(fpi->rounding) { + case FPI_Round_near: + goto ovfl1; + case FPI_Round_up: + if (!sign) + goto ovfl1; + goto ret_big; + case FPI_Round_down: + if (sign) + goto ovfl1; + goto ret_big; + } + ret_big: + nbits = fpi->nbits; + n0 = n = nbits >> kshift; + if (nbits & kmask) + ++n; + for(j = n, k = 0; j >>= 1; ++k); + *bp = b = Balloc(k); + b->wds = n; + for(j = 0; j < n0; ++j) + b->x[j] = ALL_ON; + if (n > n0) + b->x[j] = ULbits >> (ULbits - (nbits & kmask)); + *expo = fpi->emin; + return STRTOG_Normal | STRTOG_Inexlo; + } + n = s1 - s0 - 1; + for(k = 0; n > (1 << (kshift-2)) - 1; n >>= 1) + k++; + b = Balloc(k); + x = b->x; + n = 0; + L = 0; +#ifdef USE_LOCALE + for(i = 0; decimalpoint[i+1]; ++i); +#endif + while(s1 > s0) { +#ifdef USE_LOCALE + if (*--s1 == decimalpoint[i]) { + s1 -= i; + continue; + } +#else + if (*--s1 == '.') + continue; +#endif + if (n == ULbits) { + *x++ = L; + L = 0; + n = 0; + } + L |= (hexdig[*s1] & 0x0f) << n; + n += 4; + } + *x++ = L; + b->wds = n = x - b->x; + n = ULbits*n - hi0bits(L); + nbits = fpi->nbits; + lostbits = 0; + x = b->x; + if (n > nbits) { + n -= nbits; + if (any_on(b,n)) { + lostbits = 1; + k = n - 1; + if (x[k>>kshift] & 1 << (k & kmask)) { + lostbits = 2; + if (k > 0 && any_on(b,k)) + lostbits = 3; + } + } + rshift(b, n); + e += n; + } + else if (n < nbits) { + n = nbits - n; + b = lshift(b, n); + e -= n; + x = b->x; + } + if (e > fpi->emax) { + ovfl: + Bfree(b); + ovfl1: + SET_ERRNO(ERANGE); + return STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; + } + irv = STRTOG_Normal; + if (e < fpi->emin) { + irv = STRTOG_Denormal; + n = fpi->emin - e; + if (n >= nbits) { + switch (fpi->rounding) { + case FPI_Round_near: + if (n == nbits && (n < 2 || any_on(b,n-1))) + goto one_bit; + break; + case FPI_Round_up: + if (!sign) + goto one_bit; + break; + case FPI_Round_down: + if (sign) { + one_bit: + x[0] = b->wds = 1; + dret: + *bp = b; + *expo = fpi->emin; + SET_ERRNO(ERANGE); + return STRTOG_Denormal | STRTOG_Inexhi + | STRTOG_Underflow; + } + } + Bfree(b); + retz: + SET_ERRNO(ERANGE); + return STRTOG_Zero | STRTOG_Inexlo | STRTOG_Underflow; + } + k = n - 1; + if (lostbits) + lostbits = 1; + else if (k > 0) + lostbits = any_on(b,k); + if (x[k>>kshift] & 1 << (k & kmask)) + lostbits |= 2; + nbits -= n; + rshift(b,n); + e = fpi->emin; + } + if (lostbits) { + up = 0; + switch(fpi->rounding) { + case FPI_Round_zero: + break; + case FPI_Round_near: + if (lostbits & 2 + && (lostbits | x[0]) & 1) + up = 1; + break; + case FPI_Round_up: + up = 1 - sign; + break; + case FPI_Round_down: + up = sign; + } + if (up) { + k = b->wds; + b = increment(b); + x = b->x; + if (irv == STRTOG_Denormal) { + if (nbits == fpi->nbits - 1 + && x[nbits >> kshift] & 1 << (nbits & kmask)) + irv = STRTOG_Normal; + } + else if (b->wds > k + || ((n = nbits & kmask) !=0 + && hi0bits(x[k-1]) < 32-n)) { + rshift(b,1); + if (++e > fpi->emax) + goto ovfl; + } + irv |= STRTOG_Inexhi; + } + else + irv |= STRTOG_Inexlo; + } + *bp = b; + *expo = e; + return irv; +} diff --git a/libc/mingw/gdtoa/gmisc.c b/libc/mingw/gdtoa/gmisc.c new file mode 100644 index 000000000..157e87231 --- /dev/null +++ b/libc/mingw/gdtoa/gmisc.c @@ -0,0 +1,76 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +void rshift (Bigint *b, int k) +{ + ULong *x, *x1, *xe, y; + int n; + + x = x1 = b->x; + n = k >> kshift; + if (n < b->wds) { + xe = x + b->wds; + x += n; + if (k &= kmask) { + n = ULbits - k; + y = *x++ >> k; + while(x < xe) { + *x1++ = (y | (*x << n)) & ALL_ON; + y = *x++ >> k; + } + if ((*x1 = y) !=0) + x1++; + } + else + while(x < xe) + *x1++ = *x++; + } + if ((b->wds = x1 - b->x) == 0) + b->x[0] = 0; +} + +int trailz (Bigint *b) +{ + ULong L, *x, *xe; + int n = 0; + + x = b->x; + xe = x + b->wds; + for(n = 0; x < xe && !*x; x++) + n += ULbits; + if (x < xe) { + L = *x; + n += lo0bits(&L); + } + return n; +} diff --git a/libc/mingw/gdtoa/hd_init.c b/libc/mingw/gdtoa/hd_init.c new file mode 100644 index 000000000..5ee0caa73 --- /dev/null +++ b/libc/mingw/gdtoa/hd_init.c @@ -0,0 +1,49 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 2000 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +unsigned char hexdig[256]; + +static void htinit (unsigned char *h, unsigned char *s, int inc) +{ + int i, j; + for(i = 0; (j = s[i]) !=0; i++) + h[j] = i + inc; +} + +void hexdig_init_D2A (void) +{ +#define USC (unsigned char *) + htinit(hexdig, USC "0123456789", 0x10); + htinit(hexdig, USC "abcdef", 0x10 + 10); + htinit(hexdig, USC "ABCDEF", 0x10 + 10); +} diff --git a/libc/mingw/gdtoa/hexnan.c b/libc/mingw/gdtoa/hexnan.c new file mode 100644 index 000000000..4fa4c7745 --- /dev/null +++ b/libc/mingw/gdtoa/hexnan.c @@ -0,0 +1,139 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 2000 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +static void L_shift (ULong *x, ULong *x1, int i) +{ + int j; + + i = 8 - i; + i <<= 2; + j = ULbits - i; + do { + *x |= x[1] << j; + x[1] >>= i; + } while(++x < x1); +} + +int hexnan (const char **sp, FPI *fpi, ULong *x0) +{ + ULong c, h, *x, *x1, *xe; + const char *s; + int havedig, hd0, i, nbits; + + if (!hexdig['0']) + hexdig_init_D2A(); + nbits = fpi->nbits; + x = x0 + (nbits >> kshift); + if (nbits & kmask) + x++; + *--x = 0; + x1 = xe = x; + havedig = hd0 = i = 0; + s = *sp; + /* allow optional initial 0x or 0X */ + while((c = *(const unsigned char*)(s+1)) && c <= ' ') + ++s; + if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') + && *(const unsigned char*)(s+3) > ' ') + s += 2; + while((c = *(const unsigned char*)++s)) { + if (!(h = hexdig[c])) { + if (c <= ' ') { + if (hd0 < havedig) { + if (x < x1 && i < 8) + L_shift(x, x1, i); + if (x <= x0) { + i = 8; + continue; + } + hd0 = havedig; + *--x = 0; + x1 = x; + i = 0; + } + while(*(const unsigned char*)(s+1) <= ' ') + ++s; + if (s[1] == '0' && (s[2] == 'x' || s[2] == 'X') + && *(const unsigned char*)(s+3) > ' ') + s += 2; + continue; + } + if (/*(*/ c == ')' && havedig) { + *sp = s + 1; + break; + } +#ifndef GDTOA_NON_PEDANTIC_NANCHECK + do { + if (/*(*/ c == ')') { + *sp = s + 1; + break; + } + } while((c = *++s)); +#endif + return STRTOG_NaN; + } + havedig++; + if (++i > 8) { + if (x <= x0) + continue; + i = 1; + *--x = 0; + } + *x = (*x << 4) | (h & 0xf); + } + if (!havedig) + return STRTOG_NaN; + if (x < x1 && i < 8) + L_shift(x, x1, i); + if (x > x0) { + x1 = x0; + do *x1++ = *x++; + while(x <= xe); + do *x1++ = 0; + while(x1 <= xe); + } + else { + /* truncate high-order word if necessary */ + if ( (i = nbits & (ULbits-1)) !=0) + *xe &= ((ULong)0xffffffff) >> (ULbits - i); + } + for(x1 = xe;; --x1) { + if (*x1 != 0) + break; + if (x1 == x0) { + *x1 = 1; + break; + } + } + return STRTOG_NaNbits; +} diff --git a/libc/mingw/gdtoa/misc.c b/libc/mingw/gdtoa/misc.c new file mode 100644 index 000000000..43f31cea5 --- /dev/null +++ b/libc/mingw/gdtoa/misc.c @@ -0,0 +1,860 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 1999 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + + +#if defined(__MINGW32__) || defined(__MINGW64__) +/* we have to include windows.h before gdtoa + headers, otherwise defines cause conflicts. */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#define NLOCKS 2 + +#ifdef USE_WIN32_SL +/* Use spin locks. */ +static long dtoa_sl[NLOCKS]; + +#define ACQUIRE_DTOA_LOCK(n) \ + while (InterlockedCompareExchange (&dtoa_sl[n], 1, 0) != 0) \ + Sleep (0); +#define FREE_DTOA_LOCK(n) InterlockedExchange (&dtoa_sl[n], 0); + +#else /* USE_WIN32_SL */ + +#include +static CRITICAL_SECTION dtoa_CritSec[NLOCKS]; +static long dtoa_CS_init = 0; +/* + 1 = initializing + 2 = initialized + 3 = deleted +*/ +static void dtoa_lock_cleanup (void) +{ + long last_CS_init = InterlockedExchange (&dtoa_CS_init,3); + if (2 == last_CS_init) { + int i; + for (i = 0; i < NLOCKS; i++) + DeleteCriticalSection (&dtoa_CritSec[i]); + } +} + +static void dtoa_lock (int n) +{ + if (2 == dtoa_CS_init) { + EnterCriticalSection (&dtoa_CritSec[n]); + return; + } + else if (0 == dtoa_CS_init) { + long last_CS_init = InterlockedExchange (&dtoa_CS_init, 1); + if (0 == last_CS_init) { + int i; + for (i = 0; i < NLOCKS; i++) + InitializeCriticalSection (&dtoa_CritSec[i]); + atexit (dtoa_lock_cleanup); + dtoa_CS_init = 2; + } + else if (2 == last_CS_init) + dtoa_CS_init = 2; + } + /* Another thread is initializing. Wait. */ + while (1 == dtoa_CS_init) + Sleep (1); + + /* It had better be initialized now. */ + if (2 == dtoa_CS_init) + EnterCriticalSection(&dtoa_CritSec[n]); +} + +static void dtoa_unlock (int n) +{ + if (2 == dtoa_CS_init) + LeaveCriticalSection (&dtoa_CritSec[n]); +} + +#define ACQUIRE_DTOA_LOCK(n) dtoa_lock(n) +#define FREE_DTOA_LOCK(n) dtoa_unlock(n) +#endif /* USE_WIN32_SL */ + +#endif /* __MINGW32__ / __MINGW64__ */ + +#include "gdtoaimp.h" + +static Bigint *freelist[Kmax+1]; +#ifndef Omit_Private_Memory +#ifndef PRIVATE_MEM +#define PRIVATE_MEM 2304 +#endif +#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) +static double private_mem[PRIVATE_mem], *pmem_next = private_mem; +#endif + +Bigint *Balloc (int k) +{ + int x; + Bigint *rv; +#ifndef Omit_Private_Memory + unsigned int len; +#endif + + ACQUIRE_DTOA_LOCK(0); + /* The k > Kmax case does not need ACQUIRE_DTOA_LOCK(0), */ + /* but this case seems very unlikely. */ + if (k <= Kmax && (rv = freelist[k]) !=0) { + freelist[k] = rv->next; + } + else { + x = 1 << k; +#ifdef Omit_Private_Memory + rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); + if (rv == NULL) + return NULL; +#else + len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) + /sizeof(double); + if (k <= Kmax + && (size_t) (pmem_next - private_mem + len) <= PRIVATE_mem) + { + rv = (Bigint*)pmem_next; + pmem_next += len; + } + else + { + rv = (Bigint*)MALLOC(len*sizeof(double)); + if (rv == NULL) + return NULL; + } +#endif + rv->k = k; + rv->maxwds = x; + } + FREE_DTOA_LOCK(0); + rv->sign = rv->wds = 0; + return rv; +} + +void Bfree (Bigint *v) +{ + if (v) { + if (v->k > Kmax) + free((void*)v); + else { + ACQUIRE_DTOA_LOCK(0); + v->next = freelist[v->k]; + freelist[v->k] = v; + FREE_DTOA_LOCK(0); + } + } +} + +/* lo0bits(): Shift y so lowest bit is 1 and return the + * number of bits y was shifted. + * With GCC, we use an inline wrapper for __builtin_clz() + */ +#ifndef __GNUC__ +int lo0bits (ULong *y) +{ + int k; + ULong x = *y; + + if (x & 7) { + if (x & 1) + return 0; + if (x & 2) { + *y = x >> 1; + return 1; + } + *y = x >> 2; + return 2; + } + k = 0; + if (!(x & 0xffff)) { + k = 16; + x >>= 16; + } + if (!(x & 0xff)) { + k += 8; + x >>= 8; + } + if (!(x & 0xf)) { + k += 4; + x >>= 4; + } + if (!(x & 0x3)) { + k += 2; + x >>= 2; + } + if (!(x & 1)) { + k++; + x >>= 1; + if (!x) + return 32; + } + *y = x; + return k; +} +#endif /* __GNUC__ */ + +Bigint *multadd (Bigint *b, int m, int a) /* multiply by m and add a */ +{ + int i, wds; +#ifdef ULLong + ULong *x; + ULLong carry, y; +#else + ULong carry, *x, y; +#ifdef Pack_32 + ULong xi, z; +#endif +#endif + Bigint *b1; + + wds = b->wds; + x = b->x; + i = 0; + carry = a; + do { +#ifdef ULLong + y = *x * (ULLong)m + carry; + carry = y >> 32; + *x++ = y & 0xffffffffUL; +#else +#ifdef Pack_32 + xi = *x; + y = (xi & 0xffff) * m + carry; + z = (xi >> 16) * m + (y >> 16); + carry = z >> 16; + *x++ = (z << 16) + (y & 0xffff); +#else + y = *x * m + carry; + carry = y >> 16; + *x++ = y & 0xffff; +#endif +#endif + } while(++i < wds); + if (carry) { + if (wds >= b->maxwds) { + b1 = Balloc(b->k+1); + if (b1 == NULL) + return NULL; + Bcopy(b1, b); + Bfree(b); + b = b1; + } + b->x[wds++] = carry; + b->wds = wds; + } + return b; +} + +/* hi0bits(); + * With GCC, we use an inline wrapper for __builtin_clz() + */ +#ifndef __GNUC__ +int hi0bits_D2A (ULong x) +{ + int k = 0; + + if (!(x & 0xffff0000)) { + k = 16; + x <<= 16; + } + if (!(x & 0xff000000)) { + k += 8; + x <<= 8; + } + if (!(x & 0xf0000000)) { + k += 4; + x <<= 4; + } + if (!(x & 0xc0000000)) { + k += 2; + x <<= 2; + } + if (!(x & 0x80000000)) { + k++; + if (!(x & 0x40000000)) + return 32; + } + return k; +} +#endif /* __GNUC__ */ + +Bigint *i2b (int i) +{ + Bigint *b; + + b = Balloc(1); + if (b == NULL) + return NULL; + b->x[0] = i; + b->wds = 1; + return b; +} + +Bigint *mult (Bigint *a, Bigint *b) +{ + Bigint *c; + int k, wa, wb, wc; + ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; + ULong y; +#ifdef ULLong + ULLong carry, z; +#else + ULong carry, z; +#ifdef Pack_32 + ULong z2; +#endif +#endif + + if (a->wds < b->wds) { + c = a; + a = b; + b = c; + } + k = a->k; + wa = a->wds; + wb = b->wds; + wc = wa + wb; + if (wc > a->maxwds) + k++; + c = Balloc(k); + if (c == NULL) + return NULL; + for(x = c->x, xa = x + wc; x < xa; x++) + *x = 0; + xa = a->x; + xae = xa + wa; + xb = b->x; + xbe = xb + wb; + xc0 = c->x; +#ifdef ULLong + for(; xb < xbe; xc0++) { + if ( (y = *xb++) !=0) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * (ULLong)y + *xc + carry; + carry = z >> 32; + *xc++ = z & 0xffffffffUL; + } while(x < xae); + *xc = carry; + } + } +#else +#ifdef Pack_32 + for(; xb < xbe; xb++, xc0++) { + if ( (y = *xb & 0xffff) !=0) { + x = xa; + xc = xc0; + carry = 0; + do { + z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; + carry = z >> 16; + z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; + carry = z2 >> 16; + Storeinc(xc, z2, z); + } while(x < xae); + *xc = carry; + } + if ( (y = *xb >> 16) !=0) { + x = xa; + xc = xc0; + carry = 0; + z2 = *xc; + do { + z = (*x & 0xffff) * y + (*xc >> 16) + carry; + carry = z >> 16; + Storeinc(xc, z, z2); + z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; + carry = z2 >> 16; + } while(x < xae); + *xc = z2; + } + } +#else + for(; xb < xbe; xc0++) { + if ( (y = *xb++) !=0) { + x = xa; + xc = xc0; + carry = 0; + do { + z = *x++ * y + *xc + carry; + carry = z >> 16; + *xc++ = z & 0xffff; + } while(x < xae); + *xc = carry; + } + } +#endif +#endif + for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; + c->wds = wc; + return c; +} + +static Bigint *p5s; + +Bigint *pow5mult (Bigint *b, int k) +{ + Bigint *b1, *p5, *p51; + int i; + static int p05[3] = { 5, 25, 125 }; + + if ( (i = k & 3) !=0) + { + b = multadd(b, p05[i-1], 0); + if (b == NULL) + return NULL; + } + if (!(k >>= 2)) + return b; + if ((p5 = p5s) == 0) { + /* first time */ +#ifdef MULTIPLE_THREADS + ACQUIRE_DTOA_LOCK(1); + if (!(p5 = p5s)) { + p5 = p5s = i2b(625); + if (p5 == NULL) + return NULL; + p5->next = 0; + } + FREE_DTOA_LOCK(1); +#else + p5 = p5s = i2b(625); + if (p5 == NULL) + return NULL; + p5->next = 0; +#endif + } + for(;;) { + if (k & 1) { + b1 = mult(b, p5); + if (b1 == NULL) + return NULL; + Bfree(b); + b = b1; + } + if (!(k >>= 1)) + break; + if ((p51 = p5->next) == 0) { +#ifdef MULTIPLE_THREADS + ACQUIRE_DTOA_LOCK(1); + if (!(p51 = p5->next)) { + p51 = p5->next = mult(p5,p5); + if (p51 == NULL) + return NULL; + p51->next = 0; + } + FREE_DTOA_LOCK(1); +#else + p51 = p5->next = mult(p5,p5); + if (p51 == NULL) + return NULL; + p51->next = 0; +#endif + } + p5 = p51; + } + return b; +} + +Bigint *lshift (Bigint *b, int k) +{ + int i, k1, n, n1; + Bigint *b1; + ULong *x, *x1, *xe, z; + + n = k >> kshift; + k1 = b->k; + n1 = n + b->wds + 1; + for(i = b->maxwds; n1 > i; i <<= 1) + k1++; + b1 = Balloc(k1); + if (b1 == NULL) + return NULL; + x1 = b1->x; + for(i = 0; i < n; i++) + *x1++ = 0; + x = b->x; + xe = x + b->wds; + if (k &= kmask) { +#ifdef Pack_32 + k1 = 32 - k; + z = 0; + do { + *x1++ = *x << k | z; + z = *x++ >> k1; + } while(x < xe); + if ((*x1 = z) !=0) + ++n1; +#else + k1 = 16 - k; + z = 0; + do { + *x1++ = *x << k & 0xffff | z; + z = *x++ >> k1; + } while(x < xe); + if (*x1 = z) + ++n1; +#endif + } + else do + *x1++ = *x++; + while(x < xe); + b1->wds = n1 - 1; + Bfree(b); + return b1; +} + +int cmp (Bigint *a, Bigint *b) +{ + ULong *xa, *xa0, *xb, *xb0; + int i, j; + + i = a->wds; + j = b->wds; +#ifdef DEBUG + if (i > 1 && !a->x[i-1]) + Bug("cmp called with a->x[a->wds-1] == 0"); + if (j > 1 && !b->x[j-1]) + Bug("cmp called with b->x[b->wds-1] == 0"); +#endif + if (i -= j) + return i; + xa0 = a->x; + xa = xa0 + j; + xb0 = b->x; + xb = xb0 + j; + for(;;) { + if (*--xa != *--xb) + return *xa < *xb ? -1 : 1; + if (xa <= xa0) + break; + } + return 0; +} + +Bigint *diff (Bigint *a, Bigint *b) +{ + Bigint *c; + int i, wa, wb; + ULong *xa, *xae, *xb, *xbe, *xc; +#ifdef ULLong + ULLong borrow, y; +#else + ULong borrow, y; +#ifdef Pack_32 + ULong z; +#endif +#endif + + i = cmp(a,b); + if (!i) { + c = Balloc(0); + if (c == NULL) + return NULL; + c->wds = 1; + c->x[0] = 0; + return c; + } + if (i < 0) { + c = a; + a = b; + b = c; + i = 1; + } + else + i = 0; + c = Balloc(a->k); + if (c == NULL) + return NULL; + c->sign = i; + wa = a->wds; + xa = a->x; + xae = xa + wa; + wb = b->wds; + xb = b->x; + xbe = xb + wb; + xc = c->x; + borrow = 0; +#ifdef ULLong + do { + y = (ULLong)*xa++ - *xb++ - borrow; + borrow = y >> 32 & 1UL; + *xc++ = y & 0xffffffffUL; + } while(xb < xbe); + while(xa < xae) { + y = *xa++ - borrow; + borrow = y >> 32 & 1UL; + *xc++ = y & 0xffffffffUL; + } +#else +#ifdef Pack_32 + do { + y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } while(xb < xbe); + while(xa < xae) { + y = (*xa & 0xffff) - borrow; + borrow = (y & 0x10000) >> 16; + z = (*xa++ >> 16) - borrow; + borrow = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } +#else + do { + y = *xa++ - *xb++ - borrow; + borrow = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } while(xb < xbe); + while(xa < xae) { + y = *xa++ - borrow; + borrow = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } +#endif +#endif + while(!*--xc) + wa--; + c->wds = wa; + return c; +} + +double b2d (Bigint *a, int *e) +{ + ULong *xa, *xa0, w, y, z; + int k; + union _dbl_union d; +#define d0 word0(&d) +#define d1 word1(&d) + + xa0 = a->x; + xa = xa0 + a->wds; + y = *--xa; +#ifdef DEBUG + if (!y) Bug("zero y in b2d"); +#endif + k = hi0bits(y); + *e = 32 - k; +#ifdef Pack_32 + if (k < Ebits) { + d0 = Exp_1 | y >> (Ebits - k); + w = xa > xa0 ? *--xa : 0; + d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + if (k -= Ebits) { + d0 = Exp_1 | y << k | z >> (32 - k); + y = xa > xa0 ? *--xa : 0; + d1 = z << k | y >> (32 - k); + } + else { + d0 = Exp_1 | y; + d1 = z; + } +#else + if (k < Ebits + 16) { + z = xa > xa0 ? *--xa : 0; + d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; + w = xa > xa0 ? *--xa : 0; + y = xa > xa0 ? *--xa : 0; + d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; + goto ret_d; + } + z = xa > xa0 ? *--xa : 0; + w = xa > xa0 ? *--xa : 0; + k -= Ebits + 16; + d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; + y = xa > xa0 ? *--xa : 0; + d1 = w << k + 16 | y << k; +#endif + ret_d: + return dval(&d); +#undef d0 +#undef d1 +} + +Bigint *d2b (double dd, int *e, int *bits) +{ + Bigint *b; + union _dbl_union d; +#ifndef Sudden_Underflow + int i; +#endif + int de, k; + ULong *x, y, z; +#define d0 word0(&d) +#define d1 word1(&d) + d.d = dd; + +#ifdef Pack_32 + b = Balloc(1); +#else + b = Balloc(2); +#endif + if (b == NULL) + return NULL; + x = b->x; + + z = d0 & Frac_mask; + d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ +#ifdef Sudden_Underflow + de = (int)(d0 >> Exp_shift); + z |= Exp_msk11; +#else + if ( (de = (int)(d0 >> Exp_shift)) !=0) + z |= Exp_msk1; +#endif +#ifdef Pack_32 + if ( (y = d1) !=0) { + if ( (k = lo0bits(&y)) !=0) { + x[0] = y | z << (32 - k); + z >>= k; + } + else + x[0] = y; +#ifndef Sudden_Underflow + i = +#endif + b->wds = (x[1] = z) !=0 ? 2 : 1; + } + else { + k = lo0bits(&z); + x[0] = z; +#ifndef Sudden_Underflow + i = +#endif + b->wds = 1; + k += 32; + } +#else + if ( (y = d1) !=0) { + if ( (k = lo0bits(&y)) !=0) + if (k >= 16) { + x[0] = y | z << 32 - k & 0xffff; + x[1] = z >> k - 16 & 0xffff; + x[2] = z >> k; + i = 2; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16 | z << 16 - k & 0xffff; + x[2] = z >> k & 0xffff; + x[3] = z >> k+16; + i = 3; + } + else { + x[0] = y & 0xffff; + x[1] = y >> 16; + x[2] = z & 0xffff; + x[3] = z >> 16; + i = 3; + } + } + else { +#ifdef DEBUG + if (!z) + Bug("Zero passed to d2b"); +#endif + k = lo0bits(&z); + if (k >= 16) { + x[0] = z; + i = 0; + } + else { + x[0] = z & 0xffff; + x[1] = z >> 16; + i = 1; + } + k += 32; + } + while(!x[i]) + --i; + b->wds = i + 1; +#endif +#ifndef Sudden_Underflow + if (de) { +#endif + *e = de - Bias - (P-1) + k; + *bits = P - k; +#ifndef Sudden_Underflow + } + else { + *e = de - Bias - (P-1) + 1 + k; +#ifdef Pack_32 + *bits = 32*i - hi0bits(x[i-1]); +#else + *bits = (i+2)*16 - hi0bits(x[i]); +#endif + } +#endif + return b; +#undef d0 +#undef d1 +} + +const double +bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; +const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, 1e-256 }; + +const double +tens[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, + 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, + 1e20, 1e21, 1e22 +}; + +char *strcp_D2A (char *a, const char *b) +{ + while((*a = *b++)) + a++; + return a; +} + +#ifdef NO_STRING_H +void *memcpy_D2A (void *a1, void *b1, size_t len) +{ + char *a = (char*)a1, *ae = a + len; + char *b = (char*)b1, *a0 = a; + while(a < ae) + *a++ = *b++; + return a0; +} +#endif /* NO_STRING_H */ + diff --git a/libc/mingw/gdtoa/qnan.c b/libc/mingw/gdtoa/qnan.c new file mode 100644 index 000000000..c6bc3fe49 --- /dev/null +++ b/libc/mingw/gdtoa/qnan.c @@ -0,0 +1,116 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 2005 by David M. Gay +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that the copyright notice and this permission notice and warranty +disclaimer appear in supporting documentation, and that the name of +the author or any of his current or former employers not be used in +advertising or publicity pertaining to distribution of the software +without specific, written prior permission. + +THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN +NO EVENT SHALL THE AUTHOR OR ANY OF HIS CURRENT OR FORMER EMPLOYERS BE +LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, +WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS +SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +/* Program to compute quiet NaNs of various precisions (float, */ +/* double, and perhaps long double) on the current system, */ +/* provided the system uses binary IEEE (P754) arithmetic. */ +/* Note that one system's quiet NaN may be a signaling NaN on */ +/* another system. The IEEE arithmetic standards (P754, P854) */ +/* do not specify how to distinguish signaling NaNs from quiet */ +/* ones, and this detail varies across systems. The computed */ +/* NaN values are encoded in #defines for values for an */ +/* unsigned 32-bit integer type, called Ulong below, and */ +/* (for long double) perhaps as unsigned short values. Once */ +/* upon a time, there were PC compilers for Intel CPUs that */ +/* had sizeof(long double) = 10. Are such compilers still */ +/* distributed? */ + +#include +#include "gd_arith.h" + +#ifndef Long +#define Long long +#endif + +typedef unsigned Long Ulong; + +#undef HAVE_IEEE +#ifdef IEEE_8087 +#define _0 1 +#define _1 0 +#define HAVE_IEEE +#endif +#ifdef IEEE_MC68k +#define _0 0 +#define _1 1 +#define HAVE_IEEE +#endif + +#define UL (unsigned long) + +#ifdef MINGW_BUILD_GEN + int +main(void) +{ +#ifdef HAVE_IEEE + typedef union { + float f; + double d; + Ulong L[4]; +#ifndef NO_LONG_LONG +/* need u[8] instead of u[5] for 64 bit */ + unsigned short u[8]; + long double D; +#endif + } U; + U a, b, c; + int i; + a.L[0]=a.L[1]=a.L[2]=a.L[3]=0; + b.L[0]=b.L[1]=b.L[2]=b.L[3]=0; + c.L[0]=c.L[1]=c.L[2]=c.L[3]=0; + + a.L[0] = b.L[0] = 0x7f800000; + c.f = a.f - b.f; + printf("#define f_QNAN 0x%lx\n", UL c.L[0]); + a.L[_0] = b.L[_0] = 0x7ff00000; + a.L[_1] = b.L[_1] = 0; + c.d = a.d - b.d; /* quiet NaN */ + printf("#define d_QNAN0 0x%lx\n", UL c.L[0]); + printf("#define d_QNAN1 0x%lx\n", UL c.L[1]); +#ifdef NO_LONG_LONG + for(i = 0; i < 4; i++) + printf("#define ld_QNAN%d 0xffffffff\n", i); + for(i = 0; i < 5; i++) + printf("#define ldus_QNAN%d 0xffff\n", i); +#else + b.D = c.D = a.d; + if (printf("") < 0) + c.D = 37; /* never executed; just defeat optimization */ + a.L[2] = a.L[3] = 0; + a.D = b.D - c.D; + for(i = 0; i < 4; i++) + printf("#define ld_QNAN%d 0x%lx\n", i, UL a.L[i]); + for(i = 0; i < 5; i++) + printf("#define ldus_QNAN%d 0x%x\n", i, a.u[i]); +#endif +#endif /* HAVE_IEEE */ + return 0; + } +#endif diff --git a/libc/mingw/gdtoa/smisc.c b/libc/mingw/gdtoa/smisc.c new file mode 100644 index 000000000..1d09b44ea --- /dev/null +++ b/libc/mingw/gdtoa/smisc.c @@ -0,0 +1,149 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 1999 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +Bigint *s2b (const char *s, int nd0, int nd, ULong y9, int dplen) +{ + Bigint *b; + int i, k; + Long x, y; + + x = (nd + 8) / 9; + for(k = 0, y = 1; x > y; y <<= 1, k++) ; +#ifdef Pack_32 + b = Balloc(k); + b->x[0] = y9; + b->wds = 1; +#else + b = Balloc(k+1); + b->x[0] = y9 & 0xffff; + b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; +#endif + + i = 9; + if (9 < nd0) { + s += 9; + do b = multadd(b, 10, *s++ - '0'); + while(++i < nd0); + s += dplen; + } + else + s += dplen + 9; + for(; i < nd; i++) + b = multadd(b, 10, *s++ - '0'); + return b; +} + +double ratio (Bigint *a, Bigint *b) +{ + union _dbl_union da, db; + int k, ka, kb; + + dval(&da) = b2d(a, &ka); + dval(&db) = b2d(b, &kb); + k = ka - kb + ULbits*(a->wds - b->wds); + if (k > 0) + word0(&da) += k*Exp_msk1; + else { + k = -k; + word0(&db) += k*Exp_msk1; + } + return dval(&da) / dval(&db); +} + +#ifdef INFNAN_CHECK + +int match (const char **sp, char *t) +{ + int c, d; + const char *s = *sp; + + while( (d = *t++) !=0) { + if ((c = *++s) >= 'A' && c <= 'Z') + c += 'a' - 'A'; + if (c != d) + return 0; + } + *sp = s + 1; + return 1; +} +#endif /* INFNAN_CHECK */ + +void copybits (ULong *c, int n, Bigint *b) +{ + ULong *ce, *x, *xe; +#ifdef Pack_16 + int nw, nw1; +#endif + + ce = c + ((n-1) >> kshift) + 1; + x = b->x; +#ifdef Pack_32 + xe = x + b->wds; + while(x < xe) + *c++ = *x++; +#else + nw = b->wds; + nw1 = nw & 1; + for(xe = x + (nw - nw1); x < xe; x += 2) + Storeinc(c, x[1], x[0]); + if (nw1) + *c++ = *x; +#endif + while(c < ce) + *c++ = 0; +} + +ULong any_on (Bigint *b, int k) +{ + int n, nwds; + ULong *x, *x0, x1, x2; + + x = b->x; + nwds = b->wds; + n = k >> kshift; + if (n > nwds) + n = nwds; + else if (n < nwds && (k &= kmask)) { + x1 = x2 = x[n]; + x1 >>= k; + x1 <<= k; + if (x1 != x2) + return 1; + } + x0 = x; + x += n; + while(x > x0) + if (*--x) + return 1; + return 0; +} diff --git a/libc/mingw/gdtoa/strtodg.c b/libc/mingw/gdtoa/strtodg.c new file mode 100644 index 000000000..42ab9df3a --- /dev/null +++ b/libc/mingw/gdtoa/strtodg.c @@ -0,0 +1,979 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998-2001 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +#ifdef USE_LOCALE +#include "locale.h" +#endif + +static const int +fivesbits[] = { 0, 3, 5, 7, 10, 12, 14, 17, 19, 21, + 24, 26, 28, 31, 33, 35, 38, 40, 42, 45, + 47, 49, 52 +}; + +Bigint *increment (Bigint *b) +{ + ULong *x, *xe; + Bigint *b1; +#ifdef Pack_16 + ULong carry = 1, y; +#endif + + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + do { + if (*x < (ULong)0xffffffffL) { + ++*x; + return b; + } + *x++ = 0; + } while(x < xe); +#else + do { + y = *x + carry; + carry = y >> 16; + *x++ = y & 0xffff; + if (!carry) + return b; + } while(x < xe); + if (carry) +#endif + { + if (b->wds >= b->maxwds) { + b1 = Balloc(b->k+1); + Bcopy(b1,b); + Bfree(b); + b = b1; + } + b->x[b->wds++] = 1; + } + return b; +} + +void decrement (Bigint *b) +{ + ULong *x, *xe; +#ifdef Pack_16 + ULong borrow = 1, y; +#endif + + x = b->x; + xe = x + b->wds; +#ifdef Pack_32 + do { + if (*x) { + --*x; + break; + } + *x++ = 0xffffffffL; + } while(x < xe); +#else + do { + y = *x - borrow; + borrow = (y & 0x10000) >> 16; + *x++ = y & 0xffff; + } while(borrow && x < xe); +#endif +} + +static int all_on (Bigint *b, int n) +{ + ULong *x, *xe; + + x = b->x; + xe = x + (n >> kshift); + while(x < xe) + if ((*x++ & ALL_ON) != ALL_ON) + return 0; + if (n &= kmask) + return ((*x | (ALL_ON << n)) & ALL_ON) == ALL_ON; + return 1; +} + +Bigint *set_ones (Bigint *b, int n) +{ + int k; + ULong *x, *xe; + + k = (n + ((1 << kshift) - 1)) >> kshift; + if (b->k < k) { + Bfree(b); + b = Balloc(k); + } + k = n >> kshift; + if (n &= kmask) + k++; + b->wds = k; + x = b->x; + xe = x + k; + while(x < xe) + *x++ = ALL_ON; + if (n) + x[-1] >>= ULbits - n; + return b; +} + +static int rvOK (dbl_union *d, FPI *fpi, Long *expo, ULong *bits, + int exact, int rd, int *irv) +{ + Bigint *b; + ULong carry, inex, lostbits; + int bdif, e, j, k, k1, nb, rv; + + carry = rv = 0; + b = d2b(dval(d), &e, &bdif); + bdif -= nb = fpi->nbits; + e += bdif; + if (bdif <= 0) { + if (exact) + goto trunc; + goto ret; + } + if (P == nb) { + if ( +#ifndef IMPRECISE_INEXACT + exact && +#endif + fpi->rounding == +#ifdef RND_PRODQUOT + FPI_Round_near +#else + Flt_Rounds +#endif + ) goto trunc; + goto ret; + } + switch(rd) { + case 1: /* round down (toward -Infinity) */ + goto trunc; + case 2: /* round up (toward +Infinity) */ + break; + default: /* round near */ + k = bdif - 1; + if (k < 0) + goto trunc; + if (!k) { + if (!exact) + goto ret; + if (b->x[0] & 2) + break; + goto trunc; + } + if (b->x[k>>kshift] & ((ULong)1 << (k & kmask))) + break; + goto trunc; + } + /* "break" cases: round up 1 bit, then truncate; bdif > 0 */ + carry = 1; + trunc: + inex = lostbits = 0; + if (bdif > 0) { + if ( (lostbits = any_on(b, bdif)) !=0) + inex = STRTOG_Inexlo; + rshift(b, bdif); + if (carry) { + inex = STRTOG_Inexhi; + b = increment(b); + if ( (j = nb & kmask) !=0) + j = ULbits - j; + if (hi0bits(b->x[b->wds - 1]) != j) { + if (!lostbits) + lostbits = b->x[0] & 1; + rshift(b, 1); + e++; + } + } + } + else if (bdif < 0) + b = lshift(b, -bdif); + if (e < fpi->emin) { + k = fpi->emin - e; + e = fpi->emin; + if (k > nb || fpi->sudden_underflow) { + b->wds = inex = 0; + *irv = STRTOG_Underflow | STRTOG_Inexlo; + } + else { + k1 = k - 1; + if (k1 > 0 && !lostbits) + lostbits = any_on(b, k1); + if (!lostbits && !exact) + goto ret; + lostbits |= + carry = b->x[k1>>kshift] & (1 << (k1 & kmask)); + rshift(b, k); + *irv = STRTOG_Denormal; + if (carry) { + b = increment(b); + inex = STRTOG_Inexhi | STRTOG_Underflow; + } + else if (lostbits) + inex = STRTOG_Inexlo | STRTOG_Underflow; + } + } + else if (e > fpi->emax) { + e = fpi->emax + 1; + *irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; + SET_ERRNO(ERANGE); + b->wds = inex = 0; + } + *expo = e; + copybits(bits, nb, b); + *irv |= inex; + rv = 1; + ret: + Bfree(b); + return rv; +} + +static int mantbits (dbl_union *d) +{ + ULong L; + if ( (L = word1(d)) !=0) + return P - lo0bits(&L); + L = word0(d) | Exp_msk1; + return P - 32 - lo0bits(&L); +} + +int __strtodg (const char *s00, char **se, FPI *fpi, Long *expo, ULong *bits) +{ + int abe, abits, asub; + int bb0, bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, decpt, denorm; + int dsign, e, e1, e2, emin, esign, finished, i, inex, irv; + int j, k, nbits, nd, nd0, nf, nz, nz0, rd, rvbits, rve, rve1, sign; + int sudden_underflow; + const char *s, *s0, *s1; + double adj0, tol; + Long L; + union _dbl_union adj, rv; + ULong *b, *be, y, z; + Bigint *ab, *bb, *bb1, *bd, *bd0, *bs, *delta, *rvb, *rvb0; +#ifdef USE_LOCALE /*{{*/ +#ifdef NO_LOCALE_CACHE + char *decimalpoint = localeconv()->decimal_point; + int dplen = strlen(decimalpoint); +#else + char *decimalpoint; + static char *decimalpoint_cache; + static int dplen; + if (!(s0 = decimalpoint_cache)) { + s0 = localeconv()->decimal_point; + if ((decimalpoint_cache = (char*)MALLOC(strlen(s0) + 1))) { + strcpy(decimalpoint_cache, s0); + s0 = decimalpoint_cache; + } + dplen = strlen(s0); + } + decimalpoint = (char*)s0; +#endif /*NO_LOCALE_CACHE*/ +#else /*USE_LOCALE}{*/ +#define dplen 1 +#endif /*USE_LOCALE}}*/ + + irv = STRTOG_Zero; + denorm = sign = nz0 = nz = 0; + dval(&rv) = 0.; + rvb = 0; + nbits = fpi->nbits; + for(s = s00;;s++) switch(*s) { + case '-': + sign = 1; + /* no break */ + case '+': + if (*++s) + goto break2; + /* no break */ + case 0: + sign = 0; + irv = STRTOG_NoNumber; + s = s00; + goto ret; + case '\t': + case '\n': + case '\v': + case '\f': + case '\r': + case ' ': + continue; + default: + goto break2; + } + break2: + if (*s == '0') { +#ifndef NO_HEX_FP + switch(s[1]) { + case 'x': + case 'X': + irv = gethex(&s, fpi, expo, &rvb, sign); + if (irv == STRTOG_NoNumber) { + s = s00; + sign = 0; + } + goto ret; + } +#endif + nz0 = 1; + while(*++s == '0') ; + if (!*s) + goto ret; + } + sudden_underflow = fpi->sudden_underflow; + s0 = s; + y = z = 0; + for(decpt = nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) + if (nd < 9) + y = 10*y + c - '0'; + else if (nd < 16) + z = 10*z + c - '0'; + nd0 = nd; +#ifdef USE_LOCALE + if (c == *decimalpoint) { + for(i = 1; decimalpoint[i]; ++i) + if (s[i] != decimalpoint[i]) + goto dig_done; + s += i; + c = *s; +#else + if (c == '.') { + c = *++s; +#endif + decpt = 1; + if (!nd) { + for(; c == '0'; c = *++s) + nz++; + if (c > '0' && c <= '9') { + s0 = s; + nf += nz; + nz = 0; + goto have_dig; + } + goto dig_done; + } + for(; c >= '0' && c <= '9'; c = *++s) { + have_dig: + nz++; + if (c -= '0') { + nf += nz; + for(i = 1; i < nz; i++) + if (nd++ < 9) + y *= 10; + else if (nd <= DBL_DIG + 1) + z *= 10; + if (nd++ < 9) + y = 10*y + c; + else if (nd <= DBL_DIG + 1) + z = 10*z + c; + nz = 0; + } + } + }/*}*/ + dig_done: + e = 0; + if (c == 'e' || c == 'E') { + if (!nd && !nz && !nz0) { + irv = STRTOG_NoNumber; + s = s00; + goto ret; + } + s00 = s; + esign = 0; + switch(c = *++s) { + case '-': + esign = 1; + case '+': + c = *++s; + } + if (c >= '0' && c <= '9') { + while(c == '0') + c = *++s; + if (c > '0' && c <= '9') { + L = c - '0'; + s1 = s; + while((c = *++s) >= '0' && c <= '9') + L = 10*L + c - '0'; + if (s - s1 > 8 || L > 19999) + /* Avoid confusion from exponents + * so large that e might overflow. + */ + e = 19999; /* safe for 16 bit ints */ + else + e = (int)L; + if (esign) + e = -e; + } + else + e = 0; + } + else + s = s00; + } + if (!nd) { + if (!nz && !nz0) { +#ifdef INFNAN_CHECK + /* Check for Nan and Infinity */ + if (!decpt) + switch(c) { + case 'i': + case 'I': + if (match(&s,"nf")) { + --s; + if (!match(&s,"inity")) + ++s; + irv = STRTOG_Infinite; + goto infnanexp; + } + break; + case 'n': + case 'N': + if (match(&s, "an")) { + irv = STRTOG_NaN; + *expo = fpi->emax + 1; +#ifndef No_Hex_NaN + if (*s == '(') /*)*/ + irv = hexnan(&s, fpi, bits); +#endif + goto infnanexp; + } + } +#endif /* INFNAN_CHECK */ + irv = STRTOG_NoNumber; + s = s00; + } + goto ret; + } + + irv = STRTOG_Normal; + e1 = e -= nf; + rd = 0; + switch(fpi->rounding & 3) { + case FPI_Round_up: + rd = 2 - sign; + break; + case FPI_Round_zero: + rd = 1; + break; + case FPI_Round_down: + rd = 1 + sign; + } + + /* Now we have nd0 digits, starting at s0, followed by a + * decimal point, followed by nd-nd0 digits. The number we're + * after is the integer represented by those digits times + * 10**e */ + + if (!nd0) + nd0 = nd; + k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1; + dval(&rv) = y; + if (k > 9) + dval(&rv) = tens[k - 9] * dval(&rv) + z; + bd0 = 0; + if (nbits <= P && nd <= DBL_DIG) { + if (!e) { + if (rvOK(&rv, fpi, expo, bits, 1, rd, &irv)) + goto ret; + } + else if (e > 0) { + if (e <= Ten_pmax) { + i = fivesbits[e] + mantbits(&rv) <= P; + /* rv = */ rounded_product(dval(&rv), tens[e]); + if (rvOK(&rv, fpi, expo, bits, i, rd, &irv)) + goto ret; + e1 -= e; + goto rv_notOK; + } + i = DBL_DIG - nd; + if (e <= Ten_pmax + i) { + /* A fancier test would sometimes let us do + * this for larger i values. + */ + e2 = e - i; + e1 -= i; + dval(&rv) *= tens[i]; + /* rv = */ rounded_product(dval(&rv), tens[e2]); + if (rvOK(&rv, fpi, expo, bits, 0, rd, &irv)) + goto ret; + e1 -= e2; + } + } +#ifndef Inaccurate_Divide + else if (e >= -Ten_pmax) { + /* rv = */ rounded_quotient(dval(&rv), tens[-e]); + if (rvOK(&rv, fpi, expo, bits, 0, rd, &irv)) + goto ret; + e1 -= e; + } +#endif + } + rv_notOK: + e1 += nd - k; + + /* Get starting approximation = rv * 10**e1 */ + + e2 = 0; + if (e1 > 0) { + if ( (i = e1 & 15) !=0) + dval(&rv) *= tens[i]; + if (e1 &= ~15) { + e1 >>= 4; + while(e1 >= (1 << (n_bigtens-1))) { + e2 += ((word0(&rv) & Exp_mask) + >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + dval(&rv) *= bigtens[n_bigtens-1]; + e1 -= 1 << (n_bigtens-1); + } + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + for(j = 0; e1 > 0; j++, e1 >>= 1) + if (e1 & 1) + dval(&rv) *= bigtens[j]; + } + } + else if (e1 < 0) { + e1 = -e1; + if ( (i = e1 & 15) !=0) + dval(&rv) /= tens[i]; + if (e1 &= ~15) { + e1 >>= 4; + while(e1 >= (1 << (n_bigtens-1))) { + e2 += ((word0(&rv) & Exp_mask) + >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + dval(&rv) *= tinytens[n_bigtens-1]; + e1 -= 1 << (n_bigtens-1); + } + e2 += ((word0(&rv) & Exp_mask) >> Exp_shift1) - Bias; + word0(&rv) &= ~Exp_mask; + word0(&rv) |= Bias << Exp_shift1; + for(j = 0; e1 > 0; j++, e1 >>= 1) + if (e1 & 1) + dval(&rv) *= tinytens[j]; + } + } + rvb = d2b(dval(&rv), &rve, &rvbits); /* rv = rvb * 2^rve */ + rve += e2; + if ((j = rvbits - nbits) > 0) { + rshift(rvb, j); + rvbits = nbits; + rve += j; + } + bb0 = 0; /* trailing zero bits in rvb */ + e2 = rve + rvbits - nbits; + if (e2 > fpi->emax + 1) + goto huge; + rve1 = rve + rvbits - nbits; + if (e2 < (emin = fpi->emin)) { + denorm = 1; + j = rve - emin; + if (j > 0) { + rvb = lshift(rvb, j); + rvbits += j; + } + else if (j < 0) { + rvbits += j; + if (rvbits <= 0) { + if (rvbits < -1) { + ufl: + rvb->wds = 0; + rvb->x[0] = 0; + *expo = emin; + irv = STRTOG_Underflow | STRTOG_Inexlo; + goto ret; + } + rvb->x[0] = rvb->wds = rvbits = 1; + } + else + rshift(rvb, -j); + } + rve = rve1 = emin; + if (sudden_underflow && e2 + 1 < emin) + goto ufl; + } + + /* Now the hard part -- adjusting rv to the correct value.*/ + + /* Put digits into bd: true value = bd * 10^e */ + + bd0 = s2b(s0, nd0, nd, y, dplen); + + for(;;) { + bd = Balloc(bd0->k); + Bcopy(bd, bd0); + bb = Balloc(rvb->k); + Bcopy(bb, rvb); + bbbits = rvbits - bb0; + bbe = rve + bb0; + bs = i2b(1); + + if (e >= 0) { + bb2 = bb5 = 0; + bd2 = bd5 = e; + } + else { + bb2 = bb5 = -e; + bd2 = bd5 = 0; + } + if (bbe >= 0) + bb2 += bbe; + else + bd2 -= bbe; + bs2 = bb2; + j = nbits + 1 - bbbits; + i = bbe + bbbits - nbits; + if (i < emin) /* denormal */ + j += i - emin; + bb2 += j; + bd2 += j; + i = bb2 < bd2 ? bb2 : bd2; + if (i > bs2) + i = bs2; + if (i > 0) { + bb2 -= i; + bd2 -= i; + bs2 -= i; + } + if (bb5 > 0) { + bs = pow5mult(bs, bb5); + bb1 = mult(bs, bb); + Bfree(bb); + bb = bb1; + } + bb2 -= bb0; + if (bb2 > 0) + bb = lshift(bb, bb2); + else if (bb2 < 0) + rshift(bb, -bb2); + if (bd5 > 0) + bd = pow5mult(bd, bd5); + if (bd2 > 0) + bd = lshift(bd, bd2); + if (bs2 > 0) + bs = lshift(bs, bs2); + asub = 1; + inex = STRTOG_Inexhi; + delta = diff(bb, bd); + if (delta->wds <= 1 && !delta->x[0]) + break; + dsign = delta->sign; + delta->sign = finished = 0; + L = 0; + i = cmp(delta, bs); + if (rd && i <= 0) { + irv = STRTOG_Normal; + if ( (finished = dsign ^ (rd&1)) !=0) { + if (dsign != 0) { + irv |= STRTOG_Inexhi; + goto adj1; + } + irv |= STRTOG_Inexlo; + if (rve1 == emin) + goto adj1; + for(i = 0, j = nbits; j >= ULbits; + i++, j -= ULbits) { + if (rvb->x[i] & ALL_ON) + goto adj1; + } + if (j > 1 && lo0bits(rvb->x + i) < j - 1) + goto adj1; + rve = rve1 - 1; + rvb = set_ones(rvb, rvbits = nbits); + break; + } + irv |= dsign ? STRTOG_Inexlo : STRTOG_Inexhi; + break; + } + if (i < 0) { + /* Error is less than half an ulp -- check for + * special case of mantissa a power of two. + */ + irv = dsign + ? STRTOG_Normal | STRTOG_Inexlo + : STRTOG_Normal | STRTOG_Inexhi; + if (dsign || bbbits > 1 || denorm || rve1 == emin) + break; + delta = lshift(delta,1); + if (cmp(delta, bs) > 0) { + irv = STRTOG_Normal | STRTOG_Inexlo; + goto drop_down; + } + break; + } + if (i == 0) { + /* exactly half-way between */ + if (dsign) { + if (denorm && all_on(rvb, rvbits)) { + /*boundary case -- increment exponent*/ + rvb->wds = 1; + rvb->x[0] = 1; + rve = emin + nbits - (rvbits = 1); + irv = STRTOG_Normal | STRTOG_Inexhi; + denorm = 0; + break; + } + irv = STRTOG_Normal | STRTOG_Inexlo; + } + else if (bbbits == 1) { + irv = STRTOG_Normal; + drop_down: + /* boundary case -- decrement exponent */ + if (rve1 == emin) { + irv = STRTOG_Normal | STRTOG_Inexhi; + if (rvb->wds == 1 && rvb->x[0] == 1) + sudden_underflow = 1; + break; + } + rve -= nbits; + rvb = set_ones(rvb, rvbits = nbits); + break; + } + else + irv = STRTOG_Normal | STRTOG_Inexhi; + if ((bbbits < nbits && !denorm) || !(rvb->x[0] & 1)) + break; + if (dsign) { + rvb = increment(rvb); + j = kmask & (ULbits - (rvbits & kmask)); + if (hi0bits(rvb->x[rvb->wds - 1]) != j) + rvbits++; + irv = STRTOG_Normal | STRTOG_Inexhi; + } + else { + if (bbbits == 1) + goto undfl; + decrement(rvb); + irv = STRTOG_Normal | STRTOG_Inexlo; + } + break; + } + if ((dval(&adj) = ratio(delta, bs)) <= 2.) { + adj1: + inex = STRTOG_Inexlo; + if (dsign) { + asub = 0; + inex = STRTOG_Inexhi; + } + else if (denorm && bbbits <= 1) { + undfl: + rvb->wds = 0; + rve = emin; + irv = STRTOG_Underflow | STRTOG_Inexlo; + break; + } + adj0 = dval(&adj) = 1.; + } + else { + adj0 = dval(&adj) *= 0.5; + if (dsign) { + asub = 0; + inex = STRTOG_Inexlo; + } + if (dval(&adj) < 2147483647.) { + L = adj0; + adj0 -= L; + switch(rd) { + case 0: + if (adj0 >= .5) + goto inc_L; + break; + case 1: + if (asub && adj0 > 0.) + goto inc_L; + break; + case 2: + if (!asub && adj0 > 0.) { + inc_L: + L++; + inex = STRTOG_Inexact - inex; + } + } + dval(&adj) = L; + } + } + y = rve + rvbits; + + /* adj *= ulp(&rv); */ + /* if (asub) rv -= adj; else rv += adj; */ + + if (!denorm && rvbits < nbits) { + rvb = lshift(rvb, j = nbits - rvbits); + rve -= j; + rvbits = nbits; + } + ab = d2b(dval(&adj), &abe, &abits); + if (abe < 0) + rshift(ab, -abe); + else if (abe > 0) + ab = lshift(ab, abe); + rvb0 = rvb; + if (asub) { + /* rv -= adj; */ + j = hi0bits(rvb->x[rvb->wds-1]); + rvb = diff(rvb, ab); + k = rvb0->wds - 1; + if (denorm) + /* do nothing */; + else if (rvb->wds <= k + || hi0bits( rvb->x[k]) > + hi0bits(rvb0->x[k])) { + /* unlikely; can only have lost 1 high bit */ + if (rve1 == emin) { + --rvbits; + denorm = 1; + } + else { + rvb = lshift(rvb, 1); + --rve; + --rve1; + L = finished = 0; + } + } + } + else { + rvb = sum(rvb, ab); + k = rvb->wds - 1; + if (k >= rvb0->wds + || hi0bits(rvb->x[k]) < hi0bits(rvb0->x[k])) { + if (denorm) { + if (++rvbits == nbits) + denorm = 0; + } + else { + rshift(rvb, 1); + rve++; + rve1++; + L = 0; + } + } + } + Bfree(ab); + Bfree(rvb0); + if (finished) + break; + + z = rve + rvbits; + if (y == z && L) { + /* Can we stop now? */ + tol = dval(&adj) * 5e-16; /* > max rel error */ + dval(&adj) = adj0 - .5; + if (dval(&adj) < -tol) { + if (adj0 > tol) { + irv |= inex; + break; + } + } + else if (dval(&adj) > tol && adj0 < 1. - tol) { + irv |= inex; + break; + } + } + bb0 = denorm ? 0 : trailz(rvb); + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(delta); + } + if (!denorm && (j = nbits - rvbits)) { + if (j > 0) + rvb = lshift(rvb, j); + else + rshift(rvb, -j); + rve -= j; + } + *expo = rve; + Bfree(bb); + Bfree(bd); + Bfree(bs); + Bfree(bd0); + Bfree(delta); + if (rve > fpi->emax) { + switch(fpi->rounding & 3) { + case FPI_Round_near: + goto huge; + case FPI_Round_up: + if (!sign) + goto huge; + break; + case FPI_Round_down: + if (sign) + goto huge; + } + /* Round to largest representable magnitude */ + Bfree(rvb); + rvb = 0; + irv = STRTOG_Normal | STRTOG_Inexlo; + *expo = fpi->emax; + b = bits; + be = b + ((fpi->nbits + 31) >> 5); + while(b < be) + *b++ = -1; + if ((j = fpi->nbits & 0x1f)) + *--be >>= (32 - j); + goto ret; + huge: + rvb->wds = 0; + irv = STRTOG_Infinite | STRTOG_Overflow | STRTOG_Inexhi; + SET_ERRNO(ERANGE); + infnanexp: + *expo = fpi->emax + 1; + } + ret: + if (denorm) { + if (sudden_underflow) { + rvb->wds = 0; + irv = STRTOG_Underflow | STRTOG_Inexlo; + SET_ERRNO(ERANGE); + } + else { + irv = (irv & ~STRTOG_Retmask) | + (rvb->wds > 0 ? STRTOG_Denormal : STRTOG_Zero); + if (irv & STRTOG_Inexact) { + irv |= STRTOG_Underflow; + SET_ERRNO(ERANGE); + } + } + } + if (se) + *se = (char *)s; + if (sign) + irv |= STRTOG_Neg; + if (rvb) { + copybits(bits, nbits, rvb); + Bfree(rvb); + } + return irv; +} diff --git a/libc/mingw/gdtoa/strtodnrp.c b/libc/mingw/gdtoa/strtodnrp.c new file mode 100644 index 000000000..9f13de64c --- /dev/null +++ b/libc/mingw/gdtoa/strtodnrp.c @@ -0,0 +1,87 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 2004 by David M. Gay. +All Rights Reserved +Based on material in the rest of /netlib/fp/gdota.tar.gz, +which is copyright (C) 1998, 2000 by Lucent Technologies. + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* This is a variant of strtod that works on Intel ia32 systems */ +/* with the default extended-precision arithmetic -- it does not */ +/* require setting the precision control to 53 bits. */ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +double __strtod (const char *s, char **sp) +{ + static FPI fpi = { 53, 1-1023-53+1, 2046-1023-53+1, 1, SI, Int_max }; + ULong bits[2]; + Long expo; + int k; + union { ULong L[2]; double d; } u; + + k = __strtodg (s, sp, &fpi, &expo, bits); + switch(k & STRTOG_Retmask) { + case STRTOG_NoNumber: + case STRTOG_Zero: + u.L[0] = u.L[1] = 0; + break; + + case STRTOG_Normal: + u.L[_1] = bits[0]; + u.L[_0] = (bits[1] & ~0x100000) | ((expo + 0x3ff + 52) << 20); + break; + + case STRTOG_Denormal: + u.L[_1] = bits[0]; + u.L[_0] = bits[1]; + break; + + case STRTOG_Infinite: + u.L[_0] = 0x7ff00000; + u.L[_1] = 0; + break; + + case STRTOG_NaN: + u.L[_1] = d_QNAN0; + u.L[_0] = d_QNAN1; + break; + + case STRTOG_NaNbits: + u.L[_0] = 0x7ff00000 | bits[1]; + u.L[_1] = bits[0]; + } + if (k & STRTOG_Neg) + u.L[_0] |= 0x80000000L; + return u.d; +} + +double __cdecl +__mingw_strtod (const char * __restrict__ src, char ** __restrict__ endptr) + __attribute__((alias("__strtod"))); + diff --git a/libc/mingw/gdtoa/strtof.c b/libc/mingw/gdtoa/strtof.c new file mode 100644 index 000000000..5f5208af3 --- /dev/null +++ b/libc/mingw/gdtoa/strtof.c @@ -0,0 +1,77 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 2000 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +float __strtof (const char *s, char **sp) +{ + static FPI fpi0 = { 24, 1-127-24+1, 254-127-24+1, 1, SI, Int_max }; + ULong bits[1]; + Long expo; + int k; + union { ULong L[1]; float f; } u = { { 0 } }; +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif + + k = __strtodg(s, sp, fpi, &expo, bits); + switch(k & STRTOG_Retmask) { + case STRTOG_NoNumber: + case STRTOG_Zero: + u.L[0] = 0; + break; + + case STRTOG_Normal: + case STRTOG_NaNbits: + u.L[0] = (bits[0] & 0x7fffff) | ((expo + 0x7f + 23) << 23); + break; + + case STRTOG_Denormal: + u.L[0] = bits[0]; + break; + + case STRTOG_Infinite: + u.L[0] = 0x7f800000; + break; + + case STRTOG_NaN: + u.L[0] = f_QNAN; + } + if (k & STRTOG_Neg) + u.L[0] |= 0x80000000L; + return u.f; +} + +float __cdecl +__mingw_strtof (const char * __restrict__ src, char ** __restrict__ endptr) + __attribute__((alias("__strtof"))); diff --git a/libc/mingw/gdtoa/strtopx.c b/libc/mingw/gdtoa/strtopx.c new file mode 100644 index 000000000..b077105be --- /dev/null +++ b/libc/mingw/gdtoa/strtopx.c @@ -0,0 +1,125 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 2000 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +#undef _0 +#undef _1 + +/* one or the other of IEEE_MC68k or IEEE_8087 should be #defined */ + +#ifdef IEEE_MC68k +#define _0 0 +#define _1 1 +#define _2 2 +#define _3 3 +#define _4 4 +#endif +#ifdef IEEE_8087 +#define _0 4 +#define _1 3 +#define _2 2 +#define _3 1 +#define _4 0 +#endif + +typedef union lD { + UShort L[5]; + long double D; +} lD; + +static int __strtopx (const char *s, char **sp, lD *V) +{ + static FPI fpi0 = { 64, 1-16383-64+1, 32766 - 16383 - 64 + 1, 1, SI, + Int_max }; + ULong bits[2]; + Long expo; + int k; + UShort *L = & (V->L[0]); +#ifdef Honor_FLT_ROUNDS +#include "gdtoa_fltrnds.h" +#else +#define fpi &fpi0 +#endif + V->D = 0.0L; + + k = __strtodg(s, sp, fpi, &expo, bits); + switch(k & STRTOG_Retmask) { + case STRTOG_NoNumber: + case STRTOG_Zero: + L[0] = L[1] = L[2] = L[3] = L[4] = 0; + break; + + case STRTOG_Denormal: + L[_0] = 0; + goto normal_bits; + + case STRTOG_Normal: + case STRTOG_NaNbits: + L[_0] = expo + 0x3fff + 63; + normal_bits: + L[_4] = (UShort)bits[0]; + L[_3] = (UShort)(bits[0] >> 16); + L[_2] = (UShort)bits[1]; + L[_1] = (UShort)(bits[1] >> 16); + break; + + case STRTOG_Infinite: + L[_0] = 0x7fff; + L[_1] = 0x8000; + L[_2] = L[_3] = L[_4] = 0; + break; + + case STRTOG_NaN: + L[0] = ldus_QNAN0; + L[1] = ldus_QNAN1; + L[2] = ldus_QNAN2; + L[3] = ldus_QNAN3; + L[4] = ldus_QNAN4; + } + if (k & STRTOG_Neg) + L[_0] |= 0x8000; + return k; +} + +long double __cdecl +__strtold (const char * __restrict__ src, char ** __restrict__ endptr) +{ + lD ret; + ret.D = 0.0L; + __strtopx(src, endptr, &ret); + return ret.D; +} + +long double __cdecl +__mingw_strtold (const char * __restrict__ src, char ** __restrict__ endptr) + __attribute__((alias("__strtold"))); + diff --git a/libc/mingw/gdtoa/sum.c b/libc/mingw/gdtoa/sum.c new file mode 100644 index 000000000..8823541ea --- /dev/null +++ b/libc/mingw/gdtoa/sum.c @@ -0,0 +1,91 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +Bigint *sum (Bigint *a, Bigint *b) +{ + Bigint *c; + ULong carry, *xc, *xa, *xb, *xe, y; +#ifdef Pack_32 + ULong z; +#endif + + if (a->wds < b->wds) { + c = b; b = a; a = c; + } + c = Balloc(a->k); + c->wds = a->wds; + carry = 0; + xa = a->x; + xb = b->x; + xc = c->x; + xe = xc + b->wds; +#ifdef Pack_32 + do { + y = (*xa & 0xffff) + (*xb & 0xffff) + carry; + carry = (y & 0x10000) >> 16; + z = (*xa++ >> 16) + (*xb++ >> 16) + carry; + carry = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } while(xc < xe); + xe += a->wds - b->wds; + while(xc < xe) { + y = (*xa & 0xffff) + carry; + carry = (y & 0x10000) >> 16; + z = (*xa++ >> 16) + carry; + carry = (z & 0x10000) >> 16; + Storeinc(xc, z, y); + } +#else + do { + y = *xa++ + *xb++ + carry; + carry = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } while(xc < xe); + xe += a->wds - b->wds; + while(xc < xe) { + y = *xa++ + carry; + carry = (y & 0x10000) >> 16; + *xc++ = y & 0xffff; + } +#endif + if (carry) { + if (c->wds == c->maxwds) { + b = Balloc(c->k + 1); + Bcopy(b, c); + Bfree(c); + c = b; + } + c->x[c->wds++] = 1; + } + return c; +} diff --git a/libc/mingw/gdtoa/ulp.c b/libc/mingw/gdtoa/ulp.c new file mode 100644 index 000000000..bfa9bdeea --- /dev/null +++ b/libc/mingw/gdtoa/ulp.c @@ -0,0 +1,61 @@ +/**************************************************************** + +The author of this software is David M. Gay. + +Copyright (C) 1998, 1999 by Lucent Technologies +All Rights Reserved + +Permission to use, copy, modify, and distribute this software and +its documentation for any purpose and without fee is hereby +granted, provided that the above copyright notice appear in all +copies and that both that the copyright notice and this +permission notice and warranty disclaimer appear in supporting +documentation, and that the name of Lucent or any of its entities +not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior +permission. + +LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, +INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. +IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY +SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER +IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, +ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF +THIS SOFTWARE. + +****************************************************************/ + +/* Please send bug reports to David M. Gay (dmg at acm dot org, + * with " at " changed at "@" and " dot " changed to "."). */ + +#include "gdtoaimp.h" + +double ulp (dbl_union *x) +{ + Long L; + union _dbl_union a; + + L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; +#ifndef Sudden_Underflow + if (L > 0) { +#endif + word0(&a) = L; + word1(&a) = 0; +#ifndef Sudden_Underflow + } + else { + L = -L >> Exp_shift; + if (L < Exp_shift) { + word0(&a) = 0x80000 >> L; + word1(&a) = 0; + } + else { + word0(&a) = 0; + L -= Exp_shift; + word1(&a) = L >= 31 ? 1 : 1 << (31 - L); + } + } +#endif + return dval(&a); +} diff --git a/libc/mingw/math/abs64.c b/libc/mingw/math/abs64.c new file mode 100644 index 000000000..3f2133a8c --- /dev/null +++ b/libc/mingw/math/abs64.c @@ -0,0 +1,6 @@ +#include +#include + +__MINGW_EXTENSION __int64 __cdecl _abs64(__int64 x) { + return llabs(x); +} diff --git a/libc/mingw/math/arm/_chgsignl.S b/libc/mingw/math/arm/_chgsignl.S new file mode 100644 index 000000000..355d35530 --- /dev/null +++ b/libc/mingw/math/arm/_chgsignl.S @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include <_mingw_mac.h> + + .file "_chgignl.S" + .text + .align 4 + .globl __MINGW_USYMBOL(_chgsignl) + .def __MINGW_USYMBOL(_chgsignl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(_chgsignl): + vneg.f64 d0, d0 + bx lr diff --git a/libc/mingw/math/arm/ceil.S b/libc/mingw/math/arm/ceil.S new file mode 100644 index 000000000..47162c9af --- /dev/null +++ b/libc/mingw/math/arm/ceil.S @@ -0,0 +1,29 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceil.S" + .text + .align 4 + .globl __MINGW_USYMBOL(ceil) + .def __MINGW_USYMBOL(ceil); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(ceil): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + bic r0, r1, #0x00c00000 + orr r0, r0, #0x00400000 /* Round towards Plus Infinity */ + vmsr fpscr, r0 + vcvtr.s32.f64 s0, d0 + vcvt.f64.s32 d0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/ceilf.S b/libc/mingw/math/arm/ceilf.S new file mode 100644 index 000000000..a899f25fa --- /dev/null +++ b/libc/mingw/math/arm/ceilf.S @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceilf.S" + .text + .align 4 + .globl __MINGW_USYMBOL(ceilf) + .def __MINGW_USYMBOL(ceilf); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(ceilf): + vmov r2, s0 + lsr r2, r2, #23 + bic r2, r2, #0x100 + cmp r2, #0xff /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + bic r0, r1, #0x00c00000 + orr r0, r0, #0x00400000 /* Round towards Plus Infinity */ + vmsr fpscr, r0 + vcvtr.s32.f32 s0, s0 + vcvt.f32.s32 s0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/ceill.S b/libc/mingw/math/arm/ceill.S new file mode 100644 index 000000000..9c6934ba0 --- /dev/null +++ b/libc/mingw/math/arm/ceill.S @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceill.S" + .text + .align 4 + .globl __MINGW_USYMBOL(ceill) + .def __MINGW_USYMBOL(ceill); .scl 2; .type 32; .endef +__MINGW_USYMBOL(ceill): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + bic r0, r1, #0x00c00000 + orr r0, r0, #0x00400000 /* Round towards Plus Infinity */ + vmsr fpscr, r0 + vcvtr.s32.f64 s0, d0 + vcvt.f64.s32 d0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/copysignl.c b/libc/mingw/math/arm/copysignl.c new file mode 100644 index 000000000..ea66215f2 --- /dev/null +++ b/libc/mingw/math/arm/copysignl.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long double copysignl(long double x, long double y) +{ + return copysign(x, y); +} diff --git a/libc/mingw/math/arm/exp2.c b/libc/mingw/math/arm/exp2.c new file mode 100644 index 000000000..77e914d98 --- /dev/null +++ b/libc/mingw/math/arm/exp2.c @@ -0,0 +1,64 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2014 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +double exp2(double x) +{ + return pow(2, x); +} + +float exp2f(float x) +{ + return powf(2, x); +} + +long double exp2l(long double x) +{ +#if defined(__arm__) || defined(_ARM_) + return exp2(x); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm/floor.S b/libc/mingw/math/arm/floor.S new file mode 100644 index 000000000..fc1df16af --- /dev/null +++ b/libc/mingw/math/arm/floor.S @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "floor.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(floor) + .def __MINGW_USYMBOL(floor); .scl 2; .type 32; .endef +__MINGW_USYMBOL(floor): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + bic r0, r1, #0x00c00000 + orr r0, r0, #0x00800000 /* Round towards Minus Infinity */ + vmsr fpscr, r0 + vcvtr.s32.f64 s0, d0 + vcvt.f64.s32 d0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/floorf.S b/libc/mingw/math/arm/floorf.S new file mode 100644 index 000000000..b5ae0c720 --- /dev/null +++ b/libc/mingw/math/arm/floorf.S @@ -0,0 +1,27 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + #include <_mingw_mac.h> + + .file "floorf.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(floorf) + .def __MINGW_USYMBOL(floorf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(floorf): + vmov r2, s0 + lsr r2, r2, #23 + bic r2, r2, #0x100 + cmp r2, #0xff /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + bic r0, r1, #0x00c00000 + orr r0, r0, #0x00800000 /* Round towards Minus Infinity */ + vmsr fpscr, r0 + vcvtr.s32.f32 s0, s0 + vcvt.f32.s32 s0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/floorl.S b/libc/mingw/math/arm/floorl.S new file mode 100644 index 000000000..ec8c0050a --- /dev/null +++ b/libc/mingw/math/arm/floorl.S @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "floorl.S" + .text + .align 4 + .globl __MINGW_USYMBOL(floorl) + .def __MINGW_USYMBOL(floorl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(floorl): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + bic r0, r1, #0x00c00000 + orr r0, r0, #0x00800000 /* Round towards Minus Infinity */ + vmsr fpscr, r0 + vcvtr.s32.f64 s0, d0 + vcvt.f64.s32 d0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/ldexpl.c b/libc/mingw/math/arm/ldexpl.c new file mode 100644 index 000000000..7d3bffcbe --- /dev/null +++ b/libc/mingw/math/arm/ldexpl.c @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +long double ldexpl(long double x, int n) +{ +#if defined(__arm__) || defined(_ARM_) + return ldexp(x, n); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm/log2.c b/libc/mingw/math/arm/log2.c new file mode 100644 index 000000000..eeb690b97 --- /dev/null +++ b/libc/mingw/math/arm/log2.c @@ -0,0 +1,64 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2014 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +double log2(double x) +{ + return log(x) / 0.69314718246459960938; +} + +float log2f(float x) +{ + return logf(x) / 0.69314718246459960938f; +} + +long double log2l(long double x) +{ +#if defined(__arm__) || defined(_ARM_) + return log2(x); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm/nearbyint.S b/libc/mingw/math/arm/nearbyint.S new file mode 100644 index 000000000..dc66a9787 --- /dev/null +++ b/libc/mingw/math/arm/nearbyint.S @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyint.S" + .text + .align 4 + .globl __MINGW_USYMBOL(nearbyint) + .def __MINGW_USYMBOL(nearbyint); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyint): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + vcvtr.s32.f64 s0, d0 + vcvt.f64.s32 d0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/nearbyintf.S b/libc/mingw/math/arm/nearbyintf.S new file mode 100644 index 000000000..b880c7110 --- /dev/null +++ b/libc/mingw/math/arm/nearbyintf.S @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyintf.S" + .text + .align 4 + .globl __MINGW_USYMBOL(nearbyintf) + .def __MINGW_USYMBOL(nearbyintf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyintf): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + vcvtr.s32.f32 s0, s0 + vcvt.f32.s32 s0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/nearbyintl.S b/libc/mingw/math/arm/nearbyintl.S new file mode 100644 index 000000000..bceda5e40 --- /dev/null +++ b/libc/mingw/math/arm/nearbyintl.S @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyintl.S" + .text + .align 4 + .globl __MINGW_USYMBOL(nearbyintl) + .def __MINGW_USYMBOL(nearbyintl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyintl): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + vcvtr.s32.f64 s0, d0 + vcvt.f64.s32 d0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/scalbn.c b/libc/mingw/math/arm/scalbn.c new file mode 100644 index 000000000..f11fd37e0 --- /dev/null +++ b/libc/mingw/math/arm/scalbn.c @@ -0,0 +1,64 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2014 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +double scalbn(double x, int exp) +{ + return x * exp2(exp); +} + +float scalbnf(float x, int exp) +{ + return x * exp2f(exp); +} + +long double scalbnl(long double x, int exp) +{ +#if defined(__arm__) || defined(_ARM_) + return scalbn(x, exp); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm/sincos.c b/libc/mingw/math/arm/sincos.c new file mode 100644 index 000000000..3bb86ee1b --- /dev/null +++ b/libc/mingw/math/arm/sincos.c @@ -0,0 +1,29 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +void sincos (double __x, double *p_sin, double *p_cos) +{ + *p_sin = sin(__x); + *p_cos = cos(__x); +} + +void sincosf (float __x, float *p_sin, float *p_cos) +{ + *p_sin = sinf(__x); + *p_cos = cosf(__x); +} + +void sincosl (long double __x, long double *p_sin, long double *p_cos) +{ +#if defined(__arm__) || defined(_ARM_) + *p_sin = sin(__x); + *p_cos = cos(__x); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm/trunc.S b/libc/mingw/math/arm/trunc.S new file mode 100644 index 000000000..3b297cbf0 --- /dev/null +++ b/libc/mingw/math/arm/trunc.S @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "trunc.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(trunc) + .def __MINGW_USYMBOL(trunc); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(trunc): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + orr r0, r1, #0x00c00000 /* Round towards Zero */ + vmsr fpscr, r0 + vcvtr.s32.f64 s0, d0 + vcvt.f64.s32 d0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm/truncf.S b/libc/mingw/math/arm/truncf.S new file mode 100644 index 000000000..9c1f0cda1 --- /dev/null +++ b/libc/mingw/math/arm/truncf.S @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "truncf.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(truncf) + .def __MINGW_USYMBOL(truncf); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(truncf): + vmov r2, r3, d0 + lsr r3, r3, #20 + bic r3, r3, #0x800 + movw r2, #0x7ff + cmp r2, r3 /* Check for INF/NAN, just return the input in those cases */ + it eq + bxeq lr + vmrs r1, fpscr + orr r0, r1, #0x00c00000 /* Round towards Zero */ + vmsr fpscr, r0 + vcvt.s32.f32 s0, s0 + vcvt.f32.s32 s0, s0 + vmsr fpscr, r1 + bx lr diff --git a/libc/mingw/math/arm64/_chgsignl.S b/libc/mingw/math/arm64/_chgsignl.S new file mode 100644 index 000000000..0472c7093 --- /dev/null +++ b/libc/mingw/math/arm64/_chgsignl.S @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include <_mingw_mac.h> + + .file "_chgignl.S" + .text + .align 2 + .globl __MINGW_USYMBOL(_chgsignl) + .def __MINGW_USYMBOL(_chgsignl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(_chgsignl): + fneg d0, d0 + ret diff --git a/libc/mingw/math/arm64/ceil.S b/libc/mingw/math/arm64/ceil.S new file mode 100644 index 000000000..6f46d352f --- /dev/null +++ b/libc/mingw/math/arm64/ceil.S @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceil.S" + .text + .align 2 + .globl __MINGW_USYMBOL(ceil) + .def __MINGW_USYMBOL(ceil); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(ceil): + frintp d0, d0 + ret diff --git a/libc/mingw/math/arm64/ceilf.S b/libc/mingw/math/arm64/ceilf.S new file mode 100644 index 000000000..b67d7687a --- /dev/null +++ b/libc/mingw/math/arm64/ceilf.S @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceilf.S" + .text + .align 2 + .globl __MINGW_USYMBOL(ceilf) + .def __MINGW_USYMBOL(ceilf); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(ceilf): + frintp s0, s0 + ret diff --git a/libc/mingw/math/arm64/ceill.S b/libc/mingw/math/arm64/ceill.S new file mode 100644 index 000000000..99385a36d --- /dev/null +++ b/libc/mingw/math/arm64/ceill.S @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceill.S" + .text + .align 2 + .globl __MINGW_USYMBOL(ceill) + .def __MINGW_USYMBOL(ceill); .scl 2; .type 32; .endef +__MINGW_USYMBOL(ceill): + frintp d0, d0 + ret diff --git a/libc/mingw/math/arm64/copysignl.c b/libc/mingw/math/arm64/copysignl.c new file mode 100644 index 000000000..ea66215f2 --- /dev/null +++ b/libc/mingw/math/arm64/copysignl.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long double copysignl(long double x, long double y) +{ + return copysign(x, y); +} diff --git a/libc/mingw/math/arm64/exp2.S b/libc/mingw/math/arm64/exp2.S new file mode 100644 index 000000000..b1f7a07ab --- /dev/null +++ b/libc/mingw/math/arm64/exp2.S @@ -0,0 +1,19 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "exp2.S" + .text + .align 2 + .globl __MINGW_USYMBOL(exp2) + .globl __MINGW_USYMBOL(exp2l) + .def __MINGW_USYMBOL(exp2); .scl 2; .type 32; .endef + .def __MINGW_USYMBOL(exp2l); .scl 2; .type 32; .endef +__MINGW_USYMBOL(exp2): +__MINGW_USYMBOL(exp2l): + fmov d1, d0 + fmov d0, #2.0 + b pow diff --git a/libc/mingw/math/arm64/exp2f.S b/libc/mingw/math/arm64/exp2f.S new file mode 100644 index 000000000..c00f003c7 --- /dev/null +++ b/libc/mingw/math/arm64/exp2f.S @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "exp2f.S" + .text + .align 2 + .globl __MINGW_USYMBOL(exp2f) + .def __MINGW_USYMBOL(exp2f); .scl 2; .type 32; .endef +__MINGW_USYMBOL(exp2f): + fmov s1, s0 + fmov s0, #2.0 + b powf diff --git a/libc/mingw/math/arm64/floor.S b/libc/mingw/math/arm64/floor.S new file mode 100644 index 000000000..fc3f002d1 --- /dev/null +++ b/libc/mingw/math/arm64/floor.S @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "floor.S" + .text + .p2align 2 + .globl __MINGW_USYMBOL(floor) + .def __MINGW_USYMBOL(floor); .scl 2; .type 32; .endef +__MINGW_USYMBOL(floor): + frintm d0, d0 + ret diff --git a/libc/mingw/math/arm64/floorf.S b/libc/mingw/math/arm64/floorf.S new file mode 100644 index 000000000..d24db9226 --- /dev/null +++ b/libc/mingw/math/arm64/floorf.S @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + #include <_mingw_mac.h> + + .file "floorf.S" + .text + .p2align 2 + .globl __MINGW_USYMBOL(floorf) + .def __MINGW_USYMBOL(floorf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(floorf): + frintm s0, s0 + ret diff --git a/libc/mingw/math/arm64/floorl.S b/libc/mingw/math/arm64/floorl.S new file mode 100644 index 000000000..746738d6c --- /dev/null +++ b/libc/mingw/math/arm64/floorl.S @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "floorl.S" + .text + .align 2 + .globl __MINGW_USYMBOL(floorl) + .def __MINGW_USYMBOL(floorl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(floorl): + frintm d0, d0 + ret diff --git a/libc/mingw/math/arm64/ldexpl.c b/libc/mingw/math/arm64/ldexpl.c new file mode 100644 index 000000000..bfa32876d --- /dev/null +++ b/libc/mingw/math/arm64/ldexpl.c @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +long double ldexpl(long double x, int n) +{ +#if defined(__aarch64__) || defined(_ARM64_) + return ldexp(x, n); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm64/log2.c b/libc/mingw/math/arm64/log2.c new file mode 100644 index 000000000..6196f4227 --- /dev/null +++ b/libc/mingw/math/arm64/log2.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +double log2(double x) +{ + return log(x) / 0.69314718246459960938; +} + +float log2f(float x) +{ + return logf(x) / 0.69314718246459960938f; +} + +long double log2l(long double x) +{ +#if defined(__aarch64__) || defined(_ARM64_) + return log2(x); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm64/nearbyint.S b/libc/mingw/math/arm64/nearbyint.S new file mode 100644 index 000000000..b17ce2bd1 --- /dev/null +++ b/libc/mingw/math/arm64/nearbyint.S @@ -0,0 +1,17 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyint.S" + .text + .align 2 + .globl __MINGW_USYMBOL(nearbyint) + .def __MINGW_USYMBOL(nearbyint); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyint): + mrs x1, fpcr + frintx d0, d0 + msr fpcr, x1 + ret diff --git a/libc/mingw/math/arm64/nearbyintf.S b/libc/mingw/math/arm64/nearbyintf.S new file mode 100644 index 000000000..49b6aff11 --- /dev/null +++ b/libc/mingw/math/arm64/nearbyintf.S @@ -0,0 +1,17 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyintf.S" + .text + .align 2 + .globl __MINGW_USYMBOL(nearbyintf) + .def __MINGW_USYMBOL(nearbyintf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyintf): + mrs x1, fpcr + frintx s0, s0 + msr fpcr, x1 + ret diff --git a/libc/mingw/math/arm64/nearbyintl.S b/libc/mingw/math/arm64/nearbyintl.S new file mode 100644 index 000000000..cbfebb250 --- /dev/null +++ b/libc/mingw/math/arm64/nearbyintl.S @@ -0,0 +1,17 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyintl.S" + .text + .align 2 + .globl __MINGW_USYMBOL(nearbyintl) + .def __MINGW_USYMBOL(nearbyintl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyintl): + mrs x1, fpcr + frintx d0, d0 + msr fpcr, x1 + ret diff --git a/libc/mingw/math/arm64/scalbn.c b/libc/mingw/math/arm64/scalbn.c new file mode 100644 index 000000000..212752c04 --- /dev/null +++ b/libc/mingw/math/arm64/scalbn.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +double scalbn(double x, int exp) +{ + return x * exp2(exp); +} + +float scalbnf(float x, int exp) +{ + return x * exp2f(exp); +} + +long double scalbnl(long double x, int exp) +{ +#if defined(__aarch64__) || defined(_ARM64_) + return scalbn(x, exp); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm64/sincos.c b/libc/mingw/math/arm64/sincos.c new file mode 100644 index 000000000..94f824494 --- /dev/null +++ b/libc/mingw/math/arm64/sincos.c @@ -0,0 +1,29 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +void sincos (double __x, double *p_sin, double *p_cos) +{ + *p_sin = sin(__x); + *p_cos = cos(__x); +} + +void sincosf (float __x, float *p_sin, float *p_cos) +{ + *p_sin = sinf(__x); + *p_cos = cosf(__x); +} + +void sincosl (long double __x, long double *p_sin, long double *p_cos) +{ +#if defined(__aarch64__) || defined(_ARM64_) + *p_sin = sin(__x); + *p_cos = cos(__x); +#else +#error Not supported on your platform yet +#endif +} diff --git a/libc/mingw/math/arm64/trunc.S b/libc/mingw/math/arm64/trunc.S new file mode 100644 index 000000000..d784bf016 --- /dev/null +++ b/libc/mingw/math/arm64/trunc.S @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "trunc.S" + .text + .p2align 2 + .globl __MINGW_USYMBOL(trunc) + .def __MINGW_USYMBOL(trunc); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(trunc): + frintz d0, d0 + ret diff --git a/libc/mingw/math/arm64/truncf.S b/libc/mingw/math/arm64/truncf.S new file mode 100644 index 000000000..22b9ff88c --- /dev/null +++ b/libc/mingw/math/arm64/truncf.S @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "truncf.S" + .text + .p2align 2 + .globl __MINGW_USYMBOL(truncf) + .def __MINGW_USYMBOL(truncf); .scl 2; .type 32; .endef + +__MINGW_USYMBOL(truncf): + frintz s0, s0 + ret diff --git a/libc/mingw/math/cbrt.c b/libc/mingw/math/cbrt.c new file mode 100644 index 000000000..005505235 --- /dev/null +++ b/libc/mingw/math/cbrt.c @@ -0,0 +1,104 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include "cephes_mconf.h" + +static const double CBRT2 = 1.2599210498948731647672; +static const double CBRT4 = 1.5874010519681994747517; +static const double CBRT2I = 0.79370052598409973737585; +static const double CBRT4I = 0.62996052494743658238361; + +#ifndef __MINGW32__ +extern double frexp ( double, int * ); +extern double ldexp ( double, int ); +extern int isnan ( double ); +extern int isfinite ( double ); +#endif + +double cbrt(double x) +{ + int e, rem, sign; + double z; + +#ifdef __MINGW32__ + if (!isfinite (x) || x == 0) + return x; +#else +#ifdef NANS + if (isnan(x)) + return x; +#endif +#ifdef INFINITIES + if (!isfinite(x)) + return x; +#endif + if (x == 0) + return (x); +#endif /* __MINGW32__ */ + + if (x > 0) + sign = 1; + else + { + sign = -1; + x = -x; + } + + z = x; + /* extract power of 2, leaving + * mantissa between 0.5 and 1 + */ + x = frexp(x, &e); + + /* Approximate cube root of number between .5 and 1, + * peak relative error = 9.2e-6 + */ + x = (((-1.3466110473359520655053e-1 * x + + 5.4664601366395524503440e-1) * x + - 9.5438224771509446525043e-1) * x + + 1.1399983354717293273738e0 ) * x + + 4.0238979564544752126924e-1; + + /* exponent divided by 3 */ + if (e >= 0) + { + rem = e; + e /= 3; + rem -= 3*e; + if (rem == 1) + x *= CBRT2; + else if (rem == 2) + x *= CBRT4; + } + /* argument less than 1 */ + else + { + e = -e; + rem = e; + e /= 3; + rem -= 3*e; + if (rem == 1) + x *= CBRT2I; + else if (rem == 2) + x *= CBRT4I; + e = -e; + } + + /* multiply by power of 2 */ + x = ldexp(x, e); + + /* Newton iteration */ + x -= ( x - (z/(x*x)) )*0.33333333333333333333; +#ifdef DEC + x -= ( x - (z/(x*x)) )/3.0; +#else + x -= ( x - (z/(x*x)) )*0.33333333333333333333; +#endif + + if (sign < 0) + x = -x; + return (x); +} diff --git a/libc/mingw/math/cbrtf.c b/libc/mingw/math/cbrtf.c new file mode 100644 index 000000000..1c37e75bc --- /dev/null +++ b/libc/mingw/math/cbrtf.c @@ -0,0 +1,75 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include "cephes_mconf.h" + +static const float CBRT2 = 1.25992104989487316477; +static const float CBRT4 = 1.58740105196819947475; + +float cbrtf (float x) +{ + int e, rem, sign; + float z; + if (!isfinite (x) || x == 0.0F) + return x; + if (x > 0) + sign = 1; + else + { + sign = -1; + x = -x; + } + + z = x; + /* extract power of 2, leaving + * mantissa between 0.5 and 1 + */ + x = frexpf(x, &e); + + /* Approximate cube root of number between .5 and 1, + * peak relative error = 9.2e-6 + */ + x = (((-0.13466110473359520655053 * x + + 0.54664601366395524503440 ) * x + - 0.95438224771509446525043 ) * x + + 1.1399983354717293273738 ) * x + + 0.40238979564544752126924; + + /* exponent divided by 3 */ + if (e >= 0) + { + rem = e; + e /= 3; + rem -= 3*e; + if (rem == 1) + x *= CBRT2; + else if (rem == 2) + x *= CBRT4; + } +/* argument less than 1 */ + else + { + e = -e; + rem = e; + e /= 3; + rem -= 3*e; + if (rem == 1) + x /= CBRT2; + else if (rem == 2) + x /= CBRT4; + e = -e; + } + + /* multiply by power of 2 */ + x = ldexpf(x, e); + + /* Newton iteration */ + x -= ( x - (z/(x*x)) ) * 0.333333333333; + + if (sign < 0) + x = -x; + return (x); +} diff --git a/libc/mingw/math/cbrtl.c b/libc/mingw/math/cbrtl.c new file mode 100644 index 000000000..40e02ed8f --- /dev/null +++ b/libc/mingw/math/cbrtl.c @@ -0,0 +1,82 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" + +static const long double CBRT2 = 1.2599210498948731647672L; +static const long double CBRT4 = 1.5874010519681994747517L; +static const long double CBRT2I = 0.79370052598409973737585L; +static const long double CBRT4I = 0.62996052494743658238361L; + +extern long double ldexpl(long double,int); + +long double cbrtl(long double x) +{ + int e, rem, sign; + long double z; + + if (!isfinite (x) || x == 0.0L) + return (x); + + if (x > 0) + sign = 1; + else + { + sign = -1; + x = -x; + } + + z = x; + /* extract power of 2, leaving + * mantissa between 0.5 and 1 + */ + x = frexpl(x, &e); + + /* Approximate cube root of number between .5 and 1, + * peak relative error = 1.2e-6 + */ + x = (((( 1.3584464340920900529734e-1L * x + - 6.3986917220457538402318e-1L) * x + + 1.2875551670318751538055e0L) * x + - 1.4897083391357284957891e0L) * x + + 1.3304961236013647092521e0L) * x + + 3.7568280825958912391243e-1L; + + /* exponent divided by 3 */ + if (e >= 0) + { + rem = e; + e /= 3; + rem -= 3*e; + if (rem == 1) + x *= CBRT2; + else if (rem == 2) + x *= CBRT4; + } + else + { /* argument less than 1 */ + e = -e; + rem = e; + e /= 3; + rem -= 3*e; + if (rem == 1) + x *= CBRT2I; + else if (rem == 2) + x *= CBRT4I; + e = -e; + } + + /* multiply by power of 2 */ + x = ldexpl(x, e); + + /* Newton iteration */ + + x -= ( x - (z/(x*x)) )*0.3333333333333333333333L; + x -= ( x - (z/(x*x)) )*0.3333333333333333333333L; + + if (sign < 0) + x = -x; + return (x); +} diff --git a/libc/mingw/math/cephes_emath.c b/libc/mingw/math/cephes_emath.c new file mode 100644 index 000000000..41e297cfe --- /dev/null +++ b/libc/mingw/math/cephes_emath.c @@ -0,0 +1,1283 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_emath.h" + +/* + * The constants are for 64 bit precision. + */ + + +/* Move in external format number, + * converting it to internal format. + */ +void __emovi(const short unsigned int * __restrict__ a, + short unsigned int * __restrict__ b) +{ + register const unsigned short *p; + register unsigned short *q; + int i; + + q = b; + p = a + (NE-1); /* point to last word of external number */ + /* get the sign bit */ + if (*p & 0x8000) + *q++ = 0xffff; + else + *q++ = 0; + /* get the exponent */ + *q = *p--; + *q++ &= 0x7fff; /* delete the sign bit */ +#ifdef INFINITY + if ((*(q - 1) & 0x7fff) == 0x7fff) + { +#ifdef NANS + if (__eisnan(a)) + { + *q++ = 0; + for (i = 3; i < NI; i++ ) + *q++ = *p--; + return; + } +#endif + for (i = 2; i < NI; i++) + *q++ = 0; + return; + } +#endif + /* clear high guard word */ + *q++ = 0; + /* move in the significand */ + for (i = 0; i < NE - 1; i++ ) + *q++ = *p--; + /* clear low guard word */ + *q = 0; +} + + +/* +; Add significands +; x + y replaces y +*/ + +void __eaddm(const short unsigned int * __restrict__ x, + short unsigned int * __restrict__ y) +{ + register unsigned long a; + int i; + unsigned int carry; + + x += NI - 1; + y += NI - 1; + carry = 0; + for (i = M; i < NI; i++) + { + a = (unsigned long)(*x) + (unsigned long)(*y) + carry; + if (a & 0x10000) + carry = 1; + else + carry = 0; + *y = (unsigned short)a; + --x; + --y; + } +} + +/* +; Subtract significands +; y - x replaces y +*/ + +void __esubm(const short unsigned int * __restrict__ x, + short unsigned int * __restrict__ y) +{ + unsigned long a; + int i; + unsigned int carry; + + x += NI - 1; + y += NI - 1; + carry = 0; + for (i = M; i < NI; i++) + { + a = (unsigned long)(*y) - (unsigned long)(*x) - carry; + if (a & 0x10000) + carry = 1; + else + carry = 0; + *y = (unsigned short)a; + --x; + --y; + } +} + + +/* Multiply significand of e-type number b +by 16-bit quantity a, e-type result to c. */ + +static void __m16m(short unsigned int a, + short unsigned int * __restrict__ b, + short unsigned int * __restrict__ c) +{ + register unsigned short *pp; + register unsigned long carry; + unsigned short *ps; + unsigned short p[NI]; + unsigned long aa, m; + int i; + + aa = a; + pp = &p[NI - 2]; + *pp++ = 0; + *pp = 0; + ps = &b[NI - 1]; + + for(i = M + 1; i < NI; i++) + { + if (*ps == 0) + { + --ps; + --pp; + *(pp - 1) = 0; + } + else + { + m = (unsigned long) aa * *ps--; + carry = (m & 0xffff) + *pp; + *pp-- = (unsigned short)carry; + carry = (carry >> 16) + (m >> 16) + *pp; + *pp = (unsigned short)carry; + *(pp - 1) = carry >> 16; + } + } + for (i = M; i < NI; i++) + c[i] = p[i]; +} + + +/* Divide significands. Neither the numerator nor the denominator +is permitted to have its high guard word nonzero. */ + +int __edivm(short unsigned int * __restrict__ den, + short unsigned int * __restrict__ num) +{ + int i; + register unsigned short *p; + unsigned long tnum; + unsigned short j, tdenm, tquot; + unsigned short tprod[NI + 1]; + unsigned short equot[NI]; + + p = &equot[0]; + *p++ = num[0]; + *p++ = num[1]; + + for (i = M; i < NI; i++) + { + *p++ = 0; + } + __eshdn1(num); + tdenm = den[M + 1]; + for (i = M; i < NI; i++) + { + /* Find trial quotient digit (the radix is 65536). */ + tnum = (((unsigned long) num[M]) << 16) + num[M + 1]; + + /* Do not execute the divide instruction if it will overflow. */ + if ((tdenm * 0xffffUL) < tnum) + tquot = 0xffff; + else + tquot = tnum / tdenm; + + /* Prove that the divide worked. */ + /* + tcheck = (unsigned long)tquot * tdenm; + if (tnum - tcheck > tdenm) + tquot = 0xffff; + */ + /* Multiply denominator by trial quotient digit. */ + __m16m(tquot, den, tprod); + /* The quotient digit may have been overestimated. */ + if (__ecmpm(tprod, num) > 0) + { + tquot -= 1; + __esubm(den, tprod); + if(__ecmpm(tprod, num) > 0) + { + tquot -= 1; + __esubm(den, tprod); + } + } + __esubm(tprod, num); + equot[i] = tquot; + __eshup6(num); + } + /* test for nonzero remainder after roundoff bit */ + p = &num[M]; + j = 0; + for (i = M; i < NI; i++) + { + j |= *p++; + } + if (j) + j = 1; + + for (i = 0; i < NI; i++) + num[i] = equot[i]; + + return ( (int)j ); +} + + +/* Multiply significands */ +int __emulm(const short unsigned int * __restrict__ a, + short unsigned int * __restrict__ b) +{ + const unsigned short *p; + unsigned short *q; + unsigned short pprod[NI]; + unsigned short equot[NI]; + unsigned short j; + int i; + + equot[0] = b[0]; + equot[1] = b[1]; + for (i = M; i < NI; i++) + equot[i] = 0; + + j = 0; + p = &a[NI - 1]; + q = &equot[NI - 1]; + for (i = M + 1; i < NI; i++) + { + if (*p == 0) + { + --p; + } + else + { + __m16m(*p--, b, pprod); + __eaddm(pprod, equot); + } + j |= *q; + __eshdn6(equot); + } + + for (i = 0; i < NI; i++) + b[i] = equot[i]; + + /* return flag for lost nonzero bits */ + return ( (int)j ); +} + + +/* + * Normalize and round off. + * + * The internal format number to be rounded is "s". + * Input "lost" indicates whether the number is exact. + * This is the so-called sticky bit. + * + * Input "subflg" indicates whether the number was obtained + * by a subtraction operation. In that case if lost is nonzero + * then the number is slightly smaller than indicated. + * + * Input "expo" is the biased exponent, which may be negative. + * the exponent field of "s" is ignored but is replaced by + * "expo" as adjusted by normalization and rounding. + * + * Input "rcntrl" is the rounding control. + * + * Input "rnprc" is precison control (64 or NBITS). + */ + +void __emdnorm(short unsigned int *s, int lost, int subflg, int expo, int rcntrl, int rndprc) +{ + int i, j; + unsigned short r; + int rw = NI-1; /* low guard word */ + int re = NI-2; + const unsigned short rmsk = 0xffff; + const unsigned short rmbit = 0x8000; +#if NE == 6 + unsigned short rbit[NI] = {0,0,0,0,0,0,0,1,0}; +#else + unsigned short rbit[NI] = {0,0,0,0,0,0,0,0,0,0,0,1,0}; +#endif + + /* Normalize */ + j = __enormlz(s); + + /* a blank significand could mean either zero or infinity. */ +#ifndef INFINITY + if (j > NBITS) + { + __ecleazs(s); + return; + } +#endif + expo -= j; +#ifndef INFINITY + if (expo >= 32767L) + goto overf; +#else + if ((j > NBITS) && (expo < 32767L)) + { + __ecleazs(s); + return; + } +#endif + if (expo < 0L) + { + if (expo > (long)(-NBITS - 1)) + { + j = (int)expo; + i = __eshift(s, j); + if (i) + lost = 1; + } + else + { + __ecleazs(s); + return; + } + } + /* Round off, unless told not to by rcntrl. */ + if (rcntrl == 0) + goto mdfin; + if (rndprc == 64) + { + rw = 7; + re = 6; + rbit[NI - 2] = 0; + rbit[6] = 1; + } + + /* Shift down 1 temporarily if the data structure has an implied + * most significant bit and the number is denormal. + * For rndprc = 64 or NBITS, there is no implied bit. + * But Intel long double denormals lose one bit of significance even so. + */ +#if IBMPC + if ((expo <= 0) && (rndprc != NBITS)) +#else + if ((expo <= 0) && (rndprc != 64) && (rndprc != NBITS)) +#endif + { + lost |= s[NI - 1] & 1; + __eshdn1(s); + } + /* Clear out all bits below the rounding bit, + * remembering in r if any were nonzero. + */ + r = s[rw] & rmsk; + if (rndprc < NBITS) + { + i = rw + 1; + while (i < NI) + { + if( s[i] ) + r |= 1; + s[i] = 0; + ++i; + } + } + s[rw] &= (rmsk ^ 0xffff); + if ((r & rmbit) != 0) + { + if (r == rmbit) + { + if (lost == 0) + { /* round to even */ + if ((s[re] & 1) == 0) + goto mddone; + } + else + { + if (subflg != 0) + goto mddone; + } + } + __eaddm(rbit, s); + } +mddone: +#if IBMPC + if ((expo <= 0) && (rndprc != NBITS)) +#else + if ((expo <= 0) && (rndprc != 64) && (rndprc != NBITS)) +#endif + { + __eshup1(s); + } + if (s[2] != 0) + { /* overflow on roundoff */ + __eshdn1(s); + expo += 1; + } +mdfin: + s[NI - 1] = 0; + if (expo >= 32767L) + { +#ifndef INFINITY +overf: +#endif +#ifdef INFINITY + s[1] = 32767; + for (i = 2; i < NI - 1; i++ ) + s[i] = 0; +#else + s[1] = 32766; + s[2] = 0; + for (i = M + 1; i < NI - 1; i++) + s[i] = 0xffff; + s[NI - 1] = 0; + if ((rndprc < 64) || (rndprc == 113)) + s[rw] &= (rmsk ^ 0xffff); +#endif + return; + } + if (expo < 0) + s[1] = 0; + else + s[1] = (unsigned short)expo; +} + + +/* +; Multiply. +; +; unsigned short a[NE], b[NE], c[NE]; +; emul( a, b, c ); c = b * a +*/ +void __emul(const short unsigned int *a, + const short unsigned int *b, + short unsigned int *c) +{ + unsigned short ai[NI], bi[NI]; + int i, j; + long lt, lta, ltb; + +#ifdef NANS + /* NaN times anything is the same NaN. */ + if (__eisnan(a)) + { + __emov(a, c); + return; + } + if (__eisnan(b)) + { + __emov(b, c); + return; + } + /* Zero times infinity is a NaN. */ + if ((__eisinf(a) && __eiiszero(b)) + || (__eisinf(b) && __eiiszero(a))) + { + mtherr( "emul", DOMAIN); + __enan_NBITS(c); + return; + } +#endif +/* Infinity times anything else is infinity. */ +#ifdef INFINITY + if (__eisinf(a) || __eisinf(b)) + { + if (__eisneg(a) ^ __eisneg(b)) + *(c + (NE-1)) = 0x8000; + else + *(c + (NE-1)) = 0; + __einfin(c); + return; + } +#endif + __emovi(a, ai); + __emovi(b, bi); + lta = ai[E]; + ltb = bi[E]; + if (ai[E] == 0) + { + for (i = 1; i < NI - 1; i++) + { + if (ai[i] != 0) + { + lta -= __enormlz( ai ); + goto mnzer1; + } + } + __eclear(c); + return; + } +mnzer1: + + if (bi[E] == 0) + { + for (i = 1; i < NI - 1; i++) + { + if (bi[i] != 0) + { + ltb -= __enormlz(bi); + goto mnzer2; + } + } + __eclear(c); + return; + } +mnzer2: + + /* Multiply significands */ + j = __emulm(ai, bi); + /* calculate exponent */ + lt = lta + ltb - (EXONE - 1); + __emdnorm(bi, j, 0, lt, 64, NBITS); + /* calculate sign of product */ + if (ai[0] == bi[0]) + bi[0] = 0; + else + bi[0] = 0xffff; + __emovo(bi, c); +} + + +/* move out internal format to ieee long double */ +void __toe64(short unsigned int *a, short unsigned int *b) +{ + register unsigned short *p, *q; + unsigned short i; + +#ifdef NANS + if (__eiisnan(a)) + { + __enan_64(b); + return; + } +#endif +#ifdef IBMPC + /* Shift Intel denormal significand down 1. */ + if (a[E] == 0) + __eshdn1(a); +#endif + p = a; +#ifdef MIEEE + q = b; +#else + q = b + 4; /* point to output exponent */ +#if 1 + /* NOTE: if data type is 96 bits wide, clear the last word here. */ + *(q + 1)= 0; +#endif +#endif + + /* combine sign and exponent */ + i = *p++; +#ifdef MIEEE + if (i) + *q++ = *p++ | 0x8000; + else + *q++ = *p++; + *q++ = 0; +#else + if (i) + *q-- = *p++ | 0x8000; + else + *q-- = *p++; +#endif + /* skip over guard word */ + ++p; + /* move the significand */ +#ifdef MIEEE + for (i = 0; i < 4; i++) + *q++ = *p++; +#else +#ifdef INFINITY + if (__eiisinf(a)) + { + /* Intel long double infinity. */ + *q-- = 0x8000; + *q-- = 0; + *q-- = 0; + *q = 0; + return; + } +#endif + for (i = 0; i < 4; i++) + *q-- = *p++; +#endif +} + + +/* Compare two e type numbers. + * + * unsigned short a[NE], b[NE]; + * ecmp( a, b ); + * + * returns +1 if a > b + * 0 if a == b + * -1 if a < b + * -2 if either a or b is a NaN. + */ +int __ecmp(const short unsigned int * __restrict__ a, + const short unsigned int * __restrict__ b) +{ + unsigned short ai[NI], bi[NI]; + register unsigned short *p, *q; + register int i; + int msign; + +#ifdef NANS + if (__eisnan (a) || __eisnan (b)) + return (-2); +#endif + __emovi(a, ai); + p = ai; + __emovi(b, bi); + q = bi; + + if (*p != *q) + { /* the signs are different */ + /* -0 equals + 0 */ + for (i = 1; i < NI - 1; i++) + { + if (ai[i] != 0) + goto nzro; + if (bi[i] != 0) + goto nzro; + } + return (0); +nzro: + if (*p == 0) + return (1); + else + return (-1); + } + /* both are the same sign */ + if (*p == 0) + msign = 1; + else + msign = -1; + i = NI - 1; + do + { + if (*p++ != *q++) + { + goto diff; + } + } + while (--i > 0); + + return (0); /* equality */ + +diff: + if ( *(--p) > *(--q) ) + return (msign); /* p is bigger */ + else + return (-msign); /* p is littler */ +} + +/* +; Shift significand +; +; Shifts significand area up or down by the number of bits +; given by the variable sc. +*/ +int __eshift(short unsigned int *x, int sc) +{ + unsigned short lost; + unsigned short *p; + + if (sc == 0) + return (0); + + lost = 0; + p = x + NI - 1; + + if (sc < 0) + { + sc = -sc; + while (sc >= 16) + { + lost |= *p; /* remember lost bits */ + __eshdn6(x); + sc -= 16; + } + + while (sc >= 8) + { + lost |= *p & 0xff; + __eshdn8(x); + sc -= 8; + } + + while (sc > 0) + { + lost |= *p & 1; + __eshdn1(x); + sc -= 1; + } + } + else + { + while (sc >= 16) + { + __eshup6(x); + sc -= 16; + } + + while (sc >= 8) + { + __eshup8(x); + sc -= 8; + } + + while (sc > 0) + { + __eshup1(x); + sc -= 1; + } + } + if (lost) + lost = 1; + return ( (int)lost ); +} + + +/* +; normalize +; +; Shift normalizes the significand area pointed to by argument +; shift count (up = positive) is returned. +*/ +int __enormlz(short unsigned int *x) +{ + register unsigned short *p; + int sc; + + sc = 0; + p = &x[M]; + if (*p != 0) + goto normdn; + ++p; + if (*p & 0x8000) + return (0); /* already normalized */ + while (*p == 0) + { + __eshup6(x); + sc += 16; + /* With guard word, there are NBITS+16 bits available. + * return true if all are zero. + */ + if (sc > NBITS) + return (sc); + } + /* see if high byte is zero */ + while ((*p & 0xff00) == 0) + { + __eshup8(x); + sc += 8; + } + /* now shift 1 bit at a time */ + while ((*p & 0x8000) == 0) + { + __eshup1(x); + sc += 1; + if (sc > (NBITS + 16)) + { + mtherr( "enormlz", UNDERFLOW); + return (sc); + } + } + return (sc); + + /* Normalize by shifting down out of the high guard word + of the significand */ +normdn: + if (*p & 0xff00) + { + __eshdn8(x); + sc -= 8; + } + while (*p != 0) + { + __eshdn1(x); + sc -= 1; + + if (sc < -NBITS) + { + mtherr("enormlz", OVERFLOW); + return (sc); + } + } + return (sc); +} + + +/* Move internal format number out, + * converting it to external format. + */ +void __emovo(const short unsigned int * __restrict__ a, + short unsigned int * __restrict__ b) +{ + register const unsigned short *p; + register unsigned short *q; + unsigned short i; + + p = a; + q = b + (NE - 1); /* point to output exponent */ + /* combine sign and exponent */ + i = *p++; + if (i) + *q-- = *p++ | 0x8000; + else + *q-- = *p++; +#ifdef INFINITY + if (*(p - 1) == 0x7fff) + { +#ifdef NANS + if (__eiisnan(a)) + { + __enan_NBITS(b); + return; + } +#endif + __einfin(b); + return; + } +#endif + /* skip over guard word */ + ++p; + /* move the significand */ + for (i = 0; i < NE - 1; i++) + *q-- = *p++; +} + + +#if USE_LDTOA + +void __eiremain(short unsigned int *den, short unsigned int *num, + short unsigned int *equot ) +{ + long ld, ln; + unsigned short j; + + ld = den[E]; + ld -= __enormlz(den); + ln = num[E]; + ln -= __enormlz(num); + __ecleaz(equot); + while (ln >= ld) + { + if(__ecmpm(den,num) <= 0) + { + __esubm(den, num); + j = 1; + } + else + { + j = 0; + } + __eshup1(equot); + equot[NI - 1] |= j; + __eshup1(num); + ln -= 1; + } + __emdnorm( num, 0, 0, ln, 0, NBITS ); +} + + +void __eadd1(const short unsigned int * __restrict__ a, + const short unsigned int * __restrict__ b, + short unsigned int * __restrict__ c, + int subflg) +{ + unsigned short ai[NI], bi[NI], ci[NI]; + int i, lost, j, k; + long lt, lta, ltb; + +#ifdef INFINITY + if (__eisinf(a)) + { + __emov(a, c); + if( subflg ) + __eneg(c); + return; + } + if (__eisinf(b)) + { + __emov(b, c); + return; + } +#endif + __emovi(a, ai); + __emovi(b, bi); + if (sub) + ai[0] = ~ai[0]; + + /* compare exponents */ + lta = ai[E]; + ltb = bi[E]; + lt = lta - ltb; + if (lt > 0L) + { /* put the larger number in bi */ + __emovz(bi, ci); + __emovz(ai, bi); + __emovz(ci, ai); + ltb = bi[E]; + lt = -lt; + } + lost = 0; + if (lt != 0L) + { + if (lt < (long)(-NBITS - 1)) + goto done; /* answer same as larger addend */ + k = (int)lt; + lost = __eshift(ai, k); /* shift the smaller number down */ + } + else + { + /* exponents were the same, so must compare significands */ + i = __ecmpm(ai, bi); + if (i == 0) + { /* the numbers are identical in magnitude */ + /* if different signs, result is zero */ + if (ai[0] != bi[0]) + { + __eclear(c); + return; + } + /* if same sign, result is double */ + /* double denomalized tiny number */ + if ((bi[E] == 0) && ((bi[3] & 0x8000) == 0)) + { + __eshup1( bi ); + goto done; + } + /* add 1 to exponent unless both are zero! */ + for (j = 1; j < NI - 1; j++) + { + if (bi[j] != 0) + { + /* This could overflow, but let emovo take care of that. */ + ltb += 1; + break; + } + } + bi[E] = (unsigned short )ltb; + goto done; + } + if (i > 0) + { /* put the larger number in bi */ + __emovz(bi, ci); + __emovz(ai, bi); + __emovz(ci, ai); + } + } + if (ai[0] == bi[0]) + { + __eaddm(ai, bi); + subflg = 0; + } + else + { + __esubm(ai, bi); + subflg = 1; + } + __emdnorm(bi, lost, subflg, ltb, 64, NBITS); + +done: + __emovo(bi, c); +} + + +/* y = largest integer not greater than x + * (truncated toward minus infinity) + * + * unsigned short x[NE], y[NE] + * + * efloor( x, y ); + */ + + +void __efloor(short unsigned int *x, short unsigned int *y) +{ + register unsigned short *p; + int e, expon, i; + unsigned short f[NE]; + const unsigned short bmask[] = { + 0xffff, + 0xfffe, + 0xfffc, + 0xfff8, + 0xfff0, + 0xffe0, + 0xffc0, + 0xff80, + 0xff00, + 0xfe00, + 0xfc00, + 0xf800, + 0xf000, + 0xe000, + 0xc000, + 0x8000, + 0x0000, + }; + + __emov(x, f); /* leave in external format */ + expon = (int) f[NE - 1]; + e = (expon & 0x7fff) - (EXONE - 1); + if (e <= 0) + { + __eclear(y); + goto isitneg; + } + /* number of bits to clear out */ + e = NBITS - e; + __emov(f, y); + if (e <= 0) + return; + + p = &y[0]; + while (e >= 16) + { + *p++ = 0; + e -= 16; + } + /* clear the remaining bits */ + *p &= bmask[e]; + /* truncate negatives toward minus infinity */ +isitneg: + + if ((unsigned short)expon & (unsigned short)0x8000) + { + for (i = 0; i < NE - 1; i++) + { + if (f[i] != y[i]) + { + __esub( __eone, y, y ); + break; + } + } + } +} + +/* +; Subtract external format numbers. +; +; unsigned short a[NE], b[NE], c[NE]; +; esub( a, b, c ); c = b - a +*/ + +void __esub(const short unsigned int * a, + const short unsigned int * b, + short unsigned int * c) +{ +#ifdef NANS + if (__eisnan(a)) + { + __emov (a, c); + return; + } + if ( __eisnan(b)) + { + __emov(b, c); + return; + } + /* Infinity minus infinity is a NaN. + * Test for subtracting infinities of the same sign. + */ + if (__eisinf(a) && __eisinf(b) && ((__eisneg (a) ^ __eisneg (b)) == 0)) + { + mtherr("esub", DOMAIN); + __enan_NBITS( c ); + return; + } +#endif + __eadd1(a, b, c, 1); +} + + +/* +; Divide. +; +; unsigned short a[NI], b[NI], c[NI]; +; ediv( a, b, c ); c = b / a +*/ + +void __ediv(const short unsigned int *a, + const short unsigned int *b, + short unsigned int *c) +{ + unsigned short ai[NI], bi[NI]; + int i; + long lt, lta, ltb; + +#ifdef NANS + /* Return any NaN input. */ + if (__eisnan(a)) + { + __emov(a, c); + return; + } + if (__eisnan(b)) + { + __emov(b, c); + return; + } + /* Zero over zero, or infinity over infinity, is a NaN. */ + if ((__eiszero(a) && __eiszero(b)) + || (__eisinf (a) && __eisinf (b))) + { + mtherr("ediv", DOMAIN); + __enan_NBITS( c ); + return; + } +#endif +/* Infinity over anything else is infinity. */ +#ifdef INFINITY + if (__eisinf(b)) + { + if (__eisneg(a) ^ __eisneg(b)) + *(c + (NE - 1)) = 0x8000; + else + *(c + (NE - 1)) = 0; + __einfin(c); + return; + } + if (__eisinf(a)) + { + __eclear(c); + return; + } +#endif + __emovi(a, ai); + __emovi(b, bi); + lta = ai[E]; + ltb = bi[E]; + if (bi[E] == 0) + { /* See if numerator is zero. */ + for (i = 1; i < NI - 1; i++) + { + if (bi[i] != 0) + { + ltb -= __enormlz(bi); + goto dnzro1; + } + } + __eclear(c); + return; + } +dnzro1: + + if (ai[E] == 0) + { /* possible divide by zero */ + for (i = 1; i < NI - 1; i++) + { + if (ai[i] != 0) + { + lta -= __enormlz(ai); + goto dnzro2; + } + } + if (ai[0] == bi[0]) + *(c + (NE - 1)) = 0; + else + *(c + (NE - 1)) = 0x8000; + __einfin(c); + mtherr("ediv", SING); + return; + } +dnzro2: + + i = __edivm(ai, bi); + /* calculate exponent */ + lt = ltb - lta + EXONE; + __emdnorm(bi, i, 0, lt, 64, NBITS); + /* set the sign */ + if (ai[0] == bi[0]) + bi[0] = 0; + else + bi[0] = 0Xffff; + __emovo(bi, c); +} + +void __e64toe(short unsigned int *pe, short unsigned int *y) +{ + unsigned short yy[NI]; + unsigned short *p, *q, *e; + int i; + + e = pe; + p = yy; + for (i = 0; i < NE - 5; i++) + *p++ = 0; +#ifdef IBMPC + for (i = 0; i < 5; i++) + *p++ = *e++; +#endif +#ifdef DEC + for (i = 0; i < 5; i++) + *p++ = *e++; +#endif +#ifdef MIEEE + p = &yy[0] + (NE - 1); + *p-- = *e++; + ++e; + for (i = 0; i < 4; i++) + *p-- = *e++; +#endif + +#ifdef IBMPC + /* For Intel long double, shift denormal significand up 1 + -- but only if the top significand bit is zero. */ + if ((yy[NE - 1] & 0x7fff) == 0 && (yy[NE - 2] & 0x8000) == 0) + { + unsigned short temp[NI + 1]; + __emovi(yy, temp); + __eshup1(temp); + __emovo(temp,y); + return; + } +#endif +#ifdef INFINITY + /* Point to the exponent field. */ + p = &yy[NE - 1]; + if (*p == 0x7fff) + { +#ifdef NANS +#ifdef IBMPC + for (i = 0; i < 4; i++) + { + if ((i != 3 && pe[i] != 0) + /* Check for Intel long double infinity pattern. */ + || (i == 3 && pe[i] != 0x8000)) + { + __enan_NBITS(y); + return; + } + } +#else + for (i = 1; i <= 4; i++) + { + if (pe[i] != 0) + { + __enan_NBITS(y); + return; + } + } +#endif +#endif /* NANS */ + __eclear(y); + __einfin(y); + if (*p & 0x8000) + __eneg(y); + return; + } +#endif + p = yy; + q = y; + for (i = 0; i < NE; i++) + *q++ = *p++; +} + +#endif /* USE_LDTOA */ diff --git a/libc/mingw/math/cephes_emath.h b/libc/mingw/math/cephes_emath.h new file mode 100644 index 000000000..58a8e13c9 --- /dev/null +++ b/libc/mingw/math/cephes_emath.h @@ -0,0 +1,719 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _CEPHES_EMATH_H +#define _CEPHES_EMATH_H + +/** + * This is a workaround for a gcc bug + */ +#define __restrict__ + +/* This file is extracted from S L Moshier's ioldoubl.c, + * modified for use in MinGW + * + * Extended precision arithmetic functions for long double I/O. + * This program has been placed in the public domain. + */ + + +/* + * Revision history: + * + * 5 Jan 84 PDP-11 assembly language version + * 6 Dec 86 C language version + * 30 Aug 88 100 digit version, improved rounding + * 15 May 92 80-bit long double support + * + * Author: S. L. Moshier. + * + * 6 Oct 02 Modified for MinGW by inlining utility routines, + * removing global variables, and splitting out strtold + * from _IO_ldtoa and _IO_ldtostr. + * + * Danny Smith + * + */ + + +/* ieee.c + * + * Extended precision IEEE binary floating point arithmetic routines + * + * Numbers are stored in C language as arrays of 16-bit unsigned + * short integers. The arguments of the routines are pointers to + * the arrays. + * + * + * External e type data structure, simulates Intel 8087 chip + * temporary real format but possibly with a larger significand: + * + * NE-1 significand words (least significant word first, + * most significant bit is normally set) + * exponent (value = EXONE for 1.0, + * top bit is the sign) + * + * + * Internal data structure of a number (a "word" is 16 bits): + * + * ei[0] sign word (0 for positive, 0xffff for negative) + * ei[1] biased __exponent (value = EXONE for the number 1.0) + * ei[2] high guard word (always zero after normalization) + * ei[3] + * to ei[NI-2] significand (NI-4 significand words, + * most significant word first, + * most significant bit is set) + * ei[NI-1] low guard word (0x8000 bit is rounding place) + * + * + * + * Routines for external format numbers + * + * __asctoe64( string, &d ) ASCII string to long double + * __asctoeg( string, e, prec ) ASCII string to specified precision + * __e64toe( &d, e ) IEEE long double precision to e type + * __eadd( a, b, c ) c = b + a + * __eclear(e) e = 0 + * __ecmp (a, b) Returns 1 if a > b, 0 if a == b, + * -1 if a < b, -2 if either a or b is a NaN. + * __ediv( a, b, c ) c = b / a + * __efloor( a, b ) truncate to integer, toward -infinity + * __efrexp( a, exp, s ) extract exponent and significand + * __eifrac( e, &l, frac ) e to long integer and e type fraction + * __euifrac( e, &l, frac ) e to unsigned long integer and e type fraction + * __einfin( e ) set e to infinity, leaving its sign alone + * __eldexp( a, n, b ) multiply by 2**n + * __emov( a, b ) b = a + * __emul( a, b, c ) c = b * a + * __eneg(e) e = -e + * __eround( a, b ) b = nearest integer value to a + * __esub( a, b, c ) c = b - a + * __e24toasc( &f, str, n ) single to ASCII string, n digits after decimal + * __e53toasc( &d, str, n ) double to ASCII string, n digits after decimal + * __e64toasc( &d, str, n ) long double to ASCII string + * __etoasc( e, str, n ) e to ASCII string, n digits after decimal + * __etoe24( e, &f ) convert e type to IEEE single precision + * __etoe53( e, &d ) convert e type to IEEE double precision + * __etoe64( e, &d ) convert e type to IEEE long double precision + * __eisneg( e ) 1 if sign bit of e != 0, else 0 + * __eisinf( e ) 1 if e has maximum exponent (non-IEEE) + * or is infinite (IEEE) + * __eisnan( e ) 1 if e is a NaN + * __esqrt( a, b ) b = square root of a + * + * + * Routines for internal format numbers + * + * __eaddm( ai, bi ) add significands, bi = bi + ai + * __ecleaz(ei) ei = 0 + * __ecleazs(ei) set ei = 0 but leave its sign alone + * __ecmpm( ai, bi ) compare significands, return 1, 0, or -1 + * __edivm( ai, bi ) divide significands, bi = bi / ai + * __emdnorm(ai,l,s,exp) normalize and round off + * __emovi( a, ai ) convert external a to internal ai + * __emovo( ai, a ) convert internal ai to external a + * __emovz( ai, bi ) bi = ai, low guard word of bi = 0 + * __emulm( ai, bi ) multiply significands, bi = bi * ai + * __enormlz(ei) left-justify the significand + * __eshdn1( ai ) shift significand and guards down 1 bit + * __eshdn8( ai ) shift down 8 bits + * __eshdn6( ai ) shift down 16 bits + * __eshift( ai, n ) shift ai n bits up (or down if n < 0) + * __eshup1( ai ) shift significand and guards up 1 bit + * __eshup8( ai ) shift up 8 bits + * __eshup6( ai ) shift up 16 bits + * __esubm( ai, bi ) subtract significands, bi = bi - ai + * + * + * The result is always normalized and rounded to NI-4 word precision + * after each arithmetic operation. + * + * Exception flags are NOT fully supported. + * + * Define INFINITY in mconf.h for support of infinity; otherwise a + * saturation arithmetic is implemented. + * + * Define NANS for support of Not-a-Number items; otherwise the + * arithmetic will never produce a NaN output, and might be confused + * by a NaN input. + * If NaN's are supported, the output of ecmp(a,b) is -2 if + * either a or b is a NaN. This means asking if(ecmp(a,b) < 0) + * may not be legitimate. Use if(ecmp(a,b) == -1) for less-than + * if in doubt. + * Signaling NaN's are NOT supported; they are treated the same + * as quiet NaN's. + * + * Denormals are always supported here where appropriate (e.g., not + * for conversion to DEC numbers). + */ + +#include +#include +#include +#include +#include +#include +#include + +#undef alloca +#define alloca __builtin_alloca + +/* Don't build non-ANSI _IO_ldtoa. It is not thread safe. */ +#ifndef USE_LDTOA +#define USE_LDTOA 0 +#endif + + + /* Number of 16 bit words in external x type format */ +#define NE 6 + + /* Number of 16 bit words in internal format */ +#define NI (NE+3) + + /* Array offset to exponent */ +#define E 1 + + /* Array offset to high guard word */ +#define M 2 + + /* Number of bits of precision */ +#define NBITS ((NI-4)*16) + + /* Maximum number of decimal digits in ASCII conversion + * = NBITS*log10(2) + */ +#define NDEC (NBITS*8/27) + + /* The exponent of 1.0 */ +#define EXONE (0x3fff) + + +#define mtherr(fname, code) + + +extern long double strtold (const char * __restrict__ s, char ** __restrict__ se); +extern int __asctoe64(const char * __restrict__ ss, + short unsigned int * __restrict__ y); +extern void __emul(const short unsigned int * a, + const short unsigned int * b, + short unsigned int * c); +extern int __ecmp(const short unsigned int * __restrict__ a, + const short unsigned int * __restrict__ b); +extern int __enormlz(short unsigned int *x); +extern int __eshift(short unsigned int *x, int sc); +extern void __eaddm(const short unsigned int * __restrict__ x, + short unsigned int * __restrict__ y); +extern void __esubm(const short unsigned int * __restrict__ x, + short unsigned int * __restrict__ y); +extern void __emdnorm(short unsigned int *s, int lost, int subflg, + int exp, int rcntrl, const int rndprc); +extern void __toe64(short unsigned int * __restrict__ a, + short unsigned int * __restrict__ b); +extern int __edivm(short unsigned int * __restrict__ den, + short unsigned int * __restrict__ num); +extern int __emulm(const short unsigned int * __restrict__ a, + short unsigned int * __restrict__ b); +extern void __emovi(const short unsigned int * __restrict__ a, + short unsigned int * __restrict__ b); +extern void __emovo(const short unsigned int * __restrict__ a, + short unsigned int * __restrict__ b); + +#if USE_LDTOA + +extern char * _IO_ldtoa(long double, int, int, int *, int *, char **); +extern void _IO_ldtostr(long double *x, char *string, int ndigs, + int flags, char fmt); + +extern void __eiremain(short unsigned int * __restrict__ den, + short unsigned int *__restrict__ num, + short unsigned int *__restrict__ equot); +extern void __efloor(short unsigned int *x, short unsigned int *y); +extern void __eadd1(const short unsigned int * __restrict__ a, + const short unsigned int * __restrict__ b, + short unsigned int * __restrict__ c, + int subflg); +extern void __esub(const short unsigned int *a, const short unsigned int *b, + short unsigned int *c); +extern void __ediv(const short unsigned int *a, const short unsigned int *b, + short unsigned int *c); +extern void __e64toe(short unsigned int *pe, short unsigned int *y); + + +#endif + +static __inline__ int __eisneg(const short unsigned int *x); +static __inline__ int __eisinf(const short unsigned int *x); +static __inline__ int __eisnan(const short unsigned int *x); +static __inline__ int __eiszero(const short unsigned int *a); +static __inline__ void __emovz(register const short unsigned int * __restrict__ a, + register short unsigned int * __restrict__ b); +static __inline__ void __eclear(register short unsigned int *x); +static __inline__ void __ecleaz(register short unsigned int *xi); +static __inline__ void __ecleazs(register short unsigned int *xi); +static __inline__ int __eiisinf(const short unsigned int *x); +static __inline__ int __eiisnan(const short unsigned int *x); +static __inline__ int __eiiszero(const short unsigned int *x); +static __inline__ void __enan_64(short unsigned int *nanptr); +static __inline__ void __enan_NBITS (short unsigned int *nanptr); +static __inline__ void __enan_NI16 (short unsigned int *nanptr); +static __inline__ void __einfin(register short unsigned int *x); +static __inline__ void __eneg(short unsigned int *x); +static __inline__ void __eshup1(register short unsigned int *x); +static __inline__ void __eshup8(register short unsigned int *x); +static __inline__ void __eshup6(register short unsigned int *x); +static __inline__ void __eshdn1(register short unsigned int *x); +static __inline__ void __eshdn8(register short unsigned int *x); +static __inline__ void __eshdn6(register short unsigned int *x); + + + +/* Intel IEEE, low order words come first: + */ +#define IBMPC 1 + +/* Define 1 for ANSI C atan2() function + * See atan.c and clog.c. + */ +#define ANSIC 1 + +/*define VOLATILE volatile*/ +#define VOLATILE + +/* For 12-byte long doubles on an i386, pad a 16-bit short 0 + * to the end of real constants initialized by integer arrays. + * + * #define XPD 0, + * + * Otherwise, the type is 10 bytes long and XPD should be + * defined blank. + * + * #define XPD + */ +#define XPD 0, +/* #define XPD */ +#define NANS 1 + +/* NaN's require infinity support. */ +#ifdef NANS +#ifndef INFINITY +#define INFINITY +#endif +#endif + +/* This handles 64-bit long ints. */ +#define LONGBITS (8 * sizeof(long)) + + +#define NTEN 12 +#define MAXP 4096 + +/* +; Clear out entire external format number. +; +; unsigned short x[]; +; eclear( x ); +*/ + +static __inline__ void __eclear(register short unsigned int *x) +{ + memset(x, 0, NE * sizeof(unsigned short)); +} + + +/* Move external format number from a to b. + * + * emov( a, b ); + */ + +static __inline__ void __emov(register const short unsigned int * __restrict__ a, + register short unsigned int * __restrict__ b) +{ + memcpy(b, a, NE * sizeof(unsigned short)); +} + + +/* +; Negate external format number +; +; unsigned short x[NE]; +; eneg( x ); +*/ + +static __inline__ void __eneg(short unsigned int *x) +{ +#ifdef NANS + if (__eisnan(x)) + return; +#endif + x[NE-1] ^= 0x8000; /* Toggle the sign bit */ +} + + +/* Return 1 if external format number is negative, + * else return zero. + */ +static __inline__ int __eisneg(const short unsigned int *x) +{ +#ifdef NANS + if (__eisnan(x)) + return (0); +#endif + if (x[NE-1] & 0x8000) + return (1); + else + return (0); +} + + +/* Return 1 if external format number has maximum possible exponent, + * else return zero. + */ +static __inline__ int __eisinf(const short unsigned int *x) +{ + if ((x[NE - 1] & 0x7fff) == 0x7fff) + { +#ifdef NANS + if (__eisnan(x)) + return (0); +#endif + return (1); + } + else + return (0); +} + +/* Check if e-type number is not a number. + */ +static __inline__ int __eisnan(const short unsigned int *x) +{ +#ifdef NANS + int i; + /* NaN has maximum __exponent */ + if ((x[NE - 1] & 0x7fff) == 0x7fff) + /* ... and non-zero significand field. */ + for (i = 0; i < NE - 1; i++) + { + if (*x++ != 0) + return (1); + } +#endif + return (0); +} + +/* +; Fill __entire number, including __exponent and significand, with +; largest possible number. These programs implement a saturation +; value that is an ordinary, legal number. A special value +; "infinity" may also be implemented; this would require tests +; for that value and implementation of special rules for arithmetic +; operations involving inifinity. +*/ + +static __inline__ void __einfin(register short unsigned int *x) +{ + register int i; +#ifdef INFINITY + for (i = 0; i < NE - 1; i++) + *x++ = 0; + *x |= 32767; +#else + for (i = 0; i < NE - 1; i++) + *x++ = 0xffff; + *x |= 32766; + *(x - 5) = 0; +#endif +} + +/* Clear out internal format number. + */ + +static __inline__ void __ecleaz(register short unsigned int *xi) +{ + memset(xi, 0, NI * sizeof(unsigned short)); +} + +/* same, but don't touch the sign. */ + +static __inline__ void __ecleazs(register short unsigned int *xi) +{ + ++xi; + memset(xi, 0, (NI-1) * sizeof(unsigned short)); +} + +/* Move internal format number from a to b. + */ +static __inline__ void __emovz(register const short unsigned int * __restrict__ a, + register short unsigned int * __restrict__ b) +{ + memcpy(b, a, (NI-1) * sizeof(unsigned short)); + b[NI - 1] = 0; +} + +/* Return nonzero if internal format number is a NaN. + */ + +static __inline__ int __eiisnan (const short unsigned int *x) +{ + int i; + + if ((x[E] & 0x7fff) == 0x7fff) + { + for (i = M + 1; i < NI; i++ ) + { + if (x[i] != 0) + return (1); + } + } + return (0); +} + +/* Return nonzero if external format number is zero. */ + +static __inline__ int +__eiszero(const short unsigned int * a) +{ + union { + long double ld; + unsigned short sh[8]; + } av; + av.ld = 0.0; + memcpy (av.sh, a, 12); + if (av.ld == 0.0) + return (1); + return (0); +} + +/* Return nonzero if internal format number is zero. */ + +static __inline__ int +__eiiszero(const short unsigned int * ai) +{ + int i; + /* skip the sign word */ + for (i = 1; i < NI - 1; i++ ) + { + if (ai[i] != 0) + return (0); + } + return (1); +} + + +/* Return nonzero if internal format number is infinite. */ + +static __inline__ int +__eiisinf (const unsigned short *x) +{ +#ifdef NANS + if (__eiisnan (x)) + return (0); +#endif + if ((x[E] & 0x7fff) == 0x7fff) + return (1); + return (0); +} + +/* +; Compare significands of numbers in internal format. +; Guard words are included in the comparison. +; +; unsigned short a[NI], b[NI]; +; cmpm( a, b ); +; +; for the significands: +; returns +1 if a > b +; 0 if a == b +; -1 if a < b +*/ +static __inline__ int __ecmpm(register const short unsigned int * __restrict__ a, + register const short unsigned int * __restrict__ b) +{ + int i; + + a += M; /* skip up to significand area */ + b += M; + for (i = M; i < NI; i++) + { + if( *a++ != *b++ ) + goto difrnt; + } + return(0); + + difrnt: + if ( *(--a) > *(--b) ) + return (1); + else + return (-1); +} + + +/* +; Shift significand down by 1 bit +*/ + +static __inline__ void __eshdn1(register short unsigned int *x) +{ + register unsigned short bits; + int i; + + x += M; /* point to significand area */ + + bits = 0; + for (i = M; i < NI; i++ ) + { + if (*x & 1) + bits |= 1; + *x >>= 1; + if (bits & 2) + *x |= 0x8000; + bits <<= 1; + ++x; + } +} + +/* +; Shift significand up by 1 bit +*/ + +static __inline__ void __eshup1(register short unsigned int *x) +{ + register unsigned short bits; + int i; + + x += NI-1; + bits = 0; + + for (i = M; i < NI; i++) + { + if (*x & 0x8000) + bits |= 1; + *x <<= 1; + if (bits & 2) + *x |= 1; + bits <<= 1; + --x; + } +} + + +/* +; Shift significand down by 8 bits +*/ + +static __inline__ void __eshdn8(register short unsigned int *x) +{ + register unsigned short newbyt, oldbyt; + int i; + + x += M; + oldbyt = 0; + for (i = M; i < NI; i++) + { + newbyt = *x << 8; + *x >>= 8; + *x |= oldbyt; + oldbyt = newbyt; + ++x; + } +} + +/* +; Shift significand up by 8 bits +*/ + +static __inline__ void __eshup8(register short unsigned int *x) +{ + int i; + register unsigned short newbyt, oldbyt; + + x += NI - 1; + oldbyt = 0; + + for (i = M; i < NI; i++) + { + newbyt = *x >> 8; + *x <<= 8; + *x |= oldbyt; + oldbyt = newbyt; + --x; + } +} + +/* +; Shift significand up by 16 bits +*/ + +static __inline__ void __eshup6(register short unsigned int *x) +{ + int i; + register unsigned short *p; + + p = x + M; + x += M + 1; + + for (i = M; i < NI - 1; i++) + *p++ = *x++; + + *p = 0; +} + +/* +; Shift significand down by 16 bits +*/ + +static __inline__ void __eshdn6(register short unsigned int *x) +{ + int i; + register unsigned short *p; + + x += NI - 1; + p = x + 1; + + for (i = M; i < NI - 1; i++) + *(--p) = *(--x); + + *(--p) = 0; +} + +/* +; Add significands +; x + y replaces y +*/ + +static __inline__ void __enan_64(unsigned short* nanptr) +{ + int i; + for (i = 0; i < 3; i++) + *nanptr++ = 0; + *nanptr++ = 0xc000; + *nanptr++ = 0x7fff; + *nanptr = 0; + return; +} + +static __inline__ void __enan_NBITS(unsigned short* nanptr) +{ + int i; + for (i = 0; i < NE - 2; i++) + *nanptr++ = 0; + *nanptr++ = 0xc000; + *nanptr = 0x7fff; + return; +} + +static __inline__ void __enan_NI16(unsigned short* nanptr) +{ + int i; + *nanptr++ = 0; + *nanptr++ = 0x7fff; + *nanptr++ = 0; + *nanptr++ = 0xc000; + for (i = 4; i < NI; i++) + *nanptr++ = 0; + return; +} + +#endif /* _CEPHES_EMATH_H */ + diff --git a/libc/mingw/math/cephes_mconf.h b/libc/mingw/math/cephes_mconf.h new file mode 100644 index 000000000..f502f187b --- /dev/null +++ b/libc/mingw/math/cephes_mconf.h @@ -0,0 +1,417 @@ +#include +#include + + +#define IBMPC 1 +#define ANSIPROT 1 +#define MINUSZERO 1 +#define INFINITIES 1 +#define NANS 1 +#define DENORMAL 1 +#define VOLATILE +#define mtherr(fname, code) +#define XPD 0, +#ifdef __x86_64__ +#define XPD_SHORT 0, 0, +#define XPD_LONG 0, +#else +#define XPD_SHORT +#define XPD_LONG +#endif + +#if UNK +typedef union uLD { long double ld; unsigned short sh[8]; long lo[4]; } uLD; +typedef union uD { double d; unsigned short sh[4]; } uD; +#elif IBMPC +typedef union uLD { unsigned short sh[8]; long double ld; long lo[4]; } uLD; +typedef union uD { unsigned short sh[4]; double d; } uD; +#elif MIEEE +typedef union uLD { long lo[4]; long double ld; unsigned short sh[8]; } uLD; +typedef union uD { unsigned short sh[4]; double d; } uD; +#else +#error Unknown uLD/uD type definition +#endif + +#define _CEPHES_USE_ERRNO + +#ifdef _CEPHES_USE_ERRNO +#define _SET_ERRNO(x) errno = (x) +#else +#define _SET_ERRNO(x) +#endif + +/* constants used by cephes functions */ + +/* double */ +#define MAXNUM 1.7976931348623158E308 +#define MAXLOG 7.09782712893383996843E2 +#define MINLOG -7.08396418532264106224E2 +#define LOGE2 6.93147180559945309417E-1 +#define LOG2E 1.44269504088896340736 +#define PI 3.14159265358979323846 +#define PIO2 1.57079632679489661923 +#define PIO4 7.85398163397448309616E-1 + +#define NEGZERO (-0.0) +#undef NAN +#undef INFINITY +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)) +#define INFINITY __builtin_huge_val() +#define NAN __builtin_nan("") +#else +extern double __INF; +#define INFINITY (__INF) +extern double __QNAN; +#define NAN (__QNAN) +#endif + +/*long double*/ +#if defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) +#define MAXNUML 1.7976931348623158E308 +#define MAXLOGL 7.09782712893383996843E2 +#define MINLOGL -7.08396418532264106224E2 +#define LOGE2L 6.93147180559945309417E-1 +#define LOG2EL 1.44269504088896340736 +#define PIL 3.14159265358979323846 +#define PIO2L 1.57079632679489661923 +#define PIO4L 7.85398163397448309616E-1 +#else +#define MAXNUML 1.189731495357231765021263853E4932L +#define MAXLOGL 1.1356523406294143949492E4L +#define MINLOGL -1.13994985314888605586758E4L +#define LOGE2L 6.9314718055994530941723E-1L +#define LOG2EL 1.4426950408889634073599E0L +#define PIL 3.1415926535897932384626L +#define PIO2L 1.5707963267948966192313L +#define PIO4L 7.8539816339744830961566E-1L +#endif /* defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) */ + +#define isfinitel isfinite +#define isinfl isinf +#define isnanl isnan +#define signbitl signbit + +#define NEGZEROL (-0.0L) + +#undef NANL +#undef INFINITYL +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)) +#define INFINITYL __builtin_huge_vall() +#define NANL __builtin_nanl("") +#else +extern long double __INFL; +#define INFINITYL (__INFL) +extern long double __QNANL; +#define NANL (__QNANL) +#endif + +/* float */ + +#define MAXNUMF 3.4028234663852885981170418348451692544e38F +#define MAXLOGF 88.72283905206835F +#define MINLOGF -103.278929903431851103F /* log(2^-149) */ +#define LOG2EF 1.44269504088896341F +#define LOGE2F 0.693147180559945309F +#define PIF 3.141592653589793238F +#define PIO2F 1.5707963267948966192F +#define PIO4F 0.7853981633974483096F + +#define isfinitef isfinite +#define isinff isinf +#define isnanf isnan +#define signbitf signbit + +#define NEGZEROF (-0.0F) + +#undef NANF +#undef INFINITYF +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)) +#define INFINITYF __builtin_huge_valf() +#define NANF __builtin_nanf("") +#else +extern float __INFF; +#define INFINITYF (__INFF) +extern float __QNANF; +#define NANF (__QNANF) +#endif + + +/* double */ + +/* +Cephes Math Library Release 2.2: July, 1992 +Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier +Direct inquiries to 30 Frost Street, Cambridge, MA 02140 +*/ + + +/* polevl.c + * p1evl.c + * + * Evaluate polynomial + * + * + * + * SYNOPSIS: + * + * int N; + * double x, y, coef[N+1], polevl[]; + * + * y = polevl( x, coef, N ); + * + * + * + * DESCRIPTION: + * + * Evaluates polynomial of degree N: + * + * 2 N + * y = C + C x + C x +...+ C x + * 0 1 2 N + * + * Coefficients are stored in reverse order: + * + * coef[0] = C , ..., coef[N] = C . + * N 0 + * + * The function p1evl() assumes that coef[N] = 1.0 and is + * omitted from the array. Its calling arguments are + * otherwise the same as polevl(). + * + * + * SPEED: + * + * In the interest of speed, there are no checks for out + * of bounds arithmetic. This routine is used by most of + * the functions in the library. Depending on available + * equipment features, the user may wish to rewrite the + * program in microcode or assembly language. + * + */ + +/* Polynomial evaluator: + * P[0] x^n + P[1] x^(n-1) + ... + P[n] + */ +static __inline__ double polevl(double x, const uD *p, int n) +{ + register double y; + + y = p->d; + p++; + do + { + y = y * x + p->d; + p++; + } + while (--n); + return (y); +} + + +/* Polynomial evaluator: + * x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n] + */ +static __inline__ double p1evl(double x, const uD *p, int n) +{ + register double y; + + n -= 1; + y = x + p->d; p++; + do + { + y = y * x + p->d; p++; + } + while (--n); + return (y); +} + + +/* long double */ +/* +Cephes Math Library Release 2.2: July, 1992 +Copyright 1984, 1987, 1988, 1992 by Stephen L. Moshier +Direct inquiries to 30 Frost Street, Cambridge, MA 02140 +*/ + + +/* polevll.c + * p1evll.c + * + * Evaluate polynomial + * + * + * + * SYNOPSIS: + * + * int N; + * long double x, y, coef[N+1], polevl[]; + * + * y = polevll( x, coef, N ); + * + * + * + * DESCRIPTION: + * + * Evaluates polynomial of degree N: + * + * 2 N + * y = C + C x + C x +...+ C x + * 0 1 2 N + * + * Coefficients are stored in reverse order: + * + * coef[0] = C , ..., coef[N] = C . + * N 0 + * + * The function p1evll() assumes that coef[N] = 1.0 and is + * omitted from the array. Its calling arguments are + * otherwise the same as polevll(). + * + * + * SPEED: + * + * In the interest of speed, there are no checks for out + * of bounds arithmetic. This routine is used by most of + * the functions in the library. Depending on available + * equipment features, the user may wish to rewrite the + * program in microcode or assembly language. + * + */ + +/* Polynomial evaluator: + * P[0] x^n + P[1] x^(n-1) + ... + P[n] + */ +static __inline__ long double polevll(long double x, const uLD *p, int n) +{ + register long double y; + + y = p->ld; + p++; + do + { + y = y * x + p->ld; + p++; + } + while (--n); + return y; +} + + + +/* Polynomial evaluator: + * x^n + P[0] x^(n-1) + P[1] x^(n-2) + ... + P[n] + */ +static __inline__ long double p1evll(long double x, const uLD *p, int n) +{ + register long double y; + + n -= 1; + y = x + p->ld; + p++; + + do + { + y = y * x + p->ld; + p++; + } + while (--n); + return (y); +} + +/* Float version */ + +/* polevlf.c + * p1evlf.c + * + * Evaluate polynomial + * + * + * + * SYNOPSIS: + * + * int N; + * float x, y, coef[N+1], polevlf[]; + * + * y = polevlf( x, coef, N ); + * + * + * + * DESCRIPTION: + * + * Evaluates polynomial of degree N: + * + * 2 N + * y = C + C x + C x +...+ C x + * 0 1 2 N + * + * Coefficients are stored in reverse order: + * + * coef[0] = C , ..., coef[N] = C . + * N 0 + * + * The function p1evl() assumes that coef[N] = 1.0 and is + * omitted from the array. Its calling arguments are + * otherwise the same as polevl(). + * + * + * SPEED: + * + * In the interest of speed, there are no checks for out + * of bounds arithmetic. This routine is used by most of + * the functions in the library. Depending on available + * equipment features, the user may wish to rewrite the + * program in microcode or assembly language. + * + */ + +/* +Cephes Math Library Release 2.1: December, 1988 +Copyright 1984, 1987, 1988 by Stephen L. Moshier +Direct inquiries to 30 Frost Street, Cambridge, MA 02140 +*/ + +static __inline__ float polevlf(float x, const float* coef, int N) +{ + float ans; + float *p; + int i; + + p = (float*)coef; + ans = *p++; + + /* + for (i = 0; i < N; i++) + ans = ans * x + *p++; + */ + + i = N; + do + ans = ans * x + *p++; + while (--i); + + return (ans); +} + +/* p1evl() */ +/* N + * Evaluate polynomial when coefficient of x is 1.0. + * Otherwise same as polevl. + */ + +static __inline__ float p1evlf(float x, const float *coef, int N) +{ + float ans; + float *p; + int i; + + p = (float*)coef; + ans = x + *p++; + i = N - 1; + + do + ans = ans * x + *p++; + while (--i); + + return (ans); +} + diff --git a/libc/mingw/math/copysign.c b/libc/mingw/math/copysign.c new file mode 100644 index 000000000..c3fe76f0d --- /dev/null +++ b/libc/mingw/math/copysign.c @@ -0,0 +1,21 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +typedef union U +{ + unsigned int u[2]; + double d; +} U; + +double copysign(double x, double y) +{ + U h,j; + h.d = x; + j.d = y; + h.u[1] = (h.u[1] & 0x7fffffff) | (j.u[1] & 0x80000000); + return h.d; +} diff --git a/libc/mingw/math/copysignf.c b/libc/mingw/math/copysignf.c new file mode 100644 index 000000000..0fba92bc7 --- /dev/null +++ b/libc/mingw/math/copysignf.c @@ -0,0 +1,19 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +typedef union ui_f { + float f; + unsigned int ui; +} ui_f; + +float copysignf(float aX, float aY) +{ + ui_f x,y; + x.f=aX; y.f=aY; + x.ui= (x.ui & 0x7fffffff) | (y.ui & 0x80000000); + return x.f; +} diff --git a/libc/mingw/math/coshf.c b/libc/mingw/math/coshf.c new file mode 100644 index 000000000..72147f5bf --- /dev/null +++ b/libc/mingw/math/coshf.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +float coshf (float x) +{ + return (float) cosh (x); +} diff --git a/libc/mingw/math/coshl.c b/libc/mingw/math/coshl.c new file mode 100644 index 000000000..d7eb4b7cb --- /dev/null +++ b/libc/mingw/math/coshl.c @@ -0,0 +1,45 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" + +#ifndef _SET_ERRNO +#define _SET_ERRNO(x) +#endif + +long double coshl(long double x) +{ + long double y; + int x_class = fpclassify (x); + if (x_class == FP_NAN) + { + errno = EDOM; + return x; + } + else if (x_class == FP_INFINITE) + { + errno = ERANGE; + return x; + } + x = fabsl (x); + if (x > (MAXLOGL + LOGE2L)) + { + errno = ERANGE; +#ifdef INFINITIES + return (INFINITYL); +#else + return (MAXNUML); +#endif + } + if (x >= (MAXLOGL - LOGE2L)) + { + y = expl(0.5L * x); + y = (0.5L * y) * y; + return y; + } + y = expl(x); + y = 0.5L * (y + 1.0L / y); + return y; +} diff --git a/libc/mingw/math/erfl.c b/libc/mingw/math/erfl.c new file mode 100644 index 000000000..3832fe9e0 --- /dev/null +++ b/libc/mingw/math/erfl.c @@ -0,0 +1,303 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* erfl.c + * + * Error function + * + * + * + * SYNOPSIS: + * + * long double x, y, erfl(); + * + * y = erfl( x ); + * + * + * + * DESCRIPTION: + * + * The integral is + * + * x + * - + * 2 | | 2 + * erf(x) = -------- | exp( - t ) dt. + * sqrt(pi) | | + * - + * 0 + * + * The magnitude of x is limited to about 106.56 for IEEE + * arithmetic; 1 or -1 is returned outside this range. + * + * For 0 <= |x| < 1, erf(x) = x * P6(x^2)/Q6(x^2); + * Otherwise: erf(x) = 1 - erfc(x). + * + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * IEEE 0,1 50000 2.0e-19 5.7e-20 + * + */ + +/* erfcl.c + * + * Complementary error function + * + * + * + * SYNOPSIS: + * + * long double x, y, erfcl(); + * + * y = erfcl( x ); + * + * + * + * DESCRIPTION: + * + * + * 1 - erf(x) = + * + * inf. + * - + * 2 | | 2 + * erfc(x) = -------- | exp( - t ) dt + * sqrt(pi) | | + * - + * x + * + * + * For small x, erfc(x) = 1 - erf(x); otherwise rational + * approximations are computed. + * + * A special function expx2l.c is used to suppress error amplification + * in computing exp(-x^2). + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * IEEE 0,13 50000 8.4e-19 9.7e-20 + * IEEE 6,106.56 20000 2.9e-19 7.1e-20 + * + * + * ERROR MESSAGES: + * + * message condition value returned + * erfcl underflow x^2 > MAXLOGL 0.0 + * + * + */ + + +/* +Modified from file ndtrl.c +Cephes Math Library Release 2.3: January, 1995 +Copyright 1984, 1995 by Stephen L. Moshier +*/ + +#include +#include "cephes_mconf.h" + +long double erfl(long double x); + +/* erfc(x) = exp(-x^2) P(1/x)/Q(1/x) + 1/8 <= 1/x <= 1 + Peak relative error 5.8e-21 */ + +static const uLD P[10] = { + { { 0x4bf0,0x9ad8,0x7a03,0x86c7,0x401d, 0, 0, 0 } }, + { { 0xdf23,0xd843,0x4032,0x8881,0x401e, 0, 0, 0 } }, + { { 0xd025,0xcfd5,0x8494,0x88d3,0x401e, 0, 0, 0 } }, + { { 0xb6d0,0xc92b,0x5417,0xacb1,0x401d, 0, 0, 0 } }, + { { 0xada8,0x356a,0x4982,0x94a6,0x401c, 0, 0, 0 } }, + { { 0x4e13,0xcaee,0x9e31,0xb258,0x401a, 0, 0, 0 } }, + { { 0x5840,0x554d,0x37a3,0x9239,0x4018, 0, 0, 0 } }, + { { 0x3b58,0x3da2,0xaf02,0x9780,0x4015, 0, 0, 0 } }, + { { 0x0144,0x489e,0xbe68,0x9c31,0x4011, 0, 0, 0 } }, + { { 0x333b,0xd9e6,0xd404,0x986f,0xbfee, 0, 0, 0 } } +}; +static const uLD Q[] = { + { { 0x0e43,0x302d,0x79ed,0x86c7,0x401d, 0, 0, 0 } }, + { { 0xf817,0x9128,0xc0f8,0xd48b,0x401e, 0, 0, 0 } }, + { { 0x8eae,0x8dad,0x6eb4,0x9aa2,0x401f, 0, 0, 0 } }, + { { 0x00e7,0x7595,0xcd06,0x88bb,0x401f, 0, 0, 0 } }, + { { 0x4991,0xcfda,0x52f1,0xa2a9,0x401e, 0, 0, 0 } }, + { { 0xc39d,0xe415,0xc43d,0x87c0,0x401d, 0, 0, 0 } }, + { { 0xa75d,0x436f,0x30dd,0xa027,0x401b, 0, 0, 0 } }, + { { 0xc4cb,0x305a,0xbf78,0x8220,0x4019, 0, 0, 0 } }, + { { 0x3708,0x33b1,0x07fa,0x8644,0x4016, 0, 0, 0 } }, + { { 0x24fa,0x96f6,0x7153,0x8a6c,0x4012, 0, 0, 0 } } +}; + +/* erfc(x) = exp(-x^2) 1/x R(1/x^2) / S(1/x^2) + 1/128 <= 1/x < 1/8 + Peak relative error 1.9e-21 */ + +static const uLD R[] = { + { { 0x260a,0xab95,0x2fc7,0xe7c4,0x4000, 0, 0, 0 } }, + { { 0x4761,0x613e,0xdf6d,0xe58e,0x4001, 0, 0, 0 } }, + { { 0x0615,0x4b00,0x575f,0xdc7b,0x4000, 0, 0, 0 } }, + { { 0x521d,0x8527,0x3435,0x8dc2,0x3ffe, 0, 0, 0 } }, + { { 0x22cf,0xc711,0x6c5b,0xdcfb,0x3ff9, 0, 0, 0 } } +}; +static const uLD S[] = { + { { 0x5de6,0x17d7,0x54d6,0xaba9,0x4002, 0, 0, 0 } }, + { { 0x55d5,0xd300,0xe71e,0xf564,0x4002, 0, 0, 0 } }, + { { 0xb611,0x8f76,0xf020,0xd255,0x4001, 0, 0, 0 } }, + { { 0x3684,0x3798,0xb793,0x80b0,0x3fff, 0, 0, 0 } }, + { { 0xf5af,0x2fb2,0x1e57,0xc3d7,0x3ffa, 0, 0, 0 } } +}; + +/* erf(x) = x T(x^2)/U(x^2) + 0 <= x <= 1 + Peak relative error 7.6e-23 */ + +static const uLD T[] = { + { { 0xfd7a,0x3a1a,0x705b,0xe0c4,0x3ffb, 0, 0, 0 } }, + { { 0x3128,0xc337,0x3716,0xace5,0x4001, 0, 0, 0 } }, + { { 0x9517,0x4e93,0x540e,0x8f97,0x4007, 0, 0, 0 } }, + { { 0x6118,0x6059,0x9093,0xa757,0x400a, 0, 0, 0 } }, + { { 0xb954,0xa987,0xc60c,0xbc83,0x400e, 0, 0, 0 } }, + { { 0x7a56,0xe45a,0xa4bd,0x975b,0x4010, 0, 0, 0 } }, + { { 0xc446,0x6bab,0x0b2a,0x86d0,0x4013, 0, 0, 0 } } +}; + +static const uLD U[] = { + { { 0x3453,0x1f8e,0xf688,0xb507,0x4004, 0, 0, 0 } }, + { { 0x71ac,0xb12f,0x21ca,0xf2e2,0x4008, 0, 0, 0 } }, + { { 0xffe8,0x9cac,0x3b84,0xc2ac,0x400c, 0, 0, 0 } }, + { { 0x481d,0x445b,0xc807,0xc232,0x400f, 0, 0, 0 } }, + { { 0x9ad5,0x1aef,0x45b1,0xe25e,0x4011, 0, 0, 0 } }, + { { 0x71a7,0x1cad,0x012e,0xeef3,0x4012, 0, 0, 0 } } +}; + +/* expx2l.c + * + * Exponential of squared argument + * + * + * + * SYNOPSIS: + * + * long double x, y, expmx2l(); + * int sign; + * + * y = expx2l( x ); + * + * + * + * DESCRIPTION: + * + * Computes y = exp(x*x) while suppressing error amplification + * that would ordinarily arise from the inexactness of the + * exponential argument x*x. + * + * + * + * ACCURACY: + * + * Relative error: + * arithmetic domain # trials peak rms + * IEEE -106.566, 106.566 10^5 1.6e-19 4.4e-20 + * + */ + +#define M 32768.0L +#define MINV 3.0517578125e-5L + +static long double expx2l (long double x) +{ + long double u, u1, m, f; + + x = fabsl (x); + /* Represent x as an exact multiple of M plus a residual. + M is a power of 2 chosen so that exp(m * m) does not overflow + or underflow and so that |x - m| is small. */ + m = MINV * floorl(M * x + 0.5L); + f = x - m; + + /* x^2 = m^2 + 2mf + f^2 */ + u = m * m; + u1 = 2 * m * f + f * f; + + if ((u + u1) > MAXLOGL) + return (INFINITYL); + + /* u is exact, u1 is small. */ + u = expl(u) * expl(u1); + return (u); +} + +long double erfcl(long double a) +{ + long double p, q, x, y, z; + + if (isinf (a)) + return (signbit(a) ? 2.0 : 0.0); + + x = fabsl (a); + + if (x < 1.0L) + return (1.0L - erfl(a)); + + z = a * a; + + if (z > MAXLOGL) + { +under: + mtherr("erfcl", UNDERFLOW); + errno = ERANGE; + return (signbit(a) ? 2.0 : 0.0); + } + + /* Compute z = expl(a * a). */ + z = expx2l(a); + y = 1.0L/x; + + if (x < 8.0L) + { + p = polevll(y, P, 9); + q = p1evll(y, Q, 10); + } + else + { + q = y * y; + p = y * polevll(q, R, 4); + q = p1evll(q, S, 5); + } + y = p/(q * z); + + if (a < 0.0L) + y = 2.0L - y; + + if (y == 0.0L) + goto under; + + return (y); +} + +long double erfl(long double x) +{ + long double y, z; + + if (x == 0.0L) + return (x); + + if (isinf (x)) + return (signbit(x) ? -1.0L : 1.0L); + + if (fabsl(x) > 1.0L) + return (1.0L - erfcl(x)); + + z = x * x; + y = x * polevll(z, T, 6) / p1evll(z, U, 6); + return (y); +} diff --git a/libc/mingw/math/expf.c b/libc/mingw/math/expf.c new file mode 100644 index 000000000..69d7edc2b --- /dev/null +++ b/libc/mingw/math/expf.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float expf (float x) +{ + return (float) exp (x); +} diff --git a/libc/mingw/math/fabs.c b/libc/mingw/math/fabs.c new file mode 100644 index 000000000..a6637114f --- /dev/null +++ b/libc/mingw/math/fabs.c @@ -0,0 +1,20 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +double +fabs (double x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + return __builtin_fabs (x); +#elif defined(__i386__) || defined(_X86_) + double res = 0.0; + + asm volatile ("fabs;" : "=t" (res) : "0" (x)); + return res; +#endif /* defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) */ +} diff --git a/libc/mingw/math/fabsf.c b/libc/mingw/math/fabsf.c new file mode 100644 index 000000000..e7e9d8fa7 --- /dev/null +++ b/libc/mingw/math/fabsf.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +float fabsf (float x); + +float +fabsf (float x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + return __builtin_fabsf (x); +#elif defined(__i386__) || defined(_X86_) + float res = 0.0F; + asm volatile ("fabs;" : "=t" (res) : "0" (x)); + return res; +#endif /* defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) */ +} diff --git a/libc/mingw/math/fabsl.c b/libc/mingw/math/fabsl.c new file mode 100644 index 000000000..1df48cfa9 --- /dev/null +++ b/libc/mingw/math/fabsl.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +long double fabsl (long double x); + +long double +fabsl (long double x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__i386__) || defined(_X86_) + long double res = 0.0L; + asm volatile ("fabs;" : "=t" (res) : "0" (x)); + return res; +#elif defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + return __builtin_fabsl (x); +#endif /* defined(__x86_64__) || defined(_AMD64_) || defined(__i386__) || defined(_X86_) */ +} diff --git a/libc/mingw/math/fdim.c b/libc/mingw/math/fdim.c new file mode 100644 index 000000000..aec62c4a9 --- /dev/null +++ b/libc/mingw/math/fdim.c @@ -0,0 +1,24 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +double +fdim (double x, double y) +{ + int cx = fpclassify (x), cy = fpclassify (y); + double r; + + if (cx == FP_NAN || cy == FP_NAN + || (y < 0 && cx == FP_INFINITE && cy == FP_INFINITE)) + return x - y; /* Take care invalid flag is raised. */ + if (x <= y) + return 0.0; + r = x - y; + if (fpclassify (r) == FP_INFINITE) + errno = ERANGE; + return r; +} diff --git a/libc/mingw/math/fdimf.c b/libc/mingw/math/fdimf.c new file mode 100644 index 000000000..3312a932b --- /dev/null +++ b/libc/mingw/math/fdimf.c @@ -0,0 +1,24 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +float +fdimf (float x, float y) +{ + int cx = fpclassify (x), cy = fpclassify (y); + float r; + + if (cx == FP_NAN || cy == FP_NAN + || (y < 0 && cx == FP_INFINITE && cy == FP_INFINITE)) + return x - y; /* Take care invalid flag is raised. */ + if (x <= y) + return 0.0f; + r = x - y; + if (fpclassify (r) == FP_INFINITE) + errno = ERANGE; + return r; +} diff --git a/libc/mingw/math/fdiml.c b/libc/mingw/math/fdiml.c new file mode 100644 index 000000000..3be0679ac --- /dev/null +++ b/libc/mingw/math/fdiml.c @@ -0,0 +1,24 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +long double +fdiml (long double x, long double y) +{ + int cx = fpclassify (x), cy = fpclassify (y); + long double r; + + if (cx == FP_NAN || cy == FP_NAN + || (y < 0 && cx == FP_INFINITE && cy == FP_INFINITE)) + return x - y; /* Take care invalid flag is raised. */ + if (x <= y) + return 0.0; + r = x - y; + if (fpclassify (r) == FP_INFINITE) + errno = ERANGE; + return r; +} diff --git a/libc/mingw/math/fma.c b/libc/mingw/math/fma.c new file mode 100644 index 000000000..c4ce738be --- /dev/null +++ b/libc/mingw/math/fma.c @@ -0,0 +1,41 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +double fma(double x, double y, double z); + +#if defined(_ARM_) || defined(__arm__) + +/* Use hardware FMA on ARM. */ +double fma(double x, double y, double z){ + __asm__ ( + "fmacd %0, %1, %2 \n" + : "+w"(z) + : "w"(x), "w"(y) + ); + return z; +} + +#elif defined(_ARM64_) || defined(__aarch64__) + +/* Use hardware FMA on ARM64. */ +double fma(double x, double y, double z){ + __asm__ ( + "fmadd %d0, %d1, %d2, %d0 \n" + : "+w"(z) + : "w"(x), "w"(y) + ); + return z; +} + +#else + +long double fmal(long double x, long double y, long double z); + +/* For platforms that don't have hardware FMA, emulate it. */ +double fma(double x, double y, double z){ + return (double)fmal(x, y, z); +} + +#endif diff --git a/libc/mingw/math/fmaf.c b/libc/mingw/math/fmaf.c new file mode 100644 index 000000000..b3f58a84a --- /dev/null +++ b/libc/mingw/math/fmaf.c @@ -0,0 +1,41 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +float fmaf(float x, float y, float z); + +#if defined(_ARM_) || defined(__arm__) + +/* Use hardware FMA on ARM. */ +float fmaf(float x, float y, float z){ + __asm__ ( + "fmacs %0, %1, %2 \n" + : "+t"(z) + : "t"(x), "t"(y) + ); + return z; +} + +#elif defined(_ARM64_) || defined(__aarch64__) + +/* Use hardware FMA on ARM64. */ +float fmaf(float x, float y, float z){ + __asm__ ( + "fmadd %s0, %s1, %s2, %s0 \n" + : "+w"(z) + : "w"(x), "w"(y) + ); + return z; +} + +#else + +long double fmal(long double x, long double y, long double z); + +/* For platforms that don't have hardware FMA, emulate it. */ +float fmaf(float x, float y, float z){ + return (float)fmal(x, y, z); +} + +#endif diff --git a/libc/mingw/math/fmal.c b/libc/mingw/math/fmal.c new file mode 100644 index 000000000..bea674212 --- /dev/null +++ b/libc/mingw/math/fmal.c @@ -0,0 +1,145 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +long double fmal(long double x, long double y, long double z); + +#if defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) + +double fma(double x, double y, double z); + +/* On ARM `long double` is 64 bits. And ARM has hardware FMA. */ +long double fmal(long double x, long double y, long double z){ + return fma(x, y, z); +} + +#elif defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + +/** + * x87-specific software-emulated FMA by LH_Mouse (lh_mouse at 126 dot com). + * This file is donated to the mingw-w64 project. + * Note: This file requires C99 support to compile. + */ + +#include +#include +#include +#include + +/* https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format */ +typedef union x87reg_ { + struct __attribute__((__packed__)) { + union { + uint64_t f64; + struct { + uint32_t flo; + uint32_t fhi; + }; + }; + uint16_t exp : 15; + uint16_t sgn : 1; + }; + long double f; +} x87reg; + +static inline void break_down(x87reg *restrict lo, x87reg *restrict hi, long double x){ + hi->f = x; + const uint32_t flo = hi->flo; + const long exp = hi->exp; + const bool sgn = hi->sgn; + /* Erase low-order significant bits. `hi->f` now has only 32 significant bits. */ + hi->flo = 0; + + if(flo == 0){ + /* If the low-order significant bits are all zeroes, return zero in `lo->f`. */ + lo->f64 = 0; + lo->exp = 0; + } else { + /* How many bits should we shift to normalize the floating point value? */ + const long shn = __builtin_clzl(flo) - (sizeof(long) - sizeof(uint32_t)) * CHAR_BIT + 32; +#if 0 /* Naive implementation */ + if(shn < exp){ + /* `x` can be normalized, normalize it. */ + lo->f64 = (uint64_t)flo << shn; + lo->exp = (exp - shn) & 0x7FFF; + } else { + /* Otherwise, go with a denormal number. */ + if(exp > 0){ + /* Denormalize the source normal number. */ + lo->f64 = (uint64_t)flo << (exp - 1); + } else { + /* Leave the source denormal number as is. */ + lo->f64 = flo; + } + lo->exp = 0; + } +#else /* Optimal implementation */ + const long mask = (shn - exp) >> 31; /* mask = (shn < exp) ? -1 : 0 */ + long expm1 = exp - 1; + expm1 &= ~(expm1 >> 31); /* expm1 = (exp - 1 >= 0) ? (exp - 1) : 0 */ + lo->f64 = (uint64_t)flo << (((shn ^ expm1) & mask) ^ expm1); + /* f64 = flo << ((shn < exp) ? shn : expm1) */ + lo->exp = (exp - shn) & mask; /* exp = (shn < exp) ? (exp - shn) : 0 */ +#endif + } + lo->sgn = sgn; +} +static inline long double fpu_fma(long double x, long double y, long double z){ + /* + POSIX-2013: + 1. If x or y are NaN, a NaN shall be returned. + 2. If x multiplied by y is an exact infinity and z is also an infinity + but with the opposite sign, a domain error shall occur, and either a NaN + (if supported), or an implementation-defined value shall be returned. + 3. If one of x and y is infinite, the other is zero, and z is not a NaN, + a domain error shall occur, and either a NaN (if supported), or an + implementation-defined value shall be returned. + 4. If one of x and y is infinite, the other is zero, and z is a NaN, a NaN + shall be returned and a domain error may occur. + 5. If x* y is not 0*Inf nor Inf*0 and z is a NaN, a NaN shall be returned. + */ + if(__fpclassifyl(x) == FP_NAN){ + return x; /* Handle case 1. */ + } + if(__fpclassifyl(y) == FP_NAN){ + return y; /* Handle case 1. */ + } + /* Handle case 2, 3 and 4 universally. Thanks to x87 a NaN is generated + if an INF is multiplied with zero, saving us a huge amount of work. */ + const long double xy = x * y; + if(__fpclassifyl(xy) == FP_NAN){ + return xy; /* Handle case 2, 3 and 4. */ + } + if(__fpclassifyl(z) == FP_NAN){ + return z; /* Handle case 5. */ + } + /* Check whether the result is finite. */ + const long double xyz = xy + z; + const int cxyz = __fpclassifyl(xyz); + if((cxyz == FP_NAN) || (cxyz == FP_INFINITE)){ + return xyz; /* If this naive check doesn't yield a finite value, the FMA isn't + likely to return one either. Forward the value as is. */ + } + + long double ret; + x87reg xlo, xhi, ylo, yhi; + break_down(&xlo, &xhi, x); + break_down(&ylo, &yhi, y); + /* The order of these four statements is essential. Don't move them around. */ + ret = z; + ret += xhi.f * yhi.f; /* The most significant item comes first. */ + ret += xhi.f * ylo.f + xlo.f * yhi.f; /* They are equally significant. */ + ret += xlo.f * ylo.f; /* The least significant item comes last. */ + return ret; +} + +long double fmal(long double x, long double y, long double z){ + return fpu_fma(x, y, z); +} + +#else + +#error Please add FMA implementation for this platform. + +#endif diff --git a/libc/mingw/math/fmax.c b/libc/mingw/math/fmax.c new file mode 100644 index 000000000..79f330c49 --- /dev/null +++ b/libc/mingw/math/fmax.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +double +fmax (double _x, double _y) +{ + return ( isgreaterequal (_x, _y)|| __isnan (_y) ? _x : _y ); +} diff --git a/libc/mingw/math/fmaxf.c b/libc/mingw/math/fmaxf.c new file mode 100644 index 000000000..677a8a735 --- /dev/null +++ b/libc/mingw/math/fmaxf.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float +fmaxf (float _x, float _y) +{ + return (( isgreaterequal(_x, _y) || __isnanf (_y)) ? _x : _y ); +} diff --git a/libc/mingw/math/fmaxl.c b/libc/mingw/math/fmaxl.c new file mode 100644 index 000000000..15c5b47ec --- /dev/null +++ b/libc/mingw/math/fmaxl.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long double +fmaxl (long double _x, long double _y) +{ + return (( isgreaterequal(_x, _y) || __isnanl (_y)) ? _x : _y ); +} diff --git a/libc/mingw/math/fmin.c b/libc/mingw/math/fmin.c new file mode 100644 index 000000000..80695745a --- /dev/null +++ b/libc/mingw/math/fmin.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +double +fmin (double _x, double _y) +{ + return ((islessequal(_x, _y) || __isnan (_y)) ? _x : _y ); +} diff --git a/libc/mingw/math/fminf.c b/libc/mingw/math/fminf.c new file mode 100644 index 000000000..2703cb197 --- /dev/null +++ b/libc/mingw/math/fminf.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float +fminf (float _x, float _y) +{ + return ((islessequal(_x, _y) || __isnanf (_y)) ? _x : _y ); +} diff --git a/libc/mingw/math/fminl.c b/libc/mingw/math/fminl.c new file mode 100644 index 000000000..96f08f79e --- /dev/null +++ b/libc/mingw/math/fminl.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long double +fminl (long double _x, long double _y) +{ + return ((islessequal(_x, _y) || __isnanl (_y)) ? _x : _y ); +} diff --git a/libc/mingw/math/fp_consts.c b/libc/mingw/math/fp_consts.c new file mode 100644 index 000000000..12330392a --- /dev/null +++ b/libc/mingw/math/fp_consts.c @@ -0,0 +1,20 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "fp_consts.h" +const union _ieee_rep __QNAN = { __DOUBLE_QNAN_REP }; +const union _ieee_rep __SNAN = { __DOUBLE_SNAN_REP }; +const union _ieee_rep __INF = { __DOUBLE_INF_REP }; +const union _ieee_rep __DENORM = { __DOUBLE_DENORM_REP }; + +/* ISO C99 */ +#undef nan +/* FIXME */ +double nan (const char *); +double nan (const char * tagp __attribute__((unused)) ) +{ + return __QNAN.double_val; +} + diff --git a/libc/mingw/math/fp_consts.h b/libc/mingw/math/fp_consts.h new file mode 100644 index 000000000..bcd173e3a --- /dev/null +++ b/libc/mingw/math/fp_consts.h @@ -0,0 +1,54 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _FP_CONSTS_H +#define _FP_CONSTS_H + +/* +According to IEEE 754 a QNaN has exponent bits of all 1 values and +initial significand bit of 1. A SNaN has has an exponent of all 1 +values and initial significand bit of 0 (with one or more other +significand bits of 1). An Inf has significand of 0 and +exponent of all 1 values. A denormal value has all exponent bits of 0. + +The following does _not_ follow those rules, but uses values +equal to those exported from MS C++ runtime lib, msvcprt.dll +for float and double. MSVC however, does not have long doubles. +*/ + + +#define __DOUBLE_INF_REP { 0, 0, 0, 0x7ff0 } +#define __DOUBLE_QNAN_REP { 0, 0, 0, 0xfff8 } /* { 0, 0, 0, 0x7ff8 } */ +#define __DOUBLE_SNAN_REP { 0, 0, 0, 0xfff0 } /* { 1, 0, 0, 0x7ff0 } */ +#define __DOUBLE_DENORM_REP {1, 0, 0, 0} + +#define D_NAN_MASK 0x7ff0000000000000LL /* this will mask NaN's and Inf's */ + +#define __FLOAT_INF_REP { 0, 0x7f80 } +#define __FLOAT_QNAN_REP { 0, 0xffc0 } /* { 0, 0x7fc0 } */ +#define __FLOAT_SNAN_REP { 0, 0xff80 } /* { 1, 0x7f80 } */ +#define __FLOAT_DENORM_REP {1,0} + +#define F_NAN_MASK 0x7f800000 + +/* + This assumes no implicit (hidden) bit in extended mode. + Padded to 96 bits + */ +#define __LONG_DOUBLE_INF_REP { 0, 0, 0, 0x8000, 0x7fff, 0 } +#define __LONG_DOUBLE_QNAN_REP { 0, 0, 0, 0xc000, 0xffff, 0 } +#define __LONG_DOUBLE_SNAN_REP { 0, 0, 0, 0x8000, 0xffff, 0 } +#define __LONG_DOUBLE_DENORM_REP {1, 0, 0, 0, 0, 0} + +union _ieee_rep +{ + unsigned short rep[6]; + float float_val; + double double_val; + long double ldouble_val; +}; + +#endif /* _FP_CONSTS_H */ + diff --git a/libc/mingw/math/fp_constsf.c b/libc/mingw/math/fp_constsf.c new file mode 100644 index 000000000..97306dcb1 --- /dev/null +++ b/libc/mingw/math/fp_constsf.c @@ -0,0 +1,22 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "fp_consts.h" + +const union _ieee_rep __QNANF = { __FLOAT_QNAN_REP }; +const union _ieee_rep __SNANF = { __FLOAT_SNAN_REP }; +const union _ieee_rep __INFF = { __FLOAT_INF_REP }; +const union _ieee_rep __DENORMF = { __FLOAT_DENORM_REP }; + +/* ISO C99 */ +#undef nanf +/* FIXME */ +float nanf(const char *); + +float nanf(const char * tagp __attribute__((unused)) ) +{ + return __QNANF.float_val; +} + diff --git a/libc/mingw/math/fp_constsl.c b/libc/mingw/math/fp_constsl.c new file mode 100644 index 000000000..c9855df8a --- /dev/null +++ b/libc/mingw/math/fp_constsl.c @@ -0,0 +1,20 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "fp_consts.h" + +const union _ieee_rep __QNANL = { __LONG_DOUBLE_QNAN_REP }; +const union _ieee_rep __SNANL = { __LONG_DOUBLE_SNAN_REP }; +const union _ieee_rep __INFL = { __LONG_DOUBLE_INF_REP }; +const union _ieee_rep __DENORML = { __LONG_DOUBLE_DENORM_REP }; + +#undef nanl +/* FIXME */ +long double nanl (const char *); +long double nanl (const char * tagp __attribute__((unused)) ) +{ + return __QNANL.ldouble_val; +} + diff --git a/libc/mingw/math/fpclassify.c b/libc/mingw/math/fpclassify.c new file mode 100644 index 000000000..f7303ec78 --- /dev/null +++ b/libc/mingw/math/fpclassify.c @@ -0,0 +1,34 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +/* 'fxam' sets FPU flags C3,C2,C0 'fstsw' stores: + FP_NAN 001 0x0100 + FP_NORMAL 010 0x0400 + FP_INFINITE 011 0x0500 + FP_ZERO 100 0x4000 + FP_SUBNORMAL 110 0x4400 + +and sets C1 flag (signbit) if neg */ + +int __fpclassify (double _x) +{ + __mingw_dbl_type_t hlp; + unsigned int l, h; + + hlp.x = _x; + h = hlp.lh.high; + l = hlp.lh.low | (h & 0xfffff); + h &= 0x7ff00000; + if ((h | l) == 0) + return FP_ZERO; + if (!h) + return FP_SUBNORMAL; + if (h == 0x7ff00000) + return (l ? FP_NAN : FP_INFINITE); + return FP_NORMAL; +} diff --git a/libc/mingw/math/fpclassifyf.c b/libc/mingw/math/fpclassifyf.c new file mode 100644 index 000000000..1fbbfa56d --- /dev/null +++ b/libc/mingw/math/fpclassifyf.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +int __fpclassifyf (float _x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + __mingw_flt_type_t hlp; + + hlp.x = _x; + hlp.val &= 0x7fffffff; + if (hlp.val == 0) + return FP_ZERO; + if (hlp.val < 0x800000) + return FP_SUBNORMAL; + if (hlp.val >= 0x7f800000) + return (hlp.val > 0x7f800000 ? FP_NAN : FP_INFINITE); + return FP_NORMAL; +#elif defined(__i386__) || defined(_X86_) + unsigned short sw; + __asm__ __volatile__ ( + "fxam; fstsw %%ax;" + : "=a" (sw) + : "t" (_x) + ); + return sw & (FP_NAN | FP_NORMAL | FP_ZERO); +#endif +} diff --git a/libc/mingw/math/fpclassifyl.c b/libc/mingw/math/fpclassifyl.c new file mode 100644 index 000000000..a7b0c553f --- /dev/null +++ b/libc/mingw/math/fpclassifyl.c @@ -0,0 +1,37 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ +#define __CRT__NO_INLINE +#include + +int __fpclassifyl (long double _x){ +#if defined(__x86_64__) || defined(_AMD64_) + __mingw_fp_types_t hlp; + unsigned int e; + hlp.ld = &_x; + e = hlp.ldt->lh.sign_exponent & 0x7fff; + if (!e) + { + unsigned int h = hlp.ldt->lh.high; + if (!(hlp.ldt->lh.low | h)) + return FP_ZERO; + else if (!(h & 0x80000000)) + return FP_SUBNORMAL; + } + else if (e == 0x7fff) + return (((hlp.ldt->lh.high & 0x7fffffff) | hlp.ldt->lh.low) == 0 ? + FP_INFINITE : FP_NAN); + return FP_NORMAL; +#elif defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + return __fpclassify(_x); +#elif defined(__i386__) || defined(_X86_) + unsigned short sw; + __asm__ __volatile__ ( + "fxam; fstsw %%ax;" + : "=a" (sw) + : "t" (_x) + ); + return sw & (FP_NAN | FP_NORMAL | FP_ZERO ); +#endif +} diff --git a/libc/mingw/math/frexpf.c b/libc/mingw/math/frexpf.c new file mode 100644 index 000000000..d4b7ab36c --- /dev/null +++ b/libc/mingw/math/frexpf.c @@ -0,0 +1,13 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +extern double __cdecl frexp(double _X,int *_Y); + +float frexpf (float, int *); +float frexpf (float x, int *expn) +{ + return (float)frexp(x, expn); +} + diff --git a/libc/mingw/math/hypot.c b/libc/mingw/math/hypot.c new file mode 100644 index 000000000..a63c27a68 --- /dev/null +++ b/libc/mingw/math/hypot.c @@ -0,0 +1,23 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ +#define _NEW_COMPLEX_DOUBLE 1 + +#include "../complex/complex_internal.h" +#include +#include + +double hypot (double x, double y) +{ + int x_class = fpclassify (x); + int y_class = fpclassify (y); + + if (x_class == FP_INFINITE || y_class == FP_INFINITE) + return __FLT_HUGE_VAL; + else if (x_class == FP_NAN || y_class == FP_NAN) + return __FLT_NAN; + + return _hypot (x, y); +} + diff --git a/libc/mingw/math/hypotf.c b/libc/mingw/math/hypotf.c new file mode 100644 index 000000000..5cd1a2792 --- /dev/null +++ b/libc/mingw/math/hypotf.c @@ -0,0 +1,23 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ +#define _NEW_COMPLEX_FLOAT 1 + +#include "../complex/complex_internal.h" +#include +#include + +float hypotf (float x, float y) +{ + int x_class = fpclassify (x); + int y_class = fpclassify (y); + + if (x_class == FP_INFINITE || y_class == FP_INFINITE) + return __FLT_HUGE_VAL; + else if (x_class == FP_NAN || y_class == FP_NAN) + return __FLT_NAN; + + return (float) _hypot (x, y); +} + diff --git a/libc/mingw/math/hypotl.c b/libc/mingw/math/hypotl.c new file mode 100644 index 000000000..9696f2b16 --- /dev/null +++ b/libc/mingw/math/hypotl.c @@ -0,0 +1,83 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +/* +This implementation is based largely on Cephes library +function cabsl (cmplxl.c), which bears the following notice: + +Cephes Math Library Release 2.1: January, 1989 +Copyright 1984, 1987, 1989 by Stephen L. Moshier +Direct inquiries to 30 Frost Street, Cambridge, MA 02140 +*/ + +/* + Modified for use in libmingwex.a + 02 Sept 2002 Danny Smith + Calls to ldexpl replaced by logbl and calls to frexpl replaced + by scalbnl to avoid duplicated range checks. +*/ + +extern long double __INFL; +#define PRECL 32 + +long double +hypotl (long double x, long double y) +{ + int exx; + int eyy; + int scale; + long double xx =fabsl(x); + long double yy =fabsl(y); + if (!isfinite(xx) || !isfinite(yy)) + { + /* Annex F.9.4.3, hypot returns +infinity if + either component is an infinity, even when the + other compoent is NaN. */ + return (isinf(xx) || isinf(yy)) ? INFINITY : NAN; + } + + if (xx == 0.0L) + return yy; + if (yy == 0.0L) + return xx; + + /* Get exponents */ + exx = logbl (xx); + eyy = logbl (yy); + + /* Check if large differences in scale */ + scale = exx - eyy; + if ( scale > PRECL) + return xx; + if ( scale < -PRECL) + return yy; + + /* Exponent of approximate geometric mean (x 2) */ + scale = (exx + eyy) >> 1; + + /* Rescale: Geometric mean is now about 2 */ + x = scalbnl(xx, -scale); + y = scalbnl(yy, -scale); + + xx = sqrtl(x * x + y * y); + + /* Check for overflow and underflow */ + exx = logbl(xx); + exx += scale; + if (exx > LDBL_MAX_EXP) + { + errno = ERANGE; + return __INFL; + } + if (exx < LDBL_MIN_EXP) + return 0.0L; + + /* Undo scaling */ + return (scalbnl (xx, scale)); +} diff --git a/libc/mingw/math/isnan.c b/libc/mingw/math/isnan.c new file mode 100644 index 000000000..57423c293 --- /dev/null +++ b/libc/mingw/math/isnan.c @@ -0,0 +1,31 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +int +__isnan (double _x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + __mingw_dbl_type_t hlp; + int l, h; + + hlp.x = _x; + l = hlp.lh.low; + h = hlp.lh.high & 0x7fffffff; + h |= (unsigned int) (l | -l) >> 31; + h = 0x7ff00000 - h; + return (int) ((unsigned int) h) >> 31; +#elif defined(__i386__) || defined(_X86_) + unsigned short _sw; + __asm__ __volatile__ ("fxam;" + "fstsw %%ax": "=a" (_sw) : "t" (_x)); + return (_sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) + == FP_NAN; +#endif +} + +#undef isnan +int __attribute__ ((alias ("__isnan"))) isnan (double); diff --git a/libc/mingw/math/isnanf.c b/libc/mingw/math/isnanf.c new file mode 100644 index 000000000..0c8e5041e --- /dev/null +++ b/libc/mingw/math/isnanf.c @@ -0,0 +1,27 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +int +__isnanf (float _x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + __mingw_flt_type_t hlp; + int i; + + hlp.x = _x; + i = hlp.val & 0x7fffffff; + i = 0x7f800000 - i; + return (int) (((unsigned int) i) >> 31); +#elif defined(__i386__) || defined(_X86_) + unsigned short _sw; + __asm__ __volatile__ ("fxam;" + "fstsw %%ax": "=a" (_sw) : "t" (_x) ); + return (_sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) + == FP_NAN; +#endif +} + +int __attribute__ ((alias ("__isnanf"))) isnanf (float); diff --git a/libc/mingw/math/isnanl.c b/libc/mingw/math/isnanl.c new file mode 100644 index 000000000..5eb31d90f --- /dev/null +++ b/libc/mingw/math/isnanl.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +int +__isnanl (long double _x) +{ +#if defined(__x86_64__) || defined(_AMD64_) + __mingw_fp_types_t ld; + int xx, signexp; + + ld.ld = &_x; + signexp = (ld.ldt->lh.sign_exponent & 0x7fff) << 1; + xx = (int) (ld.ldt->lh.low | (ld.ldt->lh.high & 0x7fffffffu)); /* explicit */ + signexp |= (unsigned int) (xx | (-xx)) >> 31; + signexp = 0xfffe - signexp; + return (int) ((unsigned int) signexp) >> 16; +#elif defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + return __isnan(_x); +#elif defined(__i386__) || defined(_X86_) + unsigned short _sw; + __asm__ __volatile__ ("fxam;" + "fstsw %%ax": "=a" (_sw) : "t" (_x)); + return (_sw & (FP_NAN | FP_NORMAL | FP_INFINITE | FP_ZERO | FP_SUBNORMAL)) + == FP_NAN; +#endif +} + +int __attribute__ ((alias ("__isnanl"))) isnanl (long double); diff --git a/libc/mingw/math/ldexpf.c b/libc/mingw/math/ldexpf.c new file mode 100644 index 000000000..83cd89d41 --- /dev/null +++ b/libc/mingw/math/ldexpf.c @@ -0,0 +1,13 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +extern double __cdecl ldexp(double _X,int _Y); + +float ldexpf (float x, int expn); +float ldexpf (float x, int expn) +{ + return (float) ldexp (x, expn); +} + diff --git a/libc/mingw/math/lgamma.c b/libc/mingw/math/lgamma.c new file mode 100644 index 000000000..29f544b78 --- /dev/null +++ b/libc/mingw/math/lgamma.c @@ -0,0 +1,276 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" + +/* A[]: Stirling's formula expansion of log gamma + * B[], C[]: log gamma function between 2 and 3 + */ +#ifdef UNK +static uD A[] = { + { { 8.11614167470508450300E-4 } }, + { { -5.95061904284301438324E-4 } }, + { { 7.93650340457716943945E-4 } }, + { { -2.77777777730099687205E-3 } }, + { { 8.33333333333331927722E-2 } } +}; +static uD B[] = { + { { -1.37825152569120859100E3 } }, + { { -3.88016315134637840924E4 } }, + { { -3.31612992738871184744E5 } }, + { { -1.16237097492762307383E6 } }, + { { -1.72173700820839662146E6 } }, + { { -8.53555664245765465627E5 } } +}; +static uD C[] = { + { { -3.51815701436523470549E2 } }, + { { -1.70642106651881159223E4 } }, + { { -2.20528590553854454839E5 } }, + { { -1.13933444367982507207E6 } }, + { { -2.53252307177582951285E6 } }, + { { -2.01889141433532773231E6 } } +}; +/* log( sqrt( 2*pi ) ) */ +static double LS2PI = 0.91893853320467274178; +#define MAXLGM 2.556348e305 +static double LOGPI = 1.14472988584940017414; +#endif + +#ifdef DEC +static const uD A[] = { + { { 0035524,0141201,0034633,0031405 } }, + { { 0135433,0176755,0126007,0045030 } }, + { { 0035520,0006371,0003342,0172730 } }, + { { 0136066,0005540,0132605,0026407 } }, + { { 0037252,0125252,0125252,0125132 } } +}; +static const uD B[] = { + { { 0142654,0044014,0077633,0035410 } }, + { { 0144027,0110641,0125335,0144760 } }, + { { 0144641,0165637,0142204,0047447 } }, + { { 0145215,0162027,0146246,0155211 } }, + { { 0145322,0026110,0010317,0110130 } }, + { { 0145120,0061472,0120300,0025363 } } +}; +static const uD C[] = { + { { 0142257,0164150,0163630,0112622 } }, + { { 0143605,0050153,0156116,0135272 } }, + { { 0144527,0056045,0145642,0062332 } }, + { { 0145213,0012063,0106250,0001025 } }, + { { 0145432,0111254,0044577,0115142 } }, + { { 0145366,0071133,0050217,0005122 } } +}; +/* log( sqrt( 2*pi ) ) */ +static const uD LS2P[] = { {040153,037616,041445,0172645,} }; +#define LS2PI LS2P[0].d +#define MAXLGM 2.035093e36 +static const uD LPI[] = { { 0040222,0103202,0043475,0006750, } }; +#define LOGPI LPI[0].d + +#endif + +#ifdef IBMPC +static const uD A[] = { + { { 0x6661,0x2733,0x9850,0x3f4a } }, + { { 0xe943,0xb580,0x7fbd,0xbf43 } }, + { { 0x5ebb,0x20dc,0x019f,0x3f4a } }, + { { 0xa5a1,0x16b0,0xc16c,0xbf66 } }, + { { 0x554b,0x5555,0x5555,0x3fb5 } } +}; +static const uD B[] = { + { { 0x6761,0x8ff3,0x8901,0xc095 } }, + { { 0xb93e,0x355b,0xf234,0xc0e2 } }, + { { 0x89e5,0xf890,0x3d73,0xc114 } }, + { { 0xdb51,0xf994,0xbc82,0xc131 } }, + { { 0xf20b,0x0219,0x4589,0xc13a } }, + { { 0x055e,0x5418,0x0c67,0xc12a } } +}; +static const uD C[] = { + { { 0x12b2,0x1cf3,0xfd0d,0xc075 } }, + { { 0xd757,0x7b89,0xaa0d,0xc0d0 } }, + { { 0x4c9b,0xb974,0xeb84,0xc10a } }, + { { 0x0043,0x7195,0x6286,0xc131 } }, + { { 0xf34c,0x892f,0x5255,0xc143 } }, + { { 0xe14a,0x6a11,0xce4b,0xc13e } } +}; +/* log( sqrt( 2*pi ) ) */ +static const union +{ + unsigned short s[4]; + double d; +} ls2p = {{0xbeb5,0xc864,0x67f1,0x3fed}}; +#define LS2PI (ls2p.d) +#define MAXLGM 2.556348e305 +/* log (pi) */ +static const union +{ + unsigned short s[4]; + double d; +} lpi = {{0xa1bd,0x48e7,0x50d0,0x3ff2}}; +#define LOGPI (lpi.d) +#endif + +#ifdef MIEEE +static const uD A[] = { + { { 0x3f4a,0x9850,0x2733,0x6661 } }, + { { 0xbf43,0x7fbd,0xb580,0xe943 } }, + { { 0x3f4a,0x019f,0x20dc,0x5ebb } }, + { { 0xbf66,0xc16c,0x16b0,0xa5a1 } }, + { { 0x3fb5,0x5555,0x5555,0x554b } } +}; +static const uD B[] = { + { { 0xc095,0x8901,0x8ff3,0x6761 } }, + { { 0xc0e2,0xf234,0x355b,0xb93e } }, + { { 0xc114,0x3d73,0xf890,0x89e5 } }, + { { 0xc131,0xbc82,0xf994,0xdb51 } }, + { { 0xc13a,0x4589,0x0219,0xf20b } }, + { { 0xc12a,0x0c67,0x5418,0x055e } } +}; +static const uD C[] = { + { { 0xc075,0xfd0d,0x1cf3,0x12b2 } }, + { { 0xc0d0,0xaa0d,0x7b89,0xd757 } }, + { { 0xc10a,0xeb84,0xb974,0x4c9b } }, + { { 0xc131,0x6286,0x7195,0x0043 } }, + { { 0xc143,0x5255,0x892f,0xf34c } }, + { { 0xc13e,0xce4b,0x6a11,0xe14a } } +}; +/* log( sqrt( 2*pi ) ) */ +static const union +{ + unsigned short s[4]; + double d; +} ls2p = {{0x3fed,0x67f1,0xc864,0xbeb5}}; +#define LS2PI ls2p.d +#define MAXLGM 2.556348e305 +/* log (pi) */ +static const union +{ + unsigned short s[4]; + double d; +} lpi = {{0x3ff2, 0x50d0, 0x48e7, 0xa1bd}}; +#define LOGPI (lpi.d) +#endif + + +/* Logarithm of gamma function */ +/* Reentrant version */ +double __lgamma_r(double x, int* sgngam); + +double __lgamma_r(double x, int* sgngam) +{ + double p, q, u, w, z; + int i; + + *sgngam = 1; +#ifdef NANS + if (isnan(x)) + return (x); +#endif + +#ifdef INFINITIES + if (!isfinite(x)) + return (INFINITY); +#endif + + if (x < -34.0) + { + q = -x; + w = __lgamma_r(q, sgngam); /* note this modifies sgngam! */ + p = floor(q); + if (p == q) + { +lgsing: + _SET_ERRNO(EDOM); + mtherr( "lgam", SING ); +#ifdef INFINITIES + return (INFINITY); +#else + return (MAXNUM); +#endif + } + i = p; + if ((i & 1) == 0) + *sgngam = -1; + else + *sgngam = 1; + z = q - p; + if (z > 0.5) + { + p += 1.0; + z = p - q; + } + z = q * sin( PI * z ); + if (z == 0.0) + goto lgsing; + /* z = log(PI) - log( z ) - w;*/ + z = LOGPI - log( z ) - w; + return (z); + } + + if (x < 13.0) + { + z = 1.0; + p = 0.0; + u = x; + while (u >= 3.0) + { + p -= 1.0; + u = x + p; + z *= u; + } + while (u < 2.0) + { + if (u == 0.0) + goto lgsing; + z /= u; + p += 1.0; + u = x + p; + } + if (z < 0.0) + { + *sgngam = -1; + z = -z; + } + else + *sgngam = 1; + if (u == 2.0) + return ( log(z) ); + p -= 2.0; + x = x + p; + p = x * polevl(x, B, 5) / p1evl(x, C, 6); + return ( log(z) + p ); + } + + if (x > MAXLGM) + { + _SET_ERRNO(ERANGE); + mtherr("lgamma", OVERFLOW); +#ifdef INFINITIES + return (*sgngam * INFINITY); +#else + return (*sgngam * MAXNUM); +#endif + } + + q = (x - 0.5) * log(x) - x + LS2PI; + if (x > 1.0e8) + return (q); + + p = 1.0/(x*x); + if (x >= 1000.0) + q += (( 7.9365079365079365079365e-4 * p + - 2.7777777777777777777778e-3) *p + + 0.0833333333333333333333) / x; + else + q += polevl( p, A, 4 ) / x; + return (q); +} + +/* This is the C99 version */ +double lgamma(double x) +{ + return (__lgamma_r(x, &signgam)); +} + diff --git a/libc/mingw/math/lgammaf.c b/libc/mingw/math/lgammaf.c new file mode 100644 index 000000000..8c527dffc --- /dev/null +++ b/libc/mingw/math/lgammaf.c @@ -0,0 +1,187 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* log gamma(x+2), -.5 < x < .5 */ +static const float B[] = { + 6.055172732649237E-004, + -1.311620815545743E-003, + 2.863437556468661E-003, + -7.366775108654962E-003, + 2.058355474821512E-002, + -6.735323259371034E-002, + 3.224669577325661E-001, + 4.227843421859038E-001 +}; + +/* log gamma(x+1), -.25 < x < .25 */ +static const float C[] = { + 1.369488127325832E-001, + -1.590086327657347E-001, + 1.692415923504637E-001, + -2.067882815621965E-001, + 2.705806208275915E-001, + -4.006931650563372E-001, + 8.224670749082976E-001, + -5.772156501719101E-001 +}; + +/* log( sqrt( 2*pi ) ) */ +static const float LS2PI = 0.91893853320467274178; +#define MAXLGM 2.035093e36 +static const float PIINV = 0.318309886183790671538; + +#include "cephes_mconf.h" + +/* Reentrant version */ +/* Logarithm of gamma function */ +float __lgammaf_r(float x, int* sgngamf); + +float __lgammaf_r(float x, int* sgngamf) +{ + float p, q, w, z; + float nx, tx; + int i, direction; + + *sgngamf = 1; +#ifdef NANS + if (isnan(x)) + return (x); +#endif + +#ifdef INFINITIES + if (!isfinite(x)) + return (x); +#endif + + if (x < 0.0) + { + q = -x; + w = __lgammaf_r(q, sgngamf); /* note this modifies sgngam! */ + p = floorf(q); + if (p == q) + { +lgsing: + _SET_ERRNO(EDOM); + mtherr("lgamf", SING); +#ifdef INFINITIES + return (INFINITYF); +#else + return( *sgngamf * MAXNUMF ); +#endif + } + i = p; + if ((i & 1) == 0) + *sgngamf = -1; + else + *sgngamf = 1; + z = q - p; + if (z > 0.5) + { + p += 1.0; + z = p - q; + } + z = q * sinf(PIF * z); + if (z == 0.0) + goto lgsing; + z = -logf(PIINV * z) - w; + return (z); + } + + if (x < 6.5) + { + direction = 0; + z = 1.0; + tx = x; + nx = 0.0; + if (x >= 1.5) + { + while (tx > 2.5) + { + nx -= 1.0; + tx = x + nx; + z *=tx; + } + x += nx - 2.0; +iv1r5: + p = x * polevlf( x, B, 7 ); + goto cont; + } + if (x >= 1.25) + { + z *= x; + x -= 1.0; /* x + 1 - 2 */ + direction = 1; + goto iv1r5; + } + if (x >= 0.75) + { + x -= 1.0; + p = x * polevlf( x, C, 7 ); + q = 0.0; + goto contz; + } + while (tx < 1.5) + { + if (tx == 0.0) + goto lgsing; + z *=tx; + nx += 1.0; + tx = x + nx; + } + direction = 1; + x += nx - 2.0; + p = x * polevlf(x, B, 7); + +cont: + if (z < 0.0) + { + *sgngamf = -1; + z = -z; + } + else + { + *sgngamf = 1; + } + q = logf(z); + if (direction) + q = -q; +contz: + return( p + q ); + } + + if (x > MAXLGM) + { + _SET_ERRNO(ERANGE); + mtherr("lgamf", OVERFLOW); +#ifdef INFINITIES + return (*sgngamf * INFINITYF); +#else + return (*sgngamf * MAXNUMF); +#endif + + } + +/* Note, though an asymptotic formula could be used for x >= 3, + * there is cancellation error in the following if x < 6.5. */ + q = LS2PI - x; + q += (x - 0.5) * logf(x); + + if (x <= 1.0e4) + { + z = 1.0/x; + p = z * z; + q += (( 6.789774945028216E-004 * p + - 2.769887652139868E-003 ) * p + + 8.333316229807355E-002 ) * z; + } + return (q); +} + +/* This is the C99 version */ +float lgammaf(float x) +{ + return (__lgammaf_r(x, &signgam)); +} + diff --git a/libc/mingw/math/lgammal.c b/libc/mingw/math/lgammal.c new file mode 100644 index 000000000..edb9a7ebf --- /dev/null +++ b/libc/mingw/math/lgammal.c @@ -0,0 +1,337 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" + +#if UNK +static uLD S[9] = { + { { -1.193945051381510095614E-3L } }, + { { 7.220599478036909672331E-3L } }, + { { -9.622023360406271645744E-3L } }, + { { -4.219773360705915470089E-2L } }, + { { 1.665386113720805206758E-1L } }, + { { -4.200263503403344054473E-2L } }, + { { -6.558780715202540684668E-1L } }, + { { 5.772156649015328608253E-1L } }, + { { 1.000000000000000000000E0L } } +}; +#endif +#if IBMPC +static const uLD S[] = { + { { 0xbaeb,0xd6d3,0x25e5,0x9c7e,0xbff5, 0, 0, 0 } }, + { { 0xfe9a,0xceb4,0xc74e,0xec9a,0x3ff7, 0, 0, 0 } }, + { { 0x9225,0xdfef,0xb0e9,0x9da5,0xbff8, 0, 0, 0 } }, + { { 0x10b0,0xec17,0x87dc,0xacd7,0xbffa, 0, 0, 0 } }, + { { 0x6b8d,0x7515,0x1905,0xaa89,0x3ffc, 0, 0, 0 } }, + { { 0xf183,0x126b,0xf47d,0xac0a,0xbffa, 0, 0, 0 } }, + { { 0x7bf6,0x57d1,0xa013,0xa7e7,0xbffe, 0, 0, 0 } }, + { { 0xc7a9,0x7db0,0x67e3,0x93c4,0x3ffe, 0, 0, 0 } }, + { { 0x0000,0x0000,0x0000,0x8000,0x3fff, 0, 0, 0 } } +}; +#endif +#if MIEEE +static uLD S[27] = { + { { 0xbff50000,0x9c7e25e5,0xd6d3baeb, 0 } }, + { { 0x3ff70000,0xec9ac74e,0xceb4fe9a, 0 } }, + { { 0xbff80000,0x9da5b0e9,0xdfef9225, 0 } }, + { { 0xbffa0000,0xacd787dc,0xec1710b0, 0 } }, + { { 0x3ffc0000,0xaa891905,0x75156b8d, 0 } }, + { { 0xbffa0000,0xac0af47d,0x126bf183, 0 } }, + { { 0xbffe0000,0xa7e7a013,0x57d17bf6, 0 } }, + { { 0x3ffe0000,0x93c467e3,0x7db0c7a9, 0 } }, + { { 0x3fff0000,0x80000000,0x00000000, 0 } } +}; +#endif + +#if UNK +static uLD SN[9] = { + { { 1.133374167243894382010E-3L } }, + { { 7.220837261893170325704E-3L } }, + { { 9.621911155035976733706E-3L } }, + { { -4.219773343731191721664E-2L } }, + { { -1.665386113944413519335E-1L } }, + { { -4.200263503402112910504E-2L } }, + { { 6.558780715202536547116E-1L } }, + { { 5.772156649015328608727E-1L } }, + { { -1.000000000000000000000E0L } } +}; +#endif +#if IBMPC +static const uLD SN[] = { + { { 0x5dd1,0x02de,0xb9f7,0x948d,0x3ff5, 0, 0, 0 } }, + { { 0x989b,0xdd68,0xc5f1,0xec9c,0x3ff7, 0, 0, 0 } }, + { { 0x2ca1,0x18f0,0x386f,0x9da5,0x3ff8, 0, 0, 0 } }, + { { 0x783f,0x41dd,0x87d1,0xacd7,0xbffa, 0, 0, 0 } }, + { { 0x7a5b,0xd76d,0x1905,0xaa89,0xbffc, 0, 0, 0 } }, + { { 0x7f64,0x1234,0xf47d,0xac0a,0xbffa, 0, 0, 0 } }, + { { 0x5e26,0x57d1,0xa013,0xa7e7,0x3ffe, 0, 0, 0 } }, + { { 0xc7aa,0x7db0,0x67e3,0x93c4,0x3ffe, 0, 0, 0 } }, + { { 0x0000,0x0000,0x0000,0x8000,0xbfff, 0, 0, 0 } } +}; +#endif +#if MIEEE +static uLD SN[] = { + { { 0x3ff50000,0x948db9f7,0x02de5dd1, 0 } }, + { { 0x3ff70000,0xec9cc5f1,0xdd68989b, 0 } }, + { { 0x3ff80000,0x9da5386f,0x18f02ca1, 0 } }, + { { 0xbffa0000,0xacd787d1,0x41dd783f, 0 } }, + { { 0xbffc0000,0xaa891905,0xd76d7a5b, 0 } }, + { { 0xbffa0000,0xac0af47d,0x12347f64, 0 } }, + { { 0x3ffe0000,0xa7e7a013,0x57d15e26, 0 } }, + { { 0x3ffe0000,0x93c467e3,0x7db0c7aa, 0 } }, + { { 0xbfff0000,0x80000000,0x00000000, 0 } } +}; +#endif + + +/* A[]: Stirling's formula expansion of log gamma + * B[], C[]: log gamma function between 2 and 3 + */ + + +/* log gamma(x) = ( x - 0.5 ) * log(x) - x + LS2PI + 1/x A(1/x^2) + * x >= 8 + * Peak relative error 1.51e-21 + * Relative spread of error peaks 5.67e-21 + */ +#if UNK +static uLD A[7] = { + { { 4.885026142432270781165E-3L } }, + { { -1.880801938119376907179E-3L } }, + { { 8.412723297322498080632E-4L } }, + { { -5.952345851765688514613E-4L } }, + { { 7.936507795855070755671E-4L } }, + { { -2.777777777750349603440E-3L } }, + { { 8.333333333333331447505E-2L } } +}; +#endif +#if IBMPC +static const uLD A[] = { + { { 0xd984,0xcc08,0x91c2,0xa012,0x3ff7, 0, 0, 0 } }, + { { 0x3d91,0x0304,0x3da1,0xf685,0xbff5, 0, 0, 0 } }, + { { 0x3bdc,0xaad1,0xd492,0xdc88,0x3ff4, 0, 0, 0 } }, + { { 0x8b20,0x9fce,0x844e,0x9c09,0xbff4, 0, 0, 0 } }, + { { 0xf8f2,0x30e5,0x0092,0xd00d,0x3ff4, 0, 0, 0 } }, + { { 0x4d88,0x03a8,0x60b6,0xb60b,0xbff6, 0, 0, 0 } }, + { { 0x9fcc,0xaaaa,0xaaaa,0xaaaa,0x3ffb, 0, 0, 0 } } +}; +#endif +#if MIEEE +static uLD A[] = { + { { 0x3ff70000,0xa01291c2,0xcc08d984, 0 } }, + { { 0xbff50000,0xf6853da1,0x03043d91, 0 } }, + { { 0x3ff40000,0xdc88d492,0xaad13bdc, 0 } }, + { { 0xbff40000,0x9c09844e,0x9fce8b20, 0 } }, + { { 0x3ff40000,0xd00d0092,0x30e5f8f2, 0 } }, + { { 0xbff60000,0xb60b60b6,0x03a84d88, 0 } }, + { { 0x3ffb0000,0xaaaaaaaa,0xaaaa9fcc, 0 } } +}; +#endif + +/* log gamma(x+2) = x B(x)/C(x) + * 0 <= x <= 1 + * Peak relative error 7.16e-22 + * Relative spread of error peaks 4.78e-20 + */ +#if UNK +static uLD B[7] = { + { { -2.163690827643812857640E3L } }, + { { -8.723871522843511459790E4L } }, + { { -1.104326814691464261197E6L } }, + { { -6.111225012005214299996E6L } }, + { { -1.625568062543700591014E7L } }, + { { -2.003937418103815175475E7L } }, + { { -8.875666783650703802159E6L } } +}; +static uLD C[7] = { + { { -5.139481484435370143617E2L } }, + { { -3.403570840534304670537E4L } }, + { { -6.227441164066219501697E5L } }, + { { -4.814940379411882186630E6L } }, + { { -1.785433287045078156959E7L } }, + { { -3.138646407656182662088E7L } }, + { { -2.099336717757895876142E7L } } +}; +#endif +#if IBMPC +static const uLD B[] = { + { { 0x9557,0x4995,0x0da1,0x873b,0xc00a, 0, 0, 0 } }, + { { 0xfe44,0x9af8,0x5b8c,0xaa63,0xc00f, 0, 0, 0 } }, + { { 0x5aa8,0x7cf5,0x3684,0x86ce,0xc013, 0, 0, 0 } }, + { { 0x259a,0x258c,0xf206,0xba7f,0xc015, 0, 0, 0 } }, + { { 0xbe18,0x1ca3,0xc0a0,0xf80a,0xc016, 0, 0, 0 } }, + { { 0x168f,0x2c42,0x6717,0x98e3,0xc017, 0, 0, 0 } }, + { { 0x2051,0x9d55,0x92c8,0x876e,0xc016, 0, 0, 0 } } +}; +static const uLD C[] = { + { { 0xaa77,0xcf2f,0xae76,0x807c,0xc008, 0, 0, 0 } }, + { { 0xb280,0x0d74,0xb55a,0x84f3,0xc00e, 0, 0, 0 } }, + { { 0xa505,0xcd30,0x81dc,0x9809,0xc012, 0, 0, 0 } }, + { { 0x3369,0x4246,0xb8c2,0x92f0,0xc015, 0, 0, 0 } }, + { { 0x63cf,0x6aee,0xbe6f,0x8837,0xc017, 0, 0, 0 } }, + { { 0x26bb,0xccc7,0xb009,0xef75,0xc017, 0, 0, 0 } }, + { { 0x462b,0xbae8,0xab96,0xa02a,0xc017, 0, 0, 0 } } +}; +#endif +#if MIEEE +static uLD B[] = { + { { 0xc00a0000,0x873b0da1,0x49959557, 0 } }, + { { 0xc00f0000,0xaa635b8c,0x9af8fe44, 0 } }, + { { 0xc0130000,0x86ce3684,0x7cf55aa8, 0 } }, + { { 0xc0150000,0xba7ff206,0x258c259a, 0 } }, + { { 0xc0160000,0xf80ac0a0,0x1ca3be18, 0 } }, + { { 0xc0170000,0x98e36717,0x2c42168f, 0 } }, + { { 0xc0160000,0x876e92c8,0x9d552051, 0 } } +}; +static uLD C[] = { + { { 0xc0080000,0x807cae76,0xcf2faa77, 0 } }, + { { 0xc00e0000,0x84f3b55a,0x0d74b280, 0 } }, + { { 0xc0120000,0x980981dc,0xcd30a505, 0 } }, + { { 0xc0150000,0x92f0b8c2,0x42463369, 0 } }, + { { 0xc0170000,0x8837be6f,0x6aee63cf, 0 } }, + { { 0xc0170000,0xef75b009,0xccc726bb, 0 } }, + { { 0xc0170000,0xa02aab96,0xbae8462b, 0 } } +}; +#endif + +/* log( sqrt( 2*pi ) ) */ +static const long double LS2PI = 0.91893853320467274178L; +#if defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) +#define MAXLGM 2.035093e36 +#else +#define MAXLGM 1.04848146839019521116e+4928L +#endif /* defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) */ + +/* Logarithm of gamma function */ +/* Reentrant version */ +long double __lgammal_r(long double x, int* sgngaml); + +long double __lgammal_r(long double x, int* sgngaml) +{ + long double p, q, w, z, f, nx; + int i; + + *sgngaml = 1; +#ifdef NANS + if (isnanl(x)) + return(NANL); +#endif +#ifdef INFINITIES + if (!isfinitel(x)) + return (INFINITYL); +#endif + if (x < -34.0L) + { + q = -x; + w = __lgammal_r(q, sgngaml); /* note this modifies sgngam! */ + p = floorl(q); + if (p == q) + { +lgsing: + _SET_ERRNO(EDOM); + mtherr( "lgammal", SING ); +#ifdef INFINITIES + return (INFINITYL); +#else + return (MAXNUML); +#endif + } + i = p; + if ((i & 1) == 0) + *sgngaml = -1; + else + *sgngaml = 1; + z = q - p; + if (z > 0.5L) + { + p += 1.0L; + z = p - q; + } + z = q * sinl(PIL * z); + if (z == 0.0L) + goto lgsing; + /* z = LOGPI - logl( z ) - w; */ + z = logl(PIL/z) - w; + return (z); + } + + if (x < 13.0L) + { + z = 1.0L; + nx = floorl(x + 0.5L); + f = x - nx; + while (x >= 3.0L) + { + nx -= 1.0L; + x = nx + f; + z *= x; + } + while (x < 2.0L) + { + if (fabsl(x) <= 0.03125) + goto lsmall; + z /= nx + f; + nx += 1.0L; + x = nx + f; + } + if (z < 0.0L) + { + *sgngaml = -1; + z = -z; + } + else + *sgngaml = 1; + if (x == 2.0L) + return ( logl(z) ); + x = (nx - 2.0L) + f; + p = x * polevll(x, B, 6) / p1evll(x, C, 7); + return ( logl(z) + p ); + } + + if (x > MAXLGM) + { + _SET_ERRNO(ERANGE); + mtherr("lgammal", OVERFLOW); +#ifdef INFINITIES + return (*sgngaml * INFINITYL); +#else + return (*sgngaml * MAXNUML); +#endif + } + + q = (x - 0.5L) * logl(x) - x + LS2PI; + if (x > 1.0e10L) + return(q); + p = 1.0L/(x*x); + q += polevll(p, A, 6) / x; + return (q); + +lsmall: + if (x == 0.0L) + goto lgsing; + if (x < 0.0L) + { + x = -x; + q = z / (x * polevll(x, SN, 8)); + } + else + q = z / (x * polevll(x, S, 8)); + if (q < 0.0L) + { + *sgngaml = -1; + q = -q; + } + else + *sgngaml = 1; + q = logl(q); + return (q); +} + +/* This is the C99 version */ +long double lgammal(long double x) +{ + return (__lgammal_r (x, &signgam)); +} + diff --git a/libc/mingw/math/llrint.c b/libc/mingw/math/llrint.c new file mode 100644 index 000000000..8b138c07f --- /dev/null +++ b/libc/mingw/math/llrint.c @@ -0,0 +1,27 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +long long llrint (double x) +{ + long long retval = 0ll; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); +#else + int mode = fegetround(); + if (mode == FE_DOWNWARD) + retval = (long long)floor(x); + else if (mode == FE_UPWARD) + retval = (long long)ceil(x); + else if (mode == FE_TOWARDZERO) + retval = x >= 0 ? (long long)floor(x) : (long long)ceil(x); + else + retval = x >= 0 ? (long long)floor(x + 0.5) : (long long)ceil(x - 0.5); +#endif + return retval; +} + diff --git a/libc/mingw/math/llrintf.c b/libc/mingw/math/llrintf.c new file mode 100644 index 000000000..1b2a422ea --- /dev/null +++ b/libc/mingw/math/llrintf.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +long long llrintf (float x) +{ + long long retval = 0ll; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); +#else + int mode = fegetround(); + if (mode == FE_DOWNWARD) + retval = (long long)floorf(x); + else if (mode == FE_UPWARD) + retval = (long long)ceilf(x); + else if (mode == FE_TOWARDZERO) + retval = x >= 0 ? (long long)floorf(x) : (long long)ceilf(x); + else + retval = x >= 0 ? (long long)floorf(x + 0.5) : (long long)ceilf(x - 0.5); +#endif + return retval; +} diff --git a/libc/mingw/math/llrintl.c b/libc/mingw/math/llrintl.c new file mode 100644 index 000000000..ac06ab295 --- /dev/null +++ b/libc/mingw/math/llrintl.c @@ -0,0 +1,27 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +long long llrintl (long double x) +{ + long long retval = 0ll; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("fistpll %0" : "=m" (retval) : "t" (x) : "st"); +#else + int mode = fegetround(); + if (mode == FE_DOWNWARD) + retval = (long long)floor(x); + else if (mode == FE_UPWARD) + retval = (long long)ceil(x); + else if (mode == FE_TOWARDZERO) + retval = x >= 0 ? (long long)floor(x) : (long long)ceil(x); + else + retval = x >= 0 ? (long long)floor(x + 0.5) : (long long)ceil(x - 0.5); +#endif + return retval; +} + diff --git a/libc/mingw/math/llround.c b/libc/mingw/math/llround.c new file mode 100644 index 000000000..ef21bcb71 --- /dev/null +++ b/libc/mingw/math/llround.c @@ -0,0 +1,38 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +long long +llround (double x) +{ + double res; + + if (x >= 0.0) + { + res = ceil (x); + if (res - x > 0.5) + res -= 1.0; + } + else + { + res = ceil (-x); + if (res + x > 0.5) + res -= 1.0; + res = -res; + } + if (!isfinite (res) + || res > (double) LONG_LONG_MAX + || res < (double) LONG_LONG_MIN) + { + errno = ERANGE; + /* Undefined behaviour, so we could return anything. */ + /* return res > 0.0 ? LONG_LONG_MAX : LONG_LONG_MIN; */ + } + return (long long) res; +} + diff --git a/libc/mingw/math/llroundf.c b/libc/mingw/math/llroundf.c new file mode 100644 index 000000000..0a8da174f --- /dev/null +++ b/libc/mingw/math/llroundf.c @@ -0,0 +1,38 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +long long +llroundf (float x) +{ + float res; + + if (x >= 0.0F) + { + res = ceilf (x); + if (res - x > 0.5F) + res -= 1.0F; + } + else + { + res = ceilf (-x); + if (res + x > 0.5F) + res -= 1.0F; + res = -res; + } + if (!isfinite (res) + || res > (float) LONG_LONG_MAX + || res < (float) LONG_LONG_MIN) + { + errno = ERANGE; + /* Undefined behaviour, so we could return anything. */ + /* return res > 0.0F ? LONG_LONG_MAX : LONG_LONG_MIN; */ + } + return (long long) res; +} + diff --git a/libc/mingw/math/llroundl.c b/libc/mingw/math/llroundl.c new file mode 100644 index 000000000..cd75e51d8 --- /dev/null +++ b/libc/mingw/math/llroundl.c @@ -0,0 +1,38 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +long long +llroundl (long double x) +{ + long double res; + + if (x >= 0.0L) + { + res = ceill (x); + if (res - x > 0.5L) + res -= 1.0L; + } + else + { + res = ceill (-x); + if (res + x > 0.5L) + res -= 1.0L; + res = -res; + } + if (!isfinite (res) + || res > (double) LONG_LONG_MAX + || res < (double) LONG_LONG_MIN) + { + errno = ERANGE; + /* Undefined behaviour, so we could return anything. */ + /* return res > 0.0 ? LONG_LONG_MAX : LONG_LONG_MIN; */ + } + return (long long) res; +} + diff --git a/libc/mingw/math/log10f.c b/libc/mingw/math/log10f.c new file mode 100644 index 000000000..f793e0540 --- /dev/null +++ b/libc/mingw/math/log10f.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float log10f(float _X) +{ + return ((float)log10((double)_X)); +} diff --git a/libc/mingw/math/logf.c b/libc/mingw/math/logf.c new file mode 100644 index 000000000..b85b59256 --- /dev/null +++ b/libc/mingw/math/logf.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float logf(float _X) +{ + return ((float)log((double)_X)); +} diff --git a/libc/mingw/math/lrint.c b/libc/mingw/math/lrint.c new file mode 100644 index 000000000..ec80e4e55 --- /dev/null +++ b/libc/mingw/math/lrint.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long lrint (double x) +{ + long retval = 0L; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); +#elif defined(__arm__) || defined(_ARM_) + float temp; + __asm__ __volatile__ ( + "vcvtr.s32.f64 %[tmp], %[src]\n\t" + "fmrs %[dst], %[tmp]\n\t" + : [dst] "=r" (retval), [tmp] "=t" (temp) : [src] "w" (x)); +#elif defined(__aarch64__) || defined(_ARM64_) + __asm__ __volatile__ ( + "frintx %d1, %d1\n\t" + "fcvtzs %w0, %d1\n\t" + : "=r" (retval), "+w" (x)); +#endif + return retval; +} diff --git a/libc/mingw/math/lrintf.c b/libc/mingw/math/lrintf.c new file mode 100644 index 000000000..91fc5e12e --- /dev/null +++ b/libc/mingw/math/lrintf.c @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long lrintf (float x) +{ + long retval = 0l; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); +#elif defined(__arm__) || defined(_ARM_) + __asm__ __volatile__ ( + "vcvtr.s32.f32 %[src], %[src]\n\t" + "fmrs %[dst], %[src]\n\t" + : [dst] "=r" (retval), [src] "+w" (x)); +#elif defined(__aarch64__) || defined(_ARM64_) + __asm__ __volatile__ ( + "frintx %s1, %s1\n\t" + "fcvtzs %w0, %s1\n\t" + : "=r" (retval), "+w" (x)); +#endif + return retval; +} diff --git a/libc/mingw/math/lrintl.c b/libc/mingw/math/lrintl.c new file mode 100644 index 000000000..d710fac05 --- /dev/null +++ b/libc/mingw/math/lrintl.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long lrintl (long double x) +{ + long retval = 0l; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("fistpl %0" : "=m" (retval) : "t" (x) : "st"); +#elif defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + retval = lrint(x); +#endif + return retval; +} + diff --git a/libc/mingw/math/lround.c b/libc/mingw/math/lround.c new file mode 100644 index 000000000..560ef614f --- /dev/null +++ b/libc/mingw/math/lround.c @@ -0,0 +1,37 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +long +lround (double x) +{ + double res; + + if (x >= 0.0) + { + res = ceil (x); + if (res - x > 0.5) + res -= 1.0; + } + else + { + res = ceil (-x); + if (res + x > 0.5) + res -= 1.0; + res = -res; + } + if (!isfinite (res) + || res > (double) LONG_MAX + || res < (double) LONG_MIN) + { + errno = ERANGE; + /* Undefined behaviour, so we could return anything. */ + /* return res > 0.0 ? LONG_MAX : LONG_MIN; */ + } + return (long) res; +} diff --git a/libc/mingw/math/lroundf.c b/libc/mingw/math/lroundf.c new file mode 100644 index 000000000..04a9354f3 --- /dev/null +++ b/libc/mingw/math/lroundf.c @@ -0,0 +1,37 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +long +lroundf (float x) +{ + float res; + + if (x >= 0.0F) + { + res = ceilf (x); + if (res - x > 0.5F) + res -= 1.0F; + } + else + { + res = ceilf (-x); + if (res + x > 0.5F) + res -= 1.0F; + res = -res; + } + if (!isfinite (res) + || res > (float) LONG_MAX + || res < (float) LONG_MIN) + { + errno = ERANGE; + /* Undefined behaviour, so we could return anything. */ + /* return res > 0.0F ? LONG_MAX : LONG_MIN; */ + } + return (long) res; +} diff --git a/libc/mingw/math/lroundl.c b/libc/mingw/math/lroundl.c new file mode 100644 index 000000000..b4584a896 --- /dev/null +++ b/libc/mingw/math/lroundl.c @@ -0,0 +1,37 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +long +lroundl (long double x) +{ + long double res; + + if (x >= 0.0L) + { + res = ceill (x); + if (res - x > 0.5L) + res -= 1.0; + } + else + { + res = ceill (-x); + if (res + x > 0.5L) + res -= 1.0L; + res = -res; + } + if (!isfinite (res) + || res > (long double)LONG_MAX + || res < (long double)LONG_MIN) + { + errno = ERANGE; + /* Undefined behaviour, so we could return anything. */ + /* return res > 0.0L ? LONG_MAX : LONG_MIN; */ + } + return (long) res; +} diff --git a/libc/mingw/math/modf.c b/libc/mingw/math/modf.c new file mode 100644 index 000000000..d2623095c --- /dev/null +++ b/libc/mingw/math/modf.c @@ -0,0 +1,41 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +double +modf (double value, double* iptr) +{ + double int_part = 0.0; + /* truncate */ +#if defined(_AMD64_) || defined(__x86_64__) + asm volatile ("subq $8, %%rsp\n" + "fnstcw 4(%%rsp)\n" + "movzwl 4(%%rsp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%rsp)\n" + "fldcw (%%rsp)\n" + "frndint\n" + "fldcw 4(%%rsp)\n" + "addq $8, %%rsp\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */ +#elif defined(_X86_) || defined(__i386__) + asm volatile ("push %%eax\n\tsubl $8, %%esp\n" + "fnstcw 4(%%esp)\n" + "movzwl 4(%%esp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%esp)\n" + "fldcw (%%esp)\n" + "frndint\n" + "fldcw 4(%%esp)\n" + "addl $8, %%esp\n\tpop %%eax\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */ +#else + int_part = trunc(value); +#endif + if (iptr) + *iptr = int_part; + return (isinf (value) ? 0.0 : value - int_part); +} diff --git a/libc/mingw/math/modff.c b/libc/mingw/math/modff.c new file mode 100644 index 000000000..dcf19cfed --- /dev/null +++ b/libc/mingw/math/modff.c @@ -0,0 +1,42 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +float +modff (float value, float* iptr) +{ + float int_part = 0.0F; + /* truncate */ + /* truncate */ +#if defined(_AMD64_) || defined(__x86_64__) + asm volatile ("subq $8, %%rsp\n" + "fnstcw 4(%%rsp)\n" + "movzwl 4(%%rsp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%rsp)\n" + "fldcw (%%rsp)\n" + "frndint\n" + "fldcw 4(%%rsp)\n" + "addq $8, %%rsp\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */ +#elif defined(_X86_) || defined(__i386__) + asm volatile ("push %%eax\n\tsubl $8, %%esp\n" + "fnstcw 4(%%esp)\n" + "movzwl 4(%%esp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%esp)\n" + "fldcw (%%esp)\n" + "frndint\n" + "fldcw 4(%%esp)\n" + "addl $8, %%esp\n\tpop %%eax\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */ +#else + int_part = truncf(value); +#endif + if (iptr) + *iptr = int_part; + return (isinf (value) ? 0.0F : value - int_part); +} diff --git a/libc/mingw/math/modfl.c b/libc/mingw/math/modfl.c new file mode 100644 index 000000000..33593e6de --- /dev/null +++ b/libc/mingw/math/modfl.c @@ -0,0 +1,41 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include + +long double +modfl (long double value, long double* iptr) +{ + long double int_part = 0.0L; + /* truncate */ +#if defined(_AMD64_) || defined(__x86_64__) + asm volatile ("subq $8, %%rsp\n" + "fnstcw 4(%%rsp)\n" + "movzwl 4(%%rsp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%rsp)\n" + "fldcw (%%rsp)\n" + "frndint\n" + "fldcw 4(%%rsp)\n" + "addq $8, %%rsp\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */ +#elif defined(_X86_) || defined(__i386__) + asm volatile ("push %%eax\n\tsubl $8, %%esp\n" + "fnstcw 4(%%esp)\n" + "movzwl 4(%%esp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%esp)\n" + "fldcw (%%esp)\n" + "frndint\n" + "fldcw 4(%%esp)\n" + "addl $8, %%esp\n\tpop %%eax\n" : "=t" (int_part) : "0" (value) : "eax"); /* round */ +#else + int_part = truncl(value); +#endif + if (iptr) + *iptr = int_part; + return (isinf (value) ? 0.0L : value - int_part); +} diff --git a/libc/mingw/math/nextafterf.c b/libc/mingw/math/nextafterf.c new file mode 100644 index 000000000..143a35d0a --- /dev/null +++ b/libc/mingw/math/nextafterf.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float +nextafterf (float x, float y) +{ + union + { + float f; + unsigned int i; + } u; + if (isnan (y) || isnan (x)) + return x + y; + if (x == y ) + /* nextafter (0.0, -O.0) should return -0.0. */ + return y; + u.f = x; + if (x == 0.0F) + { + u.i = 1; + return y > 0.0F ? u.f : -u.f; + } + if (((x > 0.0F) ^ (y > x)) == 0) + u.i++; + else + u.i--; + return u.f; +} diff --git a/libc/mingw/math/nextafterl.c b/libc/mingw/math/nextafterl.c new file mode 100644 index 000000000..5db3af74a --- /dev/null +++ b/libc/mingw/math/nextafterl.c @@ -0,0 +1,71 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + nextafterl.c + Contributed by Danny Smith + No copyright claimed, absolutely no warranties. + + 2005-05-09 +*/ + +#include + +long double +nextafterl (long double x, long double y) +{ + union { + long double ld; + struct { + /* packed attribute is unnecessary on x86/x64 for these three variables */ + unsigned long long mantissa; + unsigned short expn; + unsigned short pad; + } parts; + } u; + + /* The normal bit is explicit for long doubles, unlike + float and double. */ + static const unsigned long long normal_bit = 0x8000000000000000ull; + u.ld = 0.0L; + if (isnan (y) || isnan (x)) + return x + y; + + if (x == y ) + /* nextafter (0.0, -O.0) should return -0.0. */ + return y; + + u.ld = x; + if (x == 0.0L) + { + u.parts.mantissa = 1ull; + return y > 0.0L ? u.ld : -u.ld; + } + + if (((x > 0.0L) ^ (y > x)) == 0) + { + u.parts.mantissa++; + if ((u.parts.mantissa & ~normal_bit) == 0ull) + u.parts.expn++; + } + else + { + if ((u.parts.mantissa & ~normal_bit) == 0ull) + u.parts.expn--; + u.parts.mantissa--; + } + + /* If we have updated the expn of a normal number, + or moved from denormal to normal, [re]set the normal bit. */ + if (u.parts.expn & 0x7fff) + u.parts.mantissa |= normal_bit; + + return u.ld; +} + +/* nexttowardl is the same function with a different name. */ +long double +nexttowardl (long double, long double) __attribute__ ((alias("nextafterl"))); + diff --git a/libc/mingw/math/nexttoward.c b/libc/mingw/math/nexttoward.c new file mode 100644 index 000000000..909f6ea2d --- /dev/null +++ b/libc/mingw/math/nexttoward.c @@ -0,0 +1,47 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + nexttoward.c + Contributed by Danny Smith + No copyright claimed, absolutely no warranties. + + 2005-05-10 +*/ + +#include + +double +nexttoward (double x, long double y) +{ + union + { + double d; + unsigned long long ll; + } u; + + long double xx = x; + + if (isnan (y) || isnan (x)) + return x + y; + + if (xx == y) + /* nextafter (0.0, -O.0) should return -0.0. */ + return y; + u.d = x; + if (x == 0.0) + { + u.ll = 1; + return y > 0.0L ? u.d : -u.d; + } + + /* Non-extended encodings are lexicographically ordered, + with implicit "normal" bit. */ + if (((x > 0.0) ^ (y > xx)) == 0) + u.ll++; + else + u.ll--; + return u.d; +} diff --git a/libc/mingw/math/nexttowardf.c b/libc/mingw/math/nexttowardf.c new file mode 100644 index 000000000..0a2f3bfb7 --- /dev/null +++ b/libc/mingw/math/nexttowardf.c @@ -0,0 +1,43 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + nexttowardf.c + Contributed by Danny Smith + No copyright claimed, absolutely no warranties. + + 2005-05-10 +*/ + +#include + +float +nexttowardf (float x, long double y) +{ + union + { + float f; + unsigned int i; + } u; + + long double xx = x; + + if (isnan (y) || isnan (x)) + return x + y; + if (xx == y ) + /* nextafter (0.0, -O.0) should return -0.0. */ + return y; + u.f = x; + if (x == 0.0F) + { + u.i = 1; + return y > 0.0L ? u.f : -u.f; + } + if (((x > 0.0F) ^ (y > xx)) == 0) + u.i++; + else + u.i--; + return u.f; +} diff --git a/libc/mingw/math/powf.c b/libc/mingw/math/powf.c new file mode 100644 index 000000000..48356277d --- /dev/null +++ b/libc/mingw/math/powf.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +float powf (float x, float y) +{ + return (float) pow ((double) x, (double) y); +} diff --git a/libc/mingw/math/powi.c b/libc/mingw/math/powi.c new file mode 100644 index 000000000..04f8b9595 --- /dev/null +++ b/libc/mingw/math/powi.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "powi.def.h" diff --git a/libc/mingw/math/powi.def.h b/libc/mingw/math/powi.def.h new file mode 100644 index 000000000..1997727fd --- /dev/null +++ b/libc/mingw/math/powi.def.h @@ -0,0 +1,153 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* IEEE 754 - Elementary Functions - Special Cases + * powi (x, +/-0) is 1 for any x (even a zero, quiet NaN, or infinity) + * powi (+1, y) is 1 for any y (even a quiet NaN) + * powi (+/-0, y) is +/-oo and signals the divideByZero exception for y an odd integer < 0 + * powi (+/-0, y) is +oo and signals the divideByZero exception for finite y < 0 and not an odd integer + * powi (+/-0, y) is +/-0 for finite y > 0 an odd integer + * powi (+/-0, y) is +0 for finite y > 0 and not an odd integer + powi (-inf, y) = +0 for y<0 and not an odd integer + powi (-inf, y) = -inf for y an odd integer > 0 + powi (-inf, y) = +inf for y>0 and not an odd integer + powi (+/-inf, y) is +/-0 with no exception for y an odd integer < 0 + powi (+/-inf, y) is +0 with no exception for finite y < 0 and not an odd integer + powi (+/-inf, y) is +/-inf with no exception for finite y > 0 an odd integer + powi (+/-inf, y) is +inf with no exception for finite y > 0 and not an odd integer + powi (x, y) signals the invalid operation exception for finite x < 0 and finite non-integer y. + + For x /= 0: lim y->oo (1/x)^y results as: for |x| < 1 that sgn(x)*0 and for |x| > 0 that sgn(x)*Infinity + +*/ +#include "../complex/complex_internal.h" +#include +#include +#include +#include +#include + +__FLT_TYPE __cdecl +__FLT_ABI(__powi) (__FLT_TYPE x, int y); + +__FLT_TYPE __cdecl +__FLT_ABI(__powi) (__FLT_TYPE x, int y) +{ + int x_class = fpclassify (x); + int odd_y = y & 1; + __FLT_TYPE d, rslt; + + if (y == 0 || x == __FLT_CST(1.0)) + return __FLT_CST(1.0); + else if (x_class == FP_NAN) + { + rslt = (signbit(x) ? -__FLT_NAN : __FLT_NAN); + __FLT_RPT_DOMAIN ("__powi", x, (__FLT_TYPE) y, rslt); + return rslt; + } + else if (x_class == FP_ZERO) + { + if (y >= 0) + { + if (!odd_y || !signbit (x)) + return __FLT_CST (0.0); + return -__FLT_CST(0.0); + } + + if (!odd_y || !signbit (x)) + return __FLT_HUGE_VAL; + return (signbit(x) ? -__FLT_HUGE_VAL : __FLT_HUGE_VAL); + } + else if (x_class == FP_INFINITE) + { + /* pow( -inf, y) = +0 for y<0 and not an odd integer, */ + if (signbit(x) && y < 0 && !odd_y) + return __FLT_CST(0.0); + /* pow( -inf, y) = -inf for y an odd integer > 0. */ + if (signbit(x) && y >= 0 && odd_y) + return -__FLT_HUGE_VAL; + /* pow( -inf, y) = +inf for y>0 and not an odd integer. */ + if (signbit(x) && y >= 0 && !odd_y) + return __FLT_HUGE_VAL; + /* pow (+/-inf, y) is +/-0 with no exception for y an odd integer < 0. */ + if (y < 0) + { + /* pow (+/-inf, y) is +0 with no exception for finite y < 0 and not an odd integer. */ + return (odd_y && signbit(x) ? -__FLT_CST(0.0) : __FLT_CST(0.0)); + } + /* pow (+/-inf, y) is +/-inf with no exception for finite y > 0 an odd integer. */ + /* pow (+/-inf, y) is +inf with no exception for finite y > 0 and not an odd integer. */ + return (odd_y && signbit(x) ? -__FLT_HUGE_VAL : __FLT_HUGE_VAL); + } + + d = __FLT_ABI(fabs) (x); + + if (y < 0) + { + d = __FLT_CST(1.0) / d; + y = -y; + } + + if (!y) + rslt = __FLT_CST(1.0); + else if (y == 1) + rslt = d; + else + { + unsigned int u = (unsigned int) y; + rslt = ((u & 1) != 0) ? d : __FLT_CST(1.0); + u >>= 1; + do + { + d *= d; + if ((u & 1) != 0) + rslt *= d; + u >>= 1; + } + while (u > 0); + } + if (signbit (x) && odd_y) + rslt = -rslt; + return rslt; +} diff --git a/libc/mingw/math/powif.c b/libc/mingw/math/powif.c new file mode 100644 index 000000000..46b85033a --- /dev/null +++ b/libc/mingw/math/powif.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_FLOAT 1 +#include "powi.def.h" diff --git a/libc/mingw/math/powil.c b/libc/mingw/math/powil.c new file mode 100644 index 000000000..d3e08e301 --- /dev/null +++ b/libc/mingw/math/powil.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "powi.def.h" diff --git a/libc/mingw/math/rint.c b/libc/mingw/math/rint.c new file mode 100644 index 000000000..d88331492 --- /dev/null +++ b/libc/mingw/math/rint.c @@ -0,0 +1,24 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +double rint (double x) { + double retval = 0.0; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (x)); +#elif defined(__arm__) || defined(_ARM_) + if (isnan(x) || isinf(x)) + return x; + float temp; + __asm__ __volatile__ ( + "vcvtr.s32.f64 %[tmp], %[src]\n\t" + "vcvt.f64.s32 %[dst], %[tmp]\n\t" + : [dst] "=w" (retval), [tmp] "=t" (temp) : [src] "w" (x)); +#elif defined(__aarch64__) || defined(_ARM64_) + __asm__ __volatile__ ("frintx %d0, %d1\n\t" : "=w" (retval) : "w" (x)); +#endif + return retval; +} diff --git a/libc/mingw/math/rintf.c b/libc/mingw/math/rintf.c new file mode 100644 index 000000000..bfae51516 --- /dev/null +++ b/libc/mingw/math/rintf.c @@ -0,0 +1,23 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float rintf (float x) { + float retval = 0.0F; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("frndint;": "=t" (retval) : "0" (x)); +#elif defined(__arm__) || defined(_ARM_) + if (isnan(x) || isinf(x)) + return x; + __asm__ __volatile__ ( + "vcvtr.s32.f32 %[dst], %[src]\n\t" + "vcvt.f32.s32 %[dst], %[dst]\n\t" + : [dst] "=t" (retval) : [src] "w" (x)); +#elif defined(__aarch64__) || defined(_ARM64_) + __asm__ __volatile__ ("frintx %s0, %s1\n\t" : "=w" (retval) : "w" (x)); +#endif + return retval; +} diff --git a/libc/mingw/math/rintl.c b/libc/mingw/math/rintl.c new file mode 100644 index 000000000..1c3780330 --- /dev/null +++ b/libc/mingw/math/rintl.c @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long double rintl (long double x) { + long double retval = 0.0L; +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + __asm__ __volatile__ ("frndint;": "=t" (retval) : "0" (x)); +#elif defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + retval = rint(x); +#endif + return retval; +} diff --git a/libc/mingw/math/round.c b/libc/mingw/math/round.c new file mode 100644 index 000000000..aecf1d84b --- /dev/null +++ b/libc/mingw/math/round.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +double +round (double x) +{ + double res; + if (x >= 0.0) + { + res = ceil (x); + if (res - x > 0.5) + res -= 1.0; + } + else + { + res = ceil (-x); + if (res + x > 0.5) + res -= 1.0; + res = -res; + } + return res; +} diff --git a/libc/mingw/math/roundf.c b/libc/mingw/math/roundf.c new file mode 100644 index 000000000..2b9542742 --- /dev/null +++ b/libc/mingw/math/roundf.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float +roundf (float x) +{ + float res; + if (x >= 0.0F) + { + res = ceilf (x); + if (res - x > 0.5F) + res -= 1.0F; + } + else + { + res = ceilf (-x); + if (res + x > 0.5F) + res -= 1.0F; + res = -res; + } + return res; +} diff --git a/libc/mingw/math/roundl.c b/libc/mingw/math/roundl.c new file mode 100644 index 000000000..9879a82cc --- /dev/null +++ b/libc/mingw/math/roundl.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +long double +roundl (long double x) +{ + long double res = 0.0L; + if (x >= 0.0L) + { + res = ceill (x); + if (res - x > 0.5L) + res -= 1.0L; + } + else + { + res = ceill (-x); + if (res + x > 0.5L) + res -= 1.0L; + res = -res; + } + return res; +} diff --git a/libc/mingw/math/s_erf.c b/libc/mingw/math/s_erf.c new file mode 100644 index 000000000..e65409b8b --- /dev/null +++ b/libc/mingw/math/s_erf.c @@ -0,0 +1,347 @@ +/* @(#)s_erf.c 1.3 95/01/18 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunSoft, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* double erf(double x) + * double erfc(double x) + * x + * 2 |\ + * erf(x) = --------- | exp(-t*t)dt + * sqrt(pi) \| + * 0 + * + * erfc(x) = 1-erf(x) + * Note that + * erf(-x) = -erf(x) + * erfc(-x) = 2 - erfc(x) + * + * Method: + * 1. For |x| in [0, 0.84375] + * erf(x) = x + x*R(x^2) + * erfc(x) = 1 - erf(x) if x in [-.84375,0.25] + * = 0.5 + ((0.5-x)-x*R) if x in [0.25,0.84375] + * where R = P/Q where P is an odd poly of degree 8 and + * Q is an odd poly of degree 10. + * -57.90 + * | R - (erf(x)-x)/x | <= 2 + * + * Remark. The formula is derived by noting + * erf(x) = (2/sqrt(pi))*(x - x^3/3 + x^5/10 - x^7/42 + ....) + * and that + * 2/sqrt(pi) = 1.128379167095512573896158903121545171688 + * is close to one. The interval is chosen because the fix + * point of erf(x) is near 0.6174 (i.e., erf(x)=x when x is + * near 0.6174), and by some experiment, 0.84375 is chosen to + * guarantee the error is less than one ulp for erf. + * + * 2. For |x| in [0.84375,1.25], let s = |x| - 1, and + * c = 0.84506291151 rounded to single (24 bits) + * erf(x) = sign(x) * (c + P1(s)/Q1(s)) + * erfc(x) = (1-c) - P1(s)/Q1(s) if x > 0 + * 1+(c+P1(s)/Q1(s)) if x < 0 + * |P1/Q1 - (erf(|x|)-c)| <= 2**-59.06 + * Remark: here we use the taylor series expansion at x=1. + * erf(1+s) = erf(1) + s*Poly(s) + * = 0.845.. + P1(s)/Q1(s) + * That is, we use rational approximation to approximate + * erf(1+s) - (c = (single)0.84506291151) + * Note that |P1/Q1|< 0.078 for x in [0.84375,1.25] + * where + * P1(s) = degree 6 poly in s + * Q1(s) = degree 6 poly in s + * + * 3. For x in [1.25,1/0.35(~2.857143)], + * erfc(x) = (1/x)*exp(-x*x-0.5625+R1/S1) + * erf(x) = 1 - erfc(x) + * where + * R1(z) = degree 7 poly in z, (z=1/x^2) + * S1(z) = degree 8 poly in z + * + * 4. For x in [1/0.35,28] + * erfc(x) = (1/x)*exp(-x*x-0.5625+R2/S2) if x > 0 + * = 2.0 - (1/x)*exp(-x*x-0.5625+R2/S2) if -6 x >= 28 + * erf(x) = sign(x) *(1 - tiny) (raise inexact) + * erfc(x) = tiny*tiny (raise underflow) if x > 0 + * = 2 - tiny if x<0 + * + * 7. Special case: + * erf(0) = 0, erf(inf) = 1, erf(-inf) = -1, + * erfc(0) = 1, erfc(inf) = 0, erfc(-inf) = 2, + * erfc/erf(NaN) is NaN + */ + + +/* #include "fdlibm.h" */ + +#include +#include +#include + +#define __ieee754_exp exp + +typedef union +{ + double value; + struct + { + uint32_t lsw; + uint32_t msw; + } parts; +} ieee_double_shape_type; + + +static inline int __get_hi_word(const double x) +{ + ieee_double_shape_type u; + u.value = x; + return u.parts.msw; +} + +static inline void __trunc_lo_word(double *x) +{ + ieee_double_shape_type u; + u.value = *x; + u.parts.lsw = 0; + *x = u.value; +} + + +static const double + tiny= 1e-300, + half= 5.00000000000000000000e-01, /* 0x3FE00000, 0x00000000 */ + one = 1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */ + two = 2.00000000000000000000e+00, /* 0x40000000, 0x00000000 */ + /* c = (float)0.84506291151 */ + erx = 8.45062911510467529297e-01, /* 0x3FEB0AC1, 0x60000000 */ + /* + * Coefficients for approximation to erf on [0,0.84375] + */ + efx = 1.28379167095512586316e-01, /* 0x3FC06EBA, 0x8214DB69 */ + efx8= 1.02703333676410069053e+00, /* 0x3FF06EBA, 0x8214DB69 */ + pp0 = 1.28379167095512558561e-01, /* 0x3FC06EBA, 0x8214DB68 */ + pp1 = -3.25042107247001499370e-01, /* 0xBFD4CD7D, 0x691CB913 */ + pp2 = -2.84817495755985104766e-02, /* 0xBF9D2A51, 0xDBD7194F */ + pp3 = -5.77027029648944159157e-03, /* 0xBF77A291, 0x236668E4 */ + pp4 = -2.37630166566501626084e-05, /* 0xBEF8EAD6, 0x120016AC */ + qq1 = 3.97917223959155352819e-01, /* 0x3FD97779, 0xCDDADC09 */ + qq2 = 6.50222499887672944485e-02, /* 0x3FB0A54C, 0x5536CEBA */ + qq3 = 5.08130628187576562776e-03, /* 0x3F74D022, 0xC4D36B0F */ + qq4 = 1.32494738004321644526e-04, /* 0x3F215DC9, 0x221C1A10 */ + qq5 = -3.96022827877536812320e-06, /* 0xBED09C43, 0x42A26120 */ + /* + * Coefficients for approximation to erf in [0.84375,1.25] + */ + pa0 = -2.36211856075265944077e-03, /* 0xBF6359B8, 0xBEF77538 */ + pa1 = 4.14856118683748331666e-01, /* 0x3FDA8D00, 0xAD92B34D */ + pa2 = -3.72207876035701323847e-01, /* 0xBFD7D240, 0xFBB8C3F1 */ + pa3 = 3.18346619901161753674e-01, /* 0x3FD45FCA, 0x805120E4 */ + pa4 = -1.10894694282396677476e-01, /* 0xBFBC6398, 0x3D3E28EC */ + pa5 = 3.54783043256182359371e-02, /* 0x3FA22A36, 0x599795EB */ + pa6 = -2.16637559486879084300e-03, /* 0xBF61BF38, 0x0A96073F */ + qa1 = 1.06420880400844228286e-01, /* 0x3FBB3E66, 0x18EEE323 */ + qa2 = 5.40397917702171048937e-01, /* 0x3FE14AF0, 0x92EB6F33 */ + qa3 = 7.18286544141962662868e-02, /* 0x3FB2635C, 0xD99FE9A7 */ + qa4 = 1.26171219808761642112e-01, /* 0x3FC02660, 0xE763351F */ + qa5 = 1.36370839120290507362e-02, /* 0x3F8BEDC2, 0x6B51DD1C */ + qa6 = 1.19844998467991074170e-02, /* 0x3F888B54, 0x5735151D */ + /* + * Coefficients for approximation to erfc in [1.25,1/0.35] + */ + ra0 = -9.86494403484714822705e-03, /* 0xBF843412, 0x600D6435 */ + ra1 = -6.93858572707181764372e-01, /* 0xBFE63416, 0xE4BA7360 */ + ra2 = -1.05586262253232909814e+01, /* 0xC0251E04, 0x41B0E726 */ + ra3 = -6.23753324503260060396e+01, /* 0xC04F300A, 0xE4CBA38D */ + ra4 = -1.62396669462573470355e+02, /* 0xC0644CB1, 0x84282266 */ + ra5 = -1.84605092906711035994e+02, /* 0xC067135C, 0xEBCCABB2 */ + ra6 = -8.12874355063065934246e+01, /* 0xC0545265, 0x57E4D2F2 */ + ra7 = -9.81432934416914548592e+00, /* 0xC023A0EF, 0xC69AC25C */ + sa1 = 1.96512716674392571292e+01, /* 0x4033A6B9, 0xBD707687 */ + sa2 = 1.37657754143519042600e+02, /* 0x4061350C, 0x526AE721 */ + sa3 = 4.34565877475229228821e+02, /* 0x407B290D, 0xD58A1A71 */ + sa4 = 6.45387271733267880336e+02, /* 0x40842B19, 0x21EC2868 */ + sa5 = 4.29008140027567833386e+02, /* 0x407AD021, 0x57700314 */ + sa6 = 1.08635005541779435134e+02, /* 0x405B28A3, 0xEE48AE2C */ + sa7 = 6.57024977031928170135e+00, /* 0x401A47EF, 0x8E484A93 */ + sa8 = -6.04244152148580987438e-02, /* 0xBFAEEFF2, 0xEE749A62 */ + /* + * Coefficients for approximation to erfc in [1/.35,28] + */ + rb0 = -9.86494292470009928597e-03, /* 0xBF843412, 0x39E86F4A */ + rb1 = -7.99283237680523006574e-01, /* 0xBFE993BA, 0x70C285DE */ + rb2 = -1.77579549177547519889e+01, /* 0xC031C209, 0x555F995A */ + rb3 = -1.60636384855821916062e+02, /* 0xC064145D, 0x43C5ED98 */ + rb4 = -6.37566443368389627722e+02, /* 0xC083EC88, 0x1375F228 */ + rb5 = -1.02509513161107724954e+03, /* 0xC0900461, 0x6A2E5992 */ + rb6 = -4.83519191608651397019e+02, /* 0xC07E384E, 0x9BDC383F */ + sb1 = 3.03380607434824582924e+01, /* 0x403E568B, 0x261D5190 */ + sb2 = 3.25792512996573918826e+02, /* 0x40745CAE, 0x221B9F0A */ + sb3 = 1.53672958608443695994e+03, /* 0x409802EB, 0x189D5118 */ + sb4 = 3.19985821950859553908e+03, /* 0x40A8FFB7, 0x688C246A */ + sb5 = 2.55305040643316442583e+03, /* 0x40A3F219, 0xCEDF3BE6 */ + sb6 = 4.74528541206955367215e+02, /* 0x407DA874, 0xE79FE763 */ + sb7 = -2.24409524465858183362e+01; /* 0xC03670E2, 0x42712D62 */ + + +double erf(double x) +{ + int hx, ix, i; + double R, S, P, Q, s, y, z, r; + hx = __get_hi_word(x); + ix = hx & 0x7fffffff; + if (ix >= 0x7ff00000) { /* erf(nan)=nan */ + i = ((unsigned)hx>>31)<<1; + return (double)(1-i)+one/x; /* erf(+-inf)=+-1 */ + } + + if (ix < 0x3feb0000) { /* |x|<0.84375 */ + if (ix < 0x3e300000) { /* |x|<2**-28 */ + if (ix < 0x00800000) + return 0.125*(8.0*x+efx8*x); /*avoid underflow */ + return x + efx*x; + } + z = x*x; + r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); + s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); + y = r/s; + return x + x*y; + } + if (ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ + s = fabs(x)-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if (hx >= 0) + return erx + P/Q; + else + return -erx - P/Q; + } + if (ix >= 0x40180000) { /* inf>|x|>=6 */ + if (hx >= 0) + return one-tiny; + else + return tiny-one; + } + x = fabs(x); + s = one/(x*x); + if (ix < 0x4006DB6E) { /* |x| < 1/0.35 */ + R = ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( + ra5+s*(ra6+s*ra7)))))); + S = one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( + sa5+s*(sa6+s*(sa7+s*sa8))))))); + } else { /* |x| >= 1/0.35 */ + R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( + rb5+s*rb6))))); + S = one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( + sb5+s*(sb6+s*sb7)))))); + } + z = x; + __trunc_lo_word(&z); + r = __ieee754_exp(-z*z-0.5625)*__ieee754_exp((z-x)*(z+x)+R/S); + if (hx >= 0) + return one-r/x; + else + return r/x-one; +} + +double erfc(double x) +{ + int hx,ix; + double R,S,P,Q,s,y,z,r; + hx = __get_hi_word(x); + ix = hx&0x7fffffff; + if (ix >= 0x7ff00000) { /* erfc(nan)=nan */ + /* erfc(+-inf)=0,2 */ + return (double)(((unsigned)hx>>31)<<1)+one/x; + } + + if (ix < 0x3feb0000) { /* |x|<0.84375 */ + if (ix < 0x3c700000) /* |x|<2**-56 */ + return one-x; + z = x*x; + r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); + s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); + y = r/s; + if (hx < 0x3fd00000) { /* x<1/4 */ + return one-(x+x*y); + } else { + r = x*y; + r += (x-half); + return half - r ; + } + } + if (ix < 0x3ff40000) { /* 0.84375 <= |x| < 1.25 */ + s = fabs(x)-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if (hx >= 0) { + z = one-erx; return z - P/Q; + } else { + z = erx+P/Q; return one+z; + } + } + if (ix < 0x403c0000) { /* |x|<28 */ + x = fabs(x); + s = one/(x*x); + if (ix < 0x4006DB6D) { /* |x| < 1/.35 ~ 2.857143*/ + R = ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( + ra5+s*(ra6+s*ra7)))))); + S = one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( + sa5+s*(sa6+s*(sa7+s*sa8))))))); + } else { /* |x| >= 1/.35 ~ 2.857143 */ + if (hx < 0 && ix >= 0x40180000) + return two-tiny; /* x < -6 */ + R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( + rb5+s*rb6))))); + S = one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( + sb5+s*(sb6+s*sb7)))))); + } + z = x; + __trunc_lo_word(&z); + r = __ieee754_exp(-z*z-0.5625)* + __ieee754_exp((z-x)*(z+x)+R/S); + if (hx > 0) + return r/x; + else + return two-r/x; + } else { + /* set range error */ + errno = ERANGE; + if (hx > 0) + return tiny*tiny; + else + return two-tiny; + } +} + diff --git a/libc/mingw/math/sf_erf.c b/libc/mingw/math/sf_erf.c new file mode 100644 index 000000000..1e1997b3c --- /dev/null +++ b/libc/mingw/math/sf_erf.c @@ -0,0 +1,268 @@ +/* sf_erf.c -- float version of s_erf.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* +#include "fdlibm.h" +*/ +#include +#include +#include + +#define __ieee754_expf expf + +typedef union +{ + float value; + uint32_t word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +static inline int +__get_float_word(float d) +{ + ieee_float_shape_type u; + u.value = d; + return u.word; +} + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +static inline void __trunc_float_word(float * x) +{ + ieee_float_shape_type u; + u.value = * x; + u.word &= 0xfffff000; +} + +#ifdef __v810__ +#define const +#endif + +static const float + tiny= 1e-30, + half= 5.0000000000e-01, /* 0x3F000000 */ + one = 1.0000000000e+00, /* 0x3F800000 */ + two = 2.0000000000e+00, /* 0x40000000 */ + /* c = (subfloat)0.84506291151 */ + erx = 8.4506291151e-01, /* 0x3f58560b */ + /* + * Coefficients for approximation to erf on [0,0.84375] + */ + efx = 1.2837916613e-01, /* 0x3e0375d4 */ + efx8= 1.0270333290e+00, /* 0x3f8375d4 */ + pp0 = 1.2837916613e-01, /* 0x3e0375d4 */ + pp1 = -3.2504209876e-01, /* 0xbea66beb */ + pp2 = -2.8481749818e-02, /* 0xbce9528f */ + pp3 = -5.7702702470e-03, /* 0xbbbd1489 */ + pp4 = -2.3763017452e-05, /* 0xb7c756b1 */ + qq1 = 3.9791721106e-01, /* 0x3ecbbbce */ + qq2 = 6.5022252500e-02, /* 0x3d852a63 */ + qq3 = 5.0813062117e-03, /* 0x3ba68116 */ + qq4 = 1.3249473704e-04, /* 0x390aee49 */ + qq5 = -3.9602282413e-06, /* 0xb684e21a */ + /* + * Coefficients for approximation to erf in [0.84375,1.25] + */ + pa0 = -2.3621185683e-03, /* 0xbb1acdc6 */ + pa1 = 4.1485610604e-01, /* 0x3ed46805 */ + pa2 = -3.7220788002e-01, /* 0xbebe9208 */ + pa3 = 3.1834661961e-01, /* 0x3ea2fe54 */ + pa4 = -1.1089469492e-01, /* 0xbde31cc2 */ + pa5 = 3.5478305072e-02, /* 0x3d1151b3 */ + pa6 = -2.1663755178e-03, /* 0xbb0df9c0 */ + qa1 = 1.0642088205e-01, /* 0x3dd9f331 */ + qa2 = 5.4039794207e-01, /* 0x3f0a5785 */ + qa3 = 7.1828655899e-02, /* 0x3d931ae7 */ + qa4 = 1.2617121637e-01, /* 0x3e013307 */ + qa5 = 1.3637083583e-02, /* 0x3c5f6e13 */ + qa6 = 1.1984500103e-02, /* 0x3c445aa3 */ + /* + * Coefficients for approximation to erfc in [1.25,1/0.35] + */ + ra0 = -9.8649440333e-03, /* 0xbc21a093 */ + ra1 = -6.9385856390e-01, /* 0xbf31a0b7 */ + ra2 = -1.0558626175e+01, /* 0xc128f022 */ + ra3 = -6.2375331879e+01, /* 0xc2798057 */ + ra4 = -1.6239666748e+02, /* 0xc322658c */ + ra5 = -1.8460508728e+02, /* 0xc3389ae7 */ + ra6 = -8.1287437439e+01, /* 0xc2a2932b */ + ra7 = -9.8143291473e+00, /* 0xc11d077e */ + sa1 = 1.9651271820e+01, /* 0x419d35ce */ + sa2 = 1.3765776062e+02, /* 0x4309a863 */ + sa3 = 4.3456588745e+02, /* 0x43d9486f */ + sa4 = 6.4538726807e+02, /* 0x442158c9 */ + sa5 = 4.2900814819e+02, /* 0x43d6810b */ + sa6 = 1.0863500214e+02, /* 0x42d9451f */ + sa7 = 6.5702495575e+00, /* 0x40d23f7c */ + sa8 = -6.0424413532e-02, /* 0xbd777f97 */ + /* + * Coefficients for approximation to erfc in [1/.35,28] + */ + rb0 = -9.8649431020e-03, /* 0xbc21a092 */ + rb1 = -7.9928326607e-01, /* 0xbf4c9dd4 */ + rb2 = -1.7757955551e+01, /* 0xc18e104b */ + rb3 = -1.6063638306e+02, /* 0xc320a2ea */ + rb4 = -6.3756646729e+02, /* 0xc41f6441 */ + rb5 = -1.0250950928e+03, /* 0xc480230b */ + rb6 = -4.8351919556e+02, /* 0xc3f1c275 */ + sb1 = 3.0338060379e+01, /* 0x41f2b459 */ + sb2 = 3.2579251099e+02, /* 0x43a2e571 */ + sb3 = 1.5367296143e+03, /* 0x44c01759 */ + sb4 = 3.1998581543e+03, /* 0x4547fdbb */ + sb5 = 2.5530502930e+03, /* 0x451f90ce */ + sb6 = 4.7452853394e+02, /* 0x43ed43a7 */ + sb7 = -2.2440952301e+01; /* 0xc1b38712 */ + +float erff(float x) +{ + int32_t hx, ix, i; + float R, S, P, Q, s, y, z, r; + hx = __get_float_word(x); + ix = hx & 0x7fffffff; + if (!(ix<0x7f800000L)) { /* erf(nan)=nan */ + i = ((uint32_t)hx>>31)<<1; + return (float)(1-i)+one/x; /* erf(+-inf)=+-1 */ + } + + if (ix < 0x3f580000) { /* |x|<0.84375 */ + if (ix < 0x31800000) { /* |x|<2**-28 */ + if (ix < 0x04000000) + /*avoid underflow */ + return (float)0.125*((float)8.0*x+efx8*x); + return x + efx*x; + } + z = x*x; + r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); + s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); + y = r/s; + return x + x*y; + } + if (ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ + s = fabsf(x)-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if (hx >= 0) + return erx + P/Q; + else + return -erx - P/Q; + } + if (ix >= 0x40c00000) { /* inf>|x|>=6 */ + if (hx >= 0) + return one-tiny; + else + return tiny-one; + } + x = fabsf(x); + s = one/(x*x); + if (ix< 0x4036DB6E) { /* |x| < 1/0.35 */ + R = ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( + ra5+s*(ra6+s*ra7)))))); + S = one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( + sa5+s*(sa6+s*(sa7+s*sa8))))))); + } else { /* |x| >= 1/0.35 */ + R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( + rb5+s*rb6))))); + S = one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( + sb5+s*(sb6+s*sb7)))))); + } + + z = x; + __trunc_float_word (&z); + r = __ieee754_expf(-z*z-(float)0.5625)*__ieee754_expf((z-x)*(z+x)+R/S); + if (hx >= 0) + return one-r/x; + else + return r/x-one; +} + +float erfcf(float x) +{ + int32_t hx, ix; + float R, S, P, Q, s, y, z, r; + hx = __get_float_word(x); + ix = hx & 0x7fffffff; + if (!(ix < 0x7f800000L)) { /* erfc(nan)=nan */ + /* erfc(+-inf)=0,2 */ + return (float)(((uint32_t)hx>>31)<<1)+one/x; + } + + if (ix < 0x3f580000) { /* |x|<0.84375 */ + if (ix < 0x23800000) /* |x|<2**-56 */ + return one-x; + z = x*x; + r = pp0+z*(pp1+z*(pp2+z*(pp3+z*pp4))); + s = one+z*(qq1+z*(qq2+z*(qq3+z*(qq4+z*qq5)))); + y = r/s; + if (hx < 0x3e800000) { /* x<1/4 */ + return one-(x+x*y); + } else { + r = x*y; + r += (x-half); + return half - r ; + } + } + if (ix < 0x3fa00000) { /* 0.84375 <= |x| < 1.25 */ + s = fabsf(x)-one; + P = pa0+s*(pa1+s*(pa2+s*(pa3+s*(pa4+s*(pa5+s*pa6))))); + Q = one+s*(qa1+s*(qa2+s*(qa3+s*(qa4+s*(qa5+s*qa6))))); + if (hx >= 0) { + z = one-erx; return z - P/Q; + } else { + z = erx+P/Q; return one+z; + } + } + + if (ix < 0x41e00000) { /* |x|<28 */ + x = fabsf(x); + s = one/(x*x); + if (ix< 0x4036DB6D) { /* |x| < 1/.35 ~ 2.857143*/ + R = ra0+s*(ra1+s*(ra2+s*(ra3+s*(ra4+s*( + ra5+s*(ra6+s*ra7)))))); + S = one+s*(sa1+s*(sa2+s*(sa3+s*(sa4+s*( + sa5+s*(sa6+s*(sa7+s*sa8))))))); + } else { /* |x| >= 1/.35 ~ 2.857143 */ + if (hx < 0 && ix >= 0x40c00000) + return two-tiny;/* x < -6 */ + R = rb0+s*(rb1+s*(rb2+s*(rb3+s*(rb4+s*( + rb5+s*rb6))))); + S = one+s*(sb1+s*(sb2+s*(sb3+s*(sb4+s*( + sb5+s*(sb6+s*sb7)))))); + } + + z = x; + __trunc_float_word (&z); + r = __ieee754_expf(-z*z-(float)0.5625)* + __ieee754_expf((z-x)*(z+x)+R/S); + if (hx > 0) + return r/x; + else + return two-r/x; + } else { + /* set range error */ + errno = ERANGE; + if (hx > 0) + return tiny*tiny; + else + return two-tiny; + } +} diff --git a/libc/mingw/math/signbit.c b/libc/mingw/math/signbit.c new file mode 100644 index 000000000..a97d8b9e9 --- /dev/null +++ b/libc/mingw/math/signbit.c @@ -0,0 +1,35 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __FP_SIGNBIT 0x0200 +int __signbit (double x); + +typedef union __mingw_dbl_type_t { + double x; + unsigned long long val; + __extension__ struct { + unsigned int low, high; + } lh; +} __mingw_dbl_type_t; + +int __signbit (double x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + __mingw_dbl_type_t hlp; + + hlp.x = x; + return ((hlp.lh.high & 0x80000000) != 0); +#elif defined(__i386__) || defined(_X86_) + unsigned short sw; + __asm__ __volatile__ ("fxam; fstsw %%ax;" + : "=a" (sw) + : "t" (x) ); + return (sw & __FP_SIGNBIT) != 0; +#endif +} + +#undef signbit +int __attribute__ ((alias ("__signbit"))) signbit (double); + diff --git a/libc/mingw/math/signbitf.c b/libc/mingw/math/signbitf.c new file mode 100644 index 000000000..bda71a61f --- /dev/null +++ b/libc/mingw/math/signbitf.c @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __FP_SIGNBIT 0x0200 +int __signbitf (float x); + +typedef union __mingw_flt_type_t { + float x; + unsigned int val; +} __mingw_flt_type_t; + +int __signbitf (float x) +{ +#if defined(__x86_64__) || defined(_AMD64_) || defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + __mingw_flt_type_t hlp; + hlp.x = x; + return ((hlp.val & 0x80000000) != 0); +#elif defined(__i386__) || defined(_X86_) + unsigned short sw; + __asm__ __volatile__ ("fxam; fstsw %%ax;" + : "=a" (sw) + : "t" (x) ); + return (sw & __FP_SIGNBIT) != 0; +#endif +} +int __attribute__ ((alias ("__signbitf"))) signbitf (float); diff --git a/libc/mingw/math/signbitl.c b/libc/mingw/math/signbitl.c new file mode 100644 index 000000000..723933dbb --- /dev/null +++ b/libc/mingw/math/signbitl.c @@ -0,0 +1,44 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +typedef union __mingw_ldbl_type_t +{ + long double x; + __extension__ struct { + unsigned int low, high; + int sign_exponent : 16; + int res1 : 16; + int res0 : 32; + } lh; +} __mingw_ldbl_type_t; + +typedef union __mingw_fp_types_t +{ + long double *ld; + __mingw_ldbl_type_t *ldt; +} __mingw_fp_types_t; + +#define __FP_SIGNBIT 0x0200 +extern int __signbit (double x); +int __signbitl (long double x); + + +int __signbitl (long double x) { +#if defined(__x86_64__) || defined(_AMD64_) + __mingw_fp_types_t ld; + ld.ld = &x; + return ((ld.ldt->lh.sign_exponent & 0x8000) != 0); +#elif defined(__arm__) || defined(_ARM_) || defined(__aarch64__) || defined(_ARM64_) + return __signbit(x); +#elif defined(__i386__) || defined(_X86_) + unsigned short sw; + __asm__ __volatile__ ("fxam; fstsw %%ax;" + : "=a" (sw) + : "t" (x) ); + return (sw & __FP_SIGNBIT) != 0; +#endif +} + +int __attribute__ ((alias ("__signbitl"))) signbitl (long double); diff --git a/libc/mingw/math/signgam.c b/libc/mingw/math/signgam.c new file mode 100644 index 000000000..ec17eb0ea --- /dev/null +++ b/libc/mingw/math/signgam.c @@ -0,0 +1,45 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2012 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +int signgam = 0; diff --git a/libc/mingw/math/sinhf.c b/libc/mingw/math/sinhf.c new file mode 100644 index 000000000..9048bf36c --- /dev/null +++ b/libc/mingw/math/sinhf.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +float sinhf (float x) +{ + return (float) sinh (x); +} diff --git a/libc/mingw/math/sinhl.c b/libc/mingw/math/sinhl.c new file mode 100644 index 000000000..4db0e51ff --- /dev/null +++ b/libc/mingw/math/sinhl.c @@ -0,0 +1,100 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" +#include + +#ifdef UNK +static uLD P[] = { + { { 1.7550769032975377032681E-6L } }, + { { 4.1680702175874268714539E-4L } }, + { { 3.0993532520425419002409E-2L } }, + { { 9.9999999999999999998002E-1L } } +}; +static long double Q[] = { + { { 1.7453965448620151484660E-8L } }, + { { -5.9116673682651952419571E-6L } }, + { { 1.0599252315677389339530E-3L } }, + { { -1.1403880487744749056675E-1L } }, + { { 6.0000000000000000000200E0L } } +}; +#endif + +#ifdef IBMPC +static const uLD P[] = { + { { 0xec6a,0xd942,0xfbb3,0xeb8f,0x3feb, 0, 0, 0 } }, + { { 0x365e,0xb30a,0xe437,0xda86,0x3ff3, 0, 0, 0 } }, + { { 0x8890,0x01f6,0x2612,0xfde6,0x3ff9, 0, 0, 0 } }, + { { 0x0000,0x0000,0x0000,0x8000,0x3fff, 0, 0, 0 } } +}; +static const uLD Q[] = { + { { 0x4edd,0x4c21,0xad09,0x95ed,0x3fe5, 0, 0, 0 } }, + { { 0x4376,0x9b70,0xd605,0xc65c,0xbfed, 0, 0, 0 } }, + { { 0xc8ad,0x5d21,0x3069,0x8aed,0x3ff5, 0, 0, 0 } }, + { { 0x9c32,0x6374,0x2d4b,0xe98d,0xbffb, 0, 0, 0 } }, + { { 0x0000,0x0000,0x0000,0xc000,0x4001, 0, 0, 0 } } +}; +#endif + +#ifdef MIEEE +static uLD P[] = { + { { 0x3feb0000,0xeb8ffbb3,0xd942ec6a, 0 } }, + { { 0x3ff30000,0xda86e437,0xb30a365e, 0 } }, + { { 0x3ff90000,0xfde62612,0x01f68890, 0 } }, + { { 0x3fff0000,0x80000000,0x00000000, 0 } } +}; +static uLD Q[] = { + { { 0x3fe50000,0x95edad09,0x4c214edd, 0 } }, + { { 0xbfed0000,0xc65cd605,0x9b704376, 0 } }, + { { 0x3ff50000,0x8aed3069,0x5d21c8ad, 0 } }, + { { 0xbffb0000,0xe98d2d4b,0x63749c32, 0 } }, + { { 0x40010000,0xc0000000,0x00000000, 0 } } +}; +#endif + +long double sinhl(long double x) +{ + long double a; + int x_class = fpclassify (x); + + if (x_class == FP_NAN) + { + errno = EDOM; + return x; + } + if (x_class == FP_ZERO) + return x; + if (x_class == FP_INFINITE || + (fabsl (x) > (MAXLOGL + LOGE2L))) + { + errno = ERANGE; +#ifdef INFINITIES + return (signbit (x) ? -INFINITYL : INFINITYL); +#else + return (signbit (x) ? -MAXNUML : MAXNUML); +#endif + } + a = fabsl (x); + if (a > 1.0L) + { + if (a >= (MAXLOGL - LOGE2L)) + { + a = expl(0.5L*a); + a = (0.5L * a) * a; + if (x < 0.0L) + a = -a; + return (a); + } + a = expl(a); + a = 0.5L*a - (0.5L/a); + if (x < 0.0L) + a = -a; + return (a); + } + + a *= a; + return (x + x * a * (polevll(a,P,3)/polevll(a,Q,4))); +} + diff --git a/libc/mingw/math/sqrt.c b/libc/mingw/math/sqrt.c new file mode 100644 index 000000000..7c854816c --- /dev/null +++ b/libc/mingw/math/sqrt.c @@ -0,0 +1,47 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#define X64_ASM "sqrtsd" +#include "sqrt.def.h" diff --git a/libc/mingw/math/sqrt.def.h b/libc/mingw/math/sqrt.def.h new file mode 100644 index 000000000..ed1e663ba --- /dev/null +++ b/libc/mingw/math/sqrt.def.h @@ -0,0 +1,92 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "../complex/complex_internal.h" +#include + +__FLT_TYPE +__FLT_ABI (sqrt) (__FLT_TYPE x) +{ + __FLT_TYPE res = __FLT_CST (0.0); + int x_class = fpclassify (x); + if (x_class == FP_NAN || signbit (x)) + { + if (x_class == FP_ZERO) + return __FLT_CST (-0.0); + + if (x_class == FP_NAN) + { + __FLT_RPT_DOMAIN ("sqrt", x, 0.0, x); + return x; + } + + res = -__FLT_NAN; + __FLT_RPT_DOMAIN ("sqrt", x, 0.0, res); + return res; + } + else if (x_class == FP_ZERO) + return __FLT_CST (0.0); + else if (x_class == FP_INFINITE) + return __FLT_HUGE_VAL; + else if (x == __FLT_CST (1.0)) + return __FLT_CST (1.0); +#if defined(__arm__) || defined(_ARM_) +#if _NEW_COMPLEX_FLOAT + asm volatile ("fsqrts %[dst], %[src];\n" : [dst] "=t" (res) : [src] "t" (x)); +#else + asm volatile ("fsqrtd %[dst], %[src];\n" : [dst] "=w" (res) : [src] "w" (x)); +#endif +#elif defined(__aarch64__) || defined(_ARM64_) +#if _NEW_COMPLEX_FLOAT + asm volatile ("fsqrt %s[dst], %s[src]\n" : [dst] "=w" (res) : [src] "w" (x)); +#else + asm volatile ("fsqrt %d[dst], %d[src]\n" : [dst] "=w" (res) : [src] "w" (x)); +#endif +#elif defined(_X86_) || defined(__i386__) || defined(_AMD64_) || defined(__x86_64__) + asm volatile ("fsqrt" : "=t" (res) : "0" (x)); +#else +#error Not supported on your platform yet +#endif + return res; +} diff --git a/libc/mingw/math/sqrtf.c b/libc/mingw/math/sqrtf.c new file mode 100644 index 000000000..316fda408 --- /dev/null +++ b/libc/mingw/math/sqrtf.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_FLOAT 1 +#include "sqrt.def.h" diff --git a/libc/mingw/math/sqrtl.c b/libc/mingw/math/sqrtl.c new file mode 100644 index 000000000..ffd818591 --- /dev/null +++ b/libc/mingw/math/sqrtl.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "sqrt.def.h" diff --git a/libc/mingw/math/tanhf.c b/libc/mingw/math/tanhf.c new file mode 100644 index 000000000..cb6f4c75a --- /dev/null +++ b/libc/mingw/math/tanhf.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +float tanhf (float x) +{ + return (float) tanh (x); +} diff --git a/libc/mingw/math/tanhl.c b/libc/mingw/math/tanhl.c new file mode 100644 index 000000000..2c48a6aab --- /dev/null +++ b/libc/mingw/math/tanhl.c @@ -0,0 +1,92 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" +#ifndef _SET_ERRNO +#define _SET_ERRNO(x) +#endif + +#ifdef UNK +static uLD P[] = { + { { -6.8473739392677100872869E-5L } }, + { { -9.5658283111794641589011E-1L } }, + { { -8.4053568599672284488465E1L } }, + { { -1.3080425704712825945553E3L } } +}; +static uLD Q[] = { + { { 9.6259501838840336946872E1L } }, + { { 1.8218117903645559060232E3L } }, + { { 3.9241277114138477845780E3L } } +}; +#endif + +#ifdef IBMPC +static uLD P[] = { + { { 0xd2a4,0x1b0c,0x8f15,0x8f99,0xbff1, 0, 0, 0 } }, + { { 0x5959,0x9111,0x9cc7,0xf4e2,0xbffe, 0, 0, 0 } }, + { { 0xb576,0xef5e,0x6d57,0xa81b,0xc005, 0, 0, 0 } }, + { { 0xe3be,0xbfbd,0x5cbc,0xa381,0xc009, 0, 0, 0 } } +}; +static uLD Q[] = { + { { 0x687f,0xce24,0xdd6c,0xc084,0x4005, 0, 0, 0 } }, + { { 0x3793,0xc95f,0xfa2f,0xe3b9,0x4009, 0, 0, 0 } }, + { { 0xd5a2,0x1f9c,0x0b1b,0xf542,0x400a, 0, 0, 0 } } +}; +#endif + +#ifdef MIEEE +static uLD P[] = { + { { 0xbff10000,0x8f998f15,0x1b0cd2a4, 0 } }, + { { 0xbffe0000,0xf4e29cc7,0x91115959, 0 } }, + { { 0xc0050000,0xa81b6d57,0xef5eb576, 0 } }, + { { 0xc0090000,0xa3815cbc,0xbfbde3be, 0 } } +}; +static uLD Q[] = { + { { 0x40050000,0xc084dd6c,0xce24687f, 0 } }, + { { 0x40090000,0xe3b9fa2f,0xc95f3793, 0 } }, + { { 0x400a0000,0xf5420b1b,0x1f9cd5a2, 0 } } +}; +#endif + +long double tanhl(long double x) +{ + long double s, z; + +#ifdef MINUSZERO + if (x == 0.0L) + return (x); +#endif + if (isnanl(x)) + { + _SET_ERRNO (EDOM); + return x; + } + + z = fabsl(x); + if (z > 0.5L * MAXLOGL) + { + _SET_ERRNO (ERANGE); + if (x > 0) + return (1.0L); + else + return (-1.0L); + } + if (z >= 0.625L) + { + s = expl(2.0*z); + z = 1.0L - 2.0/(s + 1.0L); + if (x < 0) + z = -z; + } + else + { + s = x * x; + z = polevll( s, P, 3 )/p1evll(s, Q, 3); + z = x * s * z; + z = x + z; + } + return (z); +} + diff --git a/libc/mingw/math/tgamma.c b/libc/mingw/math/tgamma.c new file mode 100644 index 000000000..a75f7a9c8 --- /dev/null +++ b/libc/mingw/math/tgamma.c @@ -0,0 +1,265 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" + +#ifdef UNK +static const uD P[7] = { + { { 1.60119522476751861407E-4 } }, + { { 1.19135147006586384913E-3 } }, + { { 1.04213797561761569935E-2 } }, + { { 4.76367800457137231464E-2 } }, + { { 2.07448227648435975150E-1 } }, + { { 4.94214826801497100753E-1 } }, + { { 9.99999999999999996796E-1 } } +}; +static const uD Q[8] = { + { { -2.31581873324120129819E-5 } }, + { { 5.39605580493303397842E-4 } }, + { { -4.45641913851797240494E-3 } }, + { { 1.18139785222060435552E-2 } }, + { { 3.58236398605498653373E-2 } }, + { { -2.34591795718243348568E-1 } }, + { { 7.14304917030273074085E-2 } }, + { { 1.00000000000000000320E0 } } +}; +#define MAXGAM 171.624376956302725 +static const double LOGPI = 1.14472988584940017414; +#endif + +#ifdef IBMPC +static const uD P[7] = { + { { 0x2153,0x3998,0xfcb8,0x3f24 } }, + { { 0xbfab,0xe686,0x84e3,0x3f53 } }, + { { 0x14b0,0xe9db,0x57cd,0x3f85 } }, + { { 0x23d3,0x18c4,0x63d9,0x3fa8 } }, + { { 0x7d31,0xdcae,0x8da9,0x3fca } }, + { { 0xe312,0x3993,0xa137,0x3fdf } }, + { { 0x0000,0x0000,0x0000,0x3ff0 } } +}; +static const uD Q[8] = { + { { 0xd3af,0x8400,0x487a,0xbef8 } }, + { { 0x2573,0x2915,0xae8a,0x3f41 } }, + { { 0xb44a,0xe750,0x40e4,0xbf72 } }, + { { 0xb117,0x5b1b,0x31ed,0x3f88 } }, + { { 0xde67,0xe33f,0x5779,0x3fa2 } }, + { { 0x87c2,0x9d42,0x071a,0xbfce } }, + { { 0x3c51,0xc9cd,0x4944,0x3fb2 } }, + { { 0x0000,0x0000,0x0000,0x3ff0 } } +}; +#define MAXGAM 171.624376956302725 +#endif + +#ifdef MIEEE +static const uD P[7] = { + { { 0x3f24,0xfcb8,0x3998,0x2153 } }, + { { 0x3f53,0x84e3,0xe686,0xbfab } }, + { { 0x3f85,0x57cd,0xe9db,0x14b0 } }, + { { 0x3fa8,0x63d9,0x18c4,0x23d3 } }, + { { 0x3fca,0x8da9,0xdcae,0x7d31 } }, + { { 0x3fdf,0xa137,0x3993,0xe312 } }, + { { 0x3ff0,0x0000,0x0000,0x0000 } } +}; +static const unsigned short Q[8] = { + { { 0xbef8,0x487a,0x8400,0xd3af } }, + { { 0x3f41,0xae8a,0x2915,0x2573 } }, + { { 0xbf72,0x40e4,0xe750,0xb44a } }, + { { 0x3f88,0x31ed,0x5b1b,0xb117 } }, + { { 0x3fa2,0x5779,0xe33f,0xde67 } }, + { { 0xbfce,0x071a,0x9d42,0x87c2 } }, + { { 0x3fb2,0x4944,0xc9cd,0x3c51 } }, + { { 0x3ff0,0x0000,0x0000,0x0000 } } +}; +#define MAXGAM 171.624376956302725 +#endif + +/* Stirling's formula for the gamma function */ +#if UNK +static const uD STIR[5] = { + { { 7.87311395793093628397E-4 } }, + { { -2.29549961613378126380E-4 } }, + { { -2.68132617805781232825E-3 } }, + { { 3.47222221605458667310E-3 } }, + { { 8.33333333333482257126E-2 } } +}; +#define MAXSTIR 143.01608 +static const double SQTPI = 2.50662827463100050242E0; +#endif +#if IBMPC +static const uD STIR[5] = { + { { 0x7293,0x592d,0xcc72,0x3f49 } }, + { { 0x1d7c,0x27e6,0x166b,0xbf2e } }, + { { 0x4fd7,0x07d4,0xf726,0xbf65 } }, + { { 0xc5fd,0x1b98,0x71c7,0x3f6c } }, + { { 0x5986,0x5555,0x5555,0x3fb5 } } +}; +#define MAXSTIR 143.01608 + +static const union +{ + unsigned short s[4]; + double d; +} sqt = {{0x2706,0x1ff6,0x0d93,0x4004}}; +#define SQTPI (sqt.d) +#endif +#if MIEEE +static const uD STIR[5] = { + { { 0x3f49,0xcc72,0x592d,0x7293 } }, + { { 0xbf2e,0x166b,0x27e6,0x1d7c } }, + { { 0xbf65,0xf726,0x07d4,0x4fd7 } }, + { { 0x3f6c,0x71c7,0x1b98,0xc5fd } }, + { { 0x3fb5,0x5555,0x5555,0x5986 } } +}; +#define MAXSTIR 143.01608 +static const uD SQT = { + { { 0x4004,0x0d93,0x1ff6,0x2706 } } +}; +#define SQTPI SQT.d +#endif + +static double stirf (double); + +/* Gamma function computed by Stirling's formula. + * The polynomial STIR is valid for 33 <= x <= 172. + */ +static double stirf(double x) +{ + double y, w, v; + + w = 1.0/x; + w = 1.0 + w * polevl(w, STIR, 4); + y = exp(x); + if (x > MAXSTIR) + { /* Avoid overflow in pow() */ + v = pow(x, 0.5 * x - 0.25); + y = v * (v / y); + } + else + { + y = pow(x, x - 0.5) / y; + } + y = SQTPI * y * w; + return (y); +} + + +double __tgamma_r(double x, int *sgngam); + +double __tgamma_r(double x, int *sgngam) +{ + double p, q, z; + int i; + + *sgngam = 1; +#ifdef NANS + if (isnan(x)) + return (x); +#endif +#ifdef INFINITIES +#ifdef NANS + if (x == INFINITY) + return (x); + if (x == -INFINITY) + return (NAN); +#else + if (!isfinite(x)) + return (x); +#endif +#endif + q = fabs(x); + + if (q > 33.0) + { + if (x < 0.0) + { + p = floor(q); + if (p == q) + { +gsing: + _SET_ERRNO(EDOM); + mtherr("tgamma", SING); +#ifdef INFINITIES + return (INFINITY); +#else + return (MAXNUM); +#endif + } + i = p; + if ((i & 1) == 0) + *sgngam = -1; + z = q - p; + if (z > 0.5) + { + p += 1.0; + z = q - p; + } + z = q * sin(PI * z); + if (z == 0.0) + { + _SET_ERRNO(ERANGE); + mtherr("tgamma", OVERFLOW); +#ifdef INFINITIES + return (*sgngam * INFINITY); +#else + return (*sgngam * MAXNUM); +#endif + } + z = fabs(z); + z = PI/(z * stirf(q)); + } + else + { + z = stirf(x); + } + return (*sgngam * z); + } + + z = 1.0; + while (x >= 3.0) + { + x -= 1.0; + z *= x; + } + + while (x < 0.0) + { + if (x > -1.E-9) + goto Small; + z /= x; + x += 1.0; + } + + while (x < 2.0) + { + if (x < 1.e-9) + goto Small; + z /= x; + x += 1.0; + } + + if (x == 2.0) + return (z); + + x -= 2.0; + p = polevl( x, P, 6 ); + q = polevl( x, Q, 7 ); + return (z * p / q); + +Small: + if (x == 0.0) + { + goto gsing; + } + else + return (z/((1.0 + 0.5772156649015329 * x) * x)); +} + +/* This is the C99 version */ +double tgamma(double x) +{ + int local_sgngam = 0; + return (__tgamma_r(x, &local_sgngam)); +} + diff --git a/libc/mingw/math/tgammaf.c b/libc/mingw/math/tgammaf.c new file mode 100644 index 000000000..771b55c77 --- /dev/null +++ b/libc/mingw/math/tgammaf.c @@ -0,0 +1,194 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" + +/* define MAXGAM 34.84425627277176174 */ + +/* Stirling's formula for the gamma function + * gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) ( 1 + 1/x P(1/x) ) + * .028 < 1/x < .1 + * relative error < 1.9e-11 + */ +static const float STIR[] = { + -2.705194986674176E-003, + 3.473255786154910E-003, + 8.333331788340907E-002, +}; +static const float MAXSTIR = 26.77; +static const float SQTPIF = 2.50662827463100050242; /* sqrt( 2 pi ) */ + +static float stirf(float); + +/* Gamma function computed by Stirling's formula, + * sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x)) + * The polynomial STIR is valid for 33 <= x <= 172. + */ +static float stirf( float x ) +{ + float y, w, v; + + w = 1.0/x; + w = 1.0 + w * polevlf(w, STIR, 2); + y = expf(-x); + if (x > MAXSTIR) + { /* Avoid overflow in pow() */ + v = powf(x, 0.5 * x - 0.25); + y *= v; + y *= v; + } + else + { + y = powf(x, x - 0.5) * y; + } + y = SQTPIF * y * w; + return (y); +} + + +/* gamma(x+2), 0 < x < 1 */ +static const float P[] = { + 1.536830450601906E-003, + 5.397581592950993E-003, + 4.130370201859976E-003, + 7.232307985516519E-002, + 8.203960091619193E-002, + 4.117857447645796E-001, + 4.227867745131584E-001, + 9.999999822945073E-001, +}; + +float __tgammaf_r( float x, int* sgngamf); + +float __tgammaf_r( float x, int* sgngamf) +{ + float p, q, z, nz; + int i, direction, negative; + +#ifdef NANS + if (isnan(x)) + return (x); +#endif +#ifdef INFINITIES +#ifdef NANS + if (x == INFINITYF) + return (x); + if (x == -INFINITYF) + return (NANF); +#else + if (!isfinite(x)) + return (x); +#endif +#endif + + *sgngamf = 1; + negative = 0; + nz = 0.0; + if (x < 0.0) + { + negative = 1; + q = -x; + p = floorf(q); + if (p == q) + { +gsing: + _SET_ERRNO(EDOM); + mtherr("tgammaf", SING); +#ifdef INFINITIES + return (INFINITYF); +#else + return (MAXNUMF); +#endif + } + i = p; + if ((i & 1) == 0) + *sgngamf = -1; + nz = q - p; + if (nz > 0.5) + { + p += 1.0; + nz = q - p; + } + nz = q * sinf(PIF * nz); + if (nz == 0.0) + { + _SET_ERRNO(ERANGE); + mtherr("tgamma", OVERFLOW); +#ifdef INFINITIES + return(*sgngamf * INFINITYF); +#else + return(*sgngamf * MAXNUMF); +#endif + } + if (nz < 0) + nz = -nz; + x = q; + } + if (x >= 10.0) + { + z = stirf(x); + } + if (x < 2.0) + direction = 1; + else + direction = 0; + z = 1.0; + while (x >= 3.0) + { + x -= 1.0; + z *= x; + } + /* + while (x < 0.0) + { + if (x > -1.E-4) + goto Small; + z *=x; + x += 1.0; + } + */ + while (x < 2.0) + { + if (x < 1.e-4) + goto Small; + z *=x; + x += 1.0; + } + + if (direction) + z = 1.0/z; + + if (x == 2.0) + return (z); + + x -= 2.0; + p = z * polevlf(x, P, 7); + +gdone: + if (negative) + { + p = *sgngamf * PIF/(nz * p ); + } + return (p); + +Small: + if (x == 0.0) + { + goto gsing; + } + else + { + p = z / ((1.0 + 0.5772156649015329 * x) * x); + goto gdone; + } +} + +/* This is the C99 version */ +float tgammaf(float x) +{ + int local_sgngamf = 0; + return (__tgammaf_r(x, &local_sgngamf)); +} + diff --git a/libc/mingw/math/tgammal.c b/libc/mingw/math/tgammal.c new file mode 100644 index 000000000..99408eed7 --- /dev/null +++ b/libc/mingw/math/tgammal.c @@ -0,0 +1,393 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include "cephes_mconf.h" + +/* +gamma(x+2) = gamma(x+2) P(x)/Q(x) +0 <= x <= 1 +Relative error +n=7, d=8 +Peak error = 1.83e-20 +Relative error spread = 8.4e-23 +*/ + +#if UNK +static const uLD P[8] = { + { { 4.212760487471622013093E-5L } }, + { { 4.542931960608009155600E-4L } }, + { { 4.092666828394035500949E-3L } }, + { { 2.385363243461108252554E-2L } }, + { { 1.113062816019361559013E-1L } }, + { { 3.629515436640239168939E-1L } }, + { { 8.378004301573126728826E-1L } }, + { { 1.000000000000000000009E0L } } +}; +static const uLD Q[9] = { + { { -1.397148517476170440917E-5L } }, + { { 2.346584059160635244282E-4L } }, + { { -1.237799246653152231188E-3L } }, + { { -7.955933682494738320586E-4L } }, + { { 2.773706565840072979165E-2L } }, + { { -4.633887671244534213831E-2L } }, + { { -2.243510905670329164562E-1L } }, + { { 4.150160950588455434583E-1L } }, + { { 9.999999999999999999908E-1L } } +}; +#endif +#if IBMPC +static const uLD P[8] = { + { { 0x434a,0x3f22,0x2bda,0xb0b2,0x3ff0, 0x0, 0x0, 0x0 } }, + { { 0xf5aa,0xe82f,0x335b,0xee2e,0x3ff3, 0x0, 0x0, 0x0 } }, + { { 0xbe6c,0x3757,0xc717,0x861b,0x3ff7, 0x0, 0x0, 0x0 } }, + { { 0x7f43,0x5196,0xb166,0xc368,0x3ff9, 0x0, 0x0, 0x0 } }, + { { 0x9549,0x8eb5,0x8c3a,0xe3f4,0x3ffb, 0x0, 0x0, 0x0 } }, + { { 0x8d75,0x23af,0xc8e4,0xb9d4,0x3ffd, 0x0, 0x0, 0x0 } }, + { { 0x29cf,0x19b3,0x16c8,0xd67a,0x3ffe, 0x0, 0x0, 0x0 } }, + { { 0x0000,0x0000,0x0000,0x8000,0x3fff, 0x0, 0x0, 0x0 } } +}; +static const uLD Q[9] = { + { { 0x5473,0x2de8,0x1268,0xea67,0xbfee, 0x0, 0x0, 0x0 } }, + { { 0x334b,0xc2f0,0xa2dd,0xf60e,0x3ff2, 0x0, 0x0, 0x0 } }, + { { 0xbeed,0x1853,0xa691,0xa23d,0xbff5, 0x0, 0x0, 0x0 } }, + { { 0x296e,0x7cb1,0x5dfd,0xd08f,0xbff4, 0x0, 0x0, 0x0 } }, + { { 0x0417,0x7989,0xd7bc,0xe338,0x3ff9, 0x0, 0x0, 0x0 } }, + { { 0x3295,0x3698,0xd580,0xbdcd,0xbffa, 0x0, 0x0, 0x0 } }, + { { 0x75ef,0x3ab7,0x4ad3,0xe5bc,0xbffc, 0x0, 0x0, 0x0 } }, + { { 0xe458,0x2ec7,0xfd57,0xd47c,0x3ffd, 0x0, 0x0, 0x0 } }, + { { 0x0000,0x0000,0x0000,0x8000,0x3fff, 0x0, 0x0, 0x0 } } +}; +#endif +#if MIEEE +static const uLD P[8] = { + { { 0x3ff00000,0xb0b22bda,0x3f22434a, 0 } }, + { { 0x3ff30000,0xee2e335b,0xe82ff5aa, 0 } }, + { { 0x3ff70000,0x861bc717,0x3757be6c, 0 } }, + { { 0x3ff90000,0xc368b166,0x51967f43, 0 } }, + { { 0x3ffb0000,0xe3f48c3a,0x8eb59549, 0 } }, + { { 0x3ffd0000,0xb9d4c8e4,0x23af8d75, 0 } }, + { { 0x3ffe0000,0xd67a16c8,0x19b329cf, 0 } }, + { { 0x3fff0000,0x80000000,0x00000000, 0 } } +}; +static const uLD Q[9] = { + { { 0xbfee0000,0xea671268,0x2de85473, 0 } }, + { { 0x3ff20000,0xf60ea2dd,0xc2f0334b, 0 } }, + { { 0xbff50000,0xa23da691,0x1853beed, 0 } }, + { { 0xbff40000,0xd08f5dfd,0x7cb1296e, 0 } }, + { { 0x3ff90000,0xe338d7bc,0x79890417, 0 } }, + { { 0xbffa0000,0xbdcdd580,0x36983295, 0 } }, + { { 0xbffc0000,0xe5bc4ad3,0x3ab775ef, 0 } }, + { { 0x3ffd0000,0xd47cfd57,0x2ec7e458, 0 } }, + { { 0x3fff0000,0x80000000,0x00000000, 0 } } +}; +#endif + +#define MAXGAML 1755.455L +/*static const long double LOGPI = 1.14472988584940017414L;*/ + +/* Stirling's formula for the gamma function +gamma(x) = sqrt(2 pi) x^(x-.5) exp(-x) (1 + 1/x P(1/x)) +z(x) = x +13 <= x <= 1024 +Relative error +n=8, d=0 +Peak error = 9.44e-21 +Relative error spread = 8.8e-4 +*/ +#if UNK +static const uLD STIR[9] = { + { { 7.147391378143610789273E-4L } }, + { { -2.363848809501759061727E-5L } }, + { { -5.950237554056330156018E-4L } }, + { { 6.989332260623193171870E-5L } }, + { { 7.840334842744753003862E-4L } }, + { { -2.294719747873185405699E-4L } }, + { { -2.681327161876304418288E-3L } }, + { { 3.472222222230075327854E-3L } }, + { { 8.333333333333331800504E-2L } } +}; +#endif +#if IBMPC +static const uLD STIR[9] = { + { { 0x6ede,0x69f7,0x54e3,0xbb5d,0x3ff4, 0, 0, 0 } }, + { { 0xc395,0x0295,0x4443,0xc64b,0xbfef, 0, 0, 0 } }, + { { 0xba6f,0x7c59,0x5e47,0x9bfb,0xbff4, 0, 0, 0 } }, + { { 0x5704,0x1a39,0xb11d,0x9293,0x3ff1, 0, 0, 0 } }, + { { 0x30b7,0x1a21,0x98b2,0xcd87,0x3ff4, 0, 0, 0 } }, + { { 0xbef3,0x7023,0x6a08,0xf09e,0xbff2, 0, 0, 0 } }, + { { 0x3a1c,0x5ac8,0x3478,0xafb9,0xbff6, 0, 0, 0 } }, + { { 0xc3c9,0x906e,0x38e3,0xe38e,0x3ff6, 0, 0, 0 } }, + { { 0xa1d5,0xaaaa,0xaaaa,0xaaaa,0x3ffb, 0, 0, 0 } } +}; +#endif +#if MIEEE +static const uLD STIR[9] = { + { { 0x3ff40000,0xbb5d54e3,0x69f76ede, 0 } }, + { { 0xbfef0000,0xc64b4443,0x0295c395, 0 } }, + { { 0xbff40000,0x9bfb5e47,0x7c59ba6f, 0 } }, + { { 0x3ff10000,0x9293b11d,0x1a395704, 0 } }, + { { 0x3ff40000,0xcd8798b2,0x1a2130b7, 0 } }, + { { 0xbff20000,0xf09e6a08,0x7023bef3, 0 } }, + { { 0xbff60000,0xafb93478,0x5ac83a1c, 0 } }, + { { 0x3ff60000,0xe38e38e3,0x906ec3c9, 0 } }, + { { 0x3ffb0000,0xaaaaaaaa,0xaaaaa1d5, 0 } } +}; +#endif +#define MAXSTIR 1024.0L +static const long double SQTPI = 2.50662827463100050242E0L; + +/* 1/gamma(x) = z P(z) + * z(x) = 1/x + * 0 < x < 0.03125 + * Peak relative error 4.2e-23 + */ +#if UNK +static const uLD S[9] = { + { { -1.193945051381510095614E-3L } }, + { { 7.220599478036909672331E-3L } }, + { { -9.622023360406271645744E-3L } }, + { { -4.219773360705915470089E-2L } }, + { { 1.665386113720805206758E-1L } }, + { { -4.200263503403344054473E-2L } }, + { { -6.558780715202540684668E-1L } }, + { { 5.772156649015328608253E-1L } }, + { { 1.000000000000000000000E0L } } +}; +#endif +#if IBMPC +static const uLD S[9] = { + { { 0xbaeb,0xd6d3,0x25e5,0x9c7e,0xbff5, 0, 0, 0 } }, + { { 0xfe9a,0xceb4,0xc74e,0xec9a,0x3ff7, 0, 0, 0 } }, + { { 0x9225,0xdfef,0xb0e9,0x9da5,0xbff8, 0, 0, 0 } }, + { { 0x10b0,0xec17,0x87dc,0xacd7,0xbffa, 0, 0, 0 } }, + { { 0x6b8d,0x7515,0x1905,0xaa89,0x3ffc, 0, 0, 0 } }, + { { 0xf183,0x126b,0xf47d,0xac0a,0xbffa, 0, 0, 0 } }, + { { 0x7bf6,0x57d1,0xa013,0xa7e7,0xbffe, 0, 0, 0 } }, + { { 0xc7a9,0x7db0,0x67e3,0x93c4,0x3ffe, 0, 0, 0 } }, + { { 0x0000,0x0000,0x0000,0x8000,0x3fff, 0, 0, 0 } } +}; +#endif +#if MIEEE +static const long S[9] = { + { { 0xbff50000,0x9c7e25e5,0xd6d3baeb, 0 } }, + { { 0x3ff70000,0xec9ac74e,0xceb4fe9a, 0 } }, + { { 0xbff80000,0x9da5b0e9,0xdfef9225, 0 } }, + { { 0xbffa0000,0xacd787dc,0xec1710b0, 0 } }, + { { 0x3ffc0000,0xaa891905,0x75156b8d, 0 } }, + { { 0xbffa0000,0xac0af47d,0x126bf183, 0 } }, + { { 0xbffe0000,0xa7e7a013,0x57d17bf6, 0 } }, + { { 0x3ffe0000,0x93c467e3,0x7db0c7a9, 0 } }, + { { 0x3fff0000,0x80000000,0x00000000, 0 } } +}; +#endif +/* 1/gamma(-x) = z P(z) + * z(x) = 1/x + * 0 < x < 0.03125 + * Peak relative error 5.16e-23 + * Relative error spread = 2.5e-24 + */ +#if UNK +static const uLD SN[9] = { + { { 1.133374167243894382010E-3L } }, + { { 7.220837261893170325704E-3L } }, + { { 9.621911155035976733706E-3L } }, + { { -4.219773343731191721664E-2L } }, + { { -1.665386113944413519335E-1L } }, + { { -4.200263503402112910504E-2L } }, + { { 6.558780715202536547116E-1L } }, + { { 5.772156649015328608727E-1L } }, + { { -1.000000000000000000000E0L } } +}; +#endif +#if IBMPC +static const uLD SN[9] = { + { { 0x5dd1,0x02de,0xb9f7,0x948d,0x3ff5, 0, 0, 0 } }, + { { 0x989b,0xdd68,0xc5f1,0xec9c,0x3ff7, 0, 0, 0 } }, + { { 0x2ca1,0x18f0,0x386f,0x9da5,0x3ff8, 0, 0, 0 } }, + { { 0x783f,0x41dd,0x87d1,0xacd7,0xbffa, 0, 0, 0 } }, + { { 0x7a5b,0xd76d,0x1905,0xaa89,0xbffc, 0, 0, 0 } }, + { { 0x7f64,0x1234,0xf47d,0xac0a,0xbffa, 0, 0, 0 } }, + { { 0x5e26,0x57d1,0xa013,0xa7e7,0x3ffe, 0, 0, 0 } }, + { { 0xc7aa,0x7db0,0x67e3,0x93c4,0x3ffe, 0, 0, 0 } }, + { { 0x0000,0x0000,0x0000,0x8000,0xbfff, 0, 0, 0 } } +}; +#endif +#if MIEEE +static const uLD SN[9] = { + { { 0x3ff50000,0x948db9f7,0x02de5dd1, 0 } }, + { { 0x3ff70000,0xec9cc5f1,0xdd68989b, 0 } }, + { { 0x3ff80000,0x9da5386f,0x18f02ca1, 0 } }, + { { 0xbffa0000,0xacd787d1,0x41dd783f, 0 } }, + { { 0xbffc0000,0xaa891905,0xd76d7a5b, 0 } }, + { { 0xbffa0000,0xac0af47d,0x12347f64, 0 } }, + { { 0x3ffe0000,0xa7e7a013,0x57d15e26, 0 } }, + { { 0x3ffe0000,0x93c467e3,0x7db0c7aa, 0 } }, + { { 0xbfff0000,0x80000000,0x00000000, 0 } } +}; +#endif + +static long double stirf (long double); + +/* Gamma function computed by Stirling's formula. */ + +static long double stirf(long double x) +{ + long double y, w, v; + + w = 1.0L/x; + /* For large x, use rational coefficients from the analytical expansion. */ + if (x > 1024.0L) + w = (((((6.97281375836585777429E-5L * w + + 7.84039221720066627474E-4L) * w + - 2.29472093621399176955E-4L) * w + - 2.68132716049382716049E-3L) * w + + 3.47222222222222222222E-3L) * w + + 8.33333333333333333333E-2L) * w + + 1.0L; + else + w = 1.0L + w * polevll( w, STIR, 8 ); + y = expl(x); + if (x > MAXSTIR) + { /* Avoid overflow in pow() */ + v = powl(x, 0.5L * x - 0.25L); + y = v * (v / y); + } + else + { + y = powl(x, x - 0.5L) / y; + } + y = SQTPI * y * w; + return (y); +} + +long double __tgammal_r(long double, int *); + +long double __tgammal_r(long double x, int* sgngaml) +{ + long double p, q, z; + int i; + + *sgngaml = 1; +#ifdef NANS + if (isnanl(x)) + return (NANL); +#endif +#ifdef INFINITIES +#ifdef NANS + if (x == INFINITYL) + return (x); + if (x == -INFINITYL) + return (NANL); +#else + if (!isfinite(x)) + return (x); +#endif +#endif + q = fabsl(x); + + if (q > 13.0L) + { + if (q > MAXGAML) + goto goverf; + if (x < 0.0L) + { + p = floorl(q); + if (p == q) + { +gsing: + _SET_ERRNO(EDOM); + mtherr("tgammal", SING); +#ifdef INFINITIES + return (INFINITYL); +#else + return (*sgngaml * MAXNUML); +#endif + } + i = p; + if ((i & 1) == 0) + *sgngaml = -1; + z = q - p; + if (z > 0.5L) + { + p += 1.0L; + z = q - p; + } + z = q * sinl(PIL * z); + z = fabsl(z) * stirf(q); + if (z <= PIL/MAXNUML) + { +goverf: + _SET_ERRNO(ERANGE); + mtherr("tgammal", OVERFLOW); +#ifdef INFINITIES + return(*sgngaml * INFINITYL); +#else + return(*sgngaml * MAXNUML); +#endif + } + z = PIL/z; + } + else + { + z = stirf(x); + } + return (*sgngaml * z); + } + + z = 1.0L; + while (x >= 3.0L) + { + x -= 1.0L; + z *= x; + } + + while (x < -0.03125L) + { + z /= x; + x += 1.0L; + } + + if (x <= 0.03125L) + goto Small; + + while (x < 2.0L) + { + z /= x; + x += 1.0L; + } + + if (x == 2.0L) + return (z); + + x -= 2.0L; + p = polevll( x, P, 7 ); + q = polevll( x, Q, 8 ); + return (z * p / q); + +Small: + if (x == 0.0L) + { + goto gsing; + } + else + { + if (x < 0.0L) + { + x = -x; + q = z / (x * polevll(x, SN, 8)); + } + else + q = z / (x * polevll(x, S, 8)); + } + return q; +} + +/* This is the C99 version. */ +long double tgammal(long double x) +{ + int local_sgngaml = 0; + return (__tgammal_r(x, &local_sgngaml)); +} + diff --git a/libc/mingw/math/truncl.c b/libc/mingw/math/truncl.c new file mode 100644 index 000000000..3b47e53d1 --- /dev/null +++ b/libc/mingw/math/truncl.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +long double +truncl (long double _x) +{ +#if defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) + return trunc(_x); +#else + long double retval = 0.0L; + unsigned short saved_cw; + unsigned short tmp_cw; + __asm__ __volatile__ ("fnstcw %0;" : "=m" (saved_cw)); /* save FPU control word */ + tmp_cw = (saved_cw & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) + | FE_TOWARDZERO; + __asm__ __volatile__ ("fldcw %0;" : : "m" (tmp_cw)); + __asm__ __volatile__ ("frndint;" : "=t" (retval) : "0" (_x)); /* round towards zero */ + __asm__ __volatile__ ("fldcw %0;" : : "m" (saved_cw) ); /* restore saved control word */ + return retval; +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ +} diff --git a/libc/mingw/math/x86/_chgsignl.S b/libc/mingw/math/x86/_chgsignl.S new file mode 100644 index 000000000..ae601b2c4 --- /dev/null +++ b/libc/mingw/math/x86/_chgsignl.S @@ -0,0 +1,46 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + * + * IEEE 854 double-extended-precision format + * unsigned int mantissa1:32 + * unsigned int mantissa0:32 + * unsigned int exponent:15 + * unsigned int negative:1 + * unsigned int empty:16 + * + * long double _chgsignl(long double x) { + * ((unsigned int *) &x)[2] ^= 0x00008000; + * return x; + * } + */ + +#include <_mingw_mac.h> + + .file "_chgignl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + .globl __MINGW_USYMBOL(_chgsignl) + .def __MINGW_USYMBOL(_chgsignl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(_chgsignl): +#if defined(_AMD64_) || defined(__x86_64__) + movq (%rdx), %rax + movq 8(%rdx), %rdx + xorq $0x8000, %rdx + movq %rax, (%rcx) + movq %rdx, 8(%rcx) + movq %rcx, %rax + ret +#elif defined(_X86_) || defined(__i386__) + movl 12(%esp),%eax + xorl $0x8000,%eax + movl %eax,12(%esp) + fldt 4(%esp) + ret +#endif + diff --git a/libc/mingw/math/x86/acosf.c b/libc/mingw/math/x86/acosf.c new file mode 100644 index 000000000..4246be090 --- /dev/null +++ b/libc/mingw/math/x86/acosf.c @@ -0,0 +1,29 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Public domain. + */ + +#include + +float +acosf (float x) +{ + float res = 0.0F; + + /* acosl = atanl (sqrtl(1 - x^2) / x) */ + asm volatile ( + "fld %%st\n\t" + "fmul %%st(0)\n\t" /* x^2 */ + "fld1\n\t" + "fsubp\n\t" /* 1 - x^2 */ + "fsqrt\n\t" /* sqrtl (1 - x^2) */ + "fxch %%st(1)\n\t" + "fpatan" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/acosh.c b/libc/mingw/math/x86/acosh.c new file mode 100644 index 000000000..ef7007f9d --- /dev/null +++ b/libc/mingw/math/x86/acosh.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "acosh.def.h" diff --git a/libc/mingw/math/x86/acosh.def.h b/libc/mingw/math/x86/acosh.def.h new file mode 100644 index 000000000..7ecf08beb --- /dev/null +++ b/libc/mingw/math/x86/acosh.def.h @@ -0,0 +1,70 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "../complex/complex_internal.h" +#include +#include "fastmath.h" + +__FLT_TYPE +__FLT_ABI(acosh) (__FLT_TYPE x) +{ + int x_class = fpclassify (x); + if (x_class == FP_NAN || x < __FLT_CST(1.0)) + { + __FLT_RPT_DOMAIN ("acosh", x, 0.0, __FLT_NAN); + return __FLT_NAN; + } + else if (x_class == FP_INFINITE) + { + __FLT_RPT_DOMAIN ("acosh", x, 0.0, __FLT_NAN); + return __FLT_NAN; + } + + if (x > __FLT_CST(0x1p32)) + return __FLT_ABI (__fast_log) (x) + 6.9314718055994530941723E-1L; + + return __FLT_ABI (__fast_log) (x + + __FLT_ABI (__fast_sqrt) ((x + __FLT_CST(1.0)) * (x - __FLT_CST(1.0)))); +} + diff --git a/libc/mingw/math/x86/acoshf.c b/libc/mingw/math/x86/acoshf.c new file mode 100644 index 000000000..a5a78eb43 --- /dev/null +++ b/libc/mingw/math/x86/acoshf.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_FLOAT 1 +#include "acosh.def.h" diff --git a/libc/mingw/math/x86/acoshl.c b/libc/mingw/math/x86/acoshl.c new file mode 100644 index 000000000..88f9f130e --- /dev/null +++ b/libc/mingw/math/x86/acoshl.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "acosh.def.h" diff --git a/libc/mingw/math/x86/acosl.c b/libc/mingw/math/x86/acosl.c new file mode 100644 index 000000000..553d06f75 --- /dev/null +++ b/libc/mingw/math/x86/acosl.c @@ -0,0 +1,23 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +long double acosl (long double x); + +long double acosl (long double x) +{ + long double res = 0.0L; + + /* acosl = atanl (sqrtl(1 - x^2) / x) */ + asm volatile ( + "fld %%st\n\t" + "fmul %%st(0)\n\t" /* x^2 */ + "fld1\n\t" + "fsubp\n\t" /* 1 - x^2 */ + "fsqrt\n\t" /* sqrtl (1 - x^2) */ + "fxch %%st(1)\n\t" + "fpatan" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/asinf.c b/libc/mingw/math/x86/asinf.c new file mode 100644 index 000000000..f0be4beb3 --- /dev/null +++ b/libc/mingw/math/x86/asinf.c @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Public domain. + */ + +/* asin = atan (x / sqrt(1 - x^2)) */ + +float asinf (float x); + +float asinf (float x) +{ + float res = 0.0F; + + asm volatile ( + "fld %%st\n\t" + "fmul %%st(0)\n\t" /* x^2 */ + "fld1\n\t" + "fsubp\n\t" /* 1 - x^2 */ + "fsqrt\n\t" /* sqrt (1 - x^2) */ + "fpatan" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/asinh.c b/libc/mingw/math/x86/asinh.c new file mode 100644 index 000000000..826cc6dee --- /dev/null +++ b/libc/mingw/math/x86/asinh.c @@ -0,0 +1,33 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include "fastmath.h" + + /* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */ +double asinh(double x) +{ + double z; + if (!isfinite (x)) + return x; + z = fabs (x); + + /* Avoid setting FPU underflow exception flag in x * x. */ +#if 0 + if ( z < 0x1p-32) + return x; +#endif + + /* Use log1p to avoid cancellation with small x. Put + x * x in denom, so overflow is harmless. + asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0) + = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */ + + z = __fast_log1p (z + z * z / (__fast_sqrt (z * z + 1.0) + 1.0)); + + return ( x > 0.0 ? z : -z); +} + diff --git a/libc/mingw/math/x86/asinhf.c b/libc/mingw/math/x86/asinhf.c new file mode 100644 index 000000000..fae785abe --- /dev/null +++ b/libc/mingw/math/x86/asinhf.c @@ -0,0 +1,33 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include "fastmath.h" + + /* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */ +float asinhf(float x) +{ + float z; + if (!isfinite (x)) + return x; + z = fabsf (x); + + /* Avoid setting FPU underflow exception flag in x * x. */ +#if 0 + if ( z < 0x1p-32) + return x; +#endif + + + /* Use log1p to avoid cancellation with small x. Put + x * x in denom, so overflow is harmless. + asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0) + = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */ + + z = __fast_log1p (z + z * z / (__fast_sqrt (z * z + 1.0) + 1.0)); + + return ( x > 0.0 ? z : -z); +} diff --git a/libc/mingw/math/x86/asinhl.c b/libc/mingw/math/x86/asinhl.c new file mode 100644 index 000000000..bb2ca97b2 --- /dev/null +++ b/libc/mingw/math/x86/asinhl.c @@ -0,0 +1,33 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include "fastmath.h" + + /* asinh(x) = copysign(log(fabs(x) + sqrt(x * x + 1.0)), x) */ +long double asinhl(long double x) +{ + long double z; + if (!isfinite (x)) + return x; + + z = fabsl (x); + + /* Avoid setting FPU underflow exception flag in x * x. */ +#if 0 + if ( z < 0x1p-32) + return x; +#endif + + /* Use log1p to avoid cancellation with small x. Put + x * x in denom, so overflow is harmless. + asinh(x) = log1p (x + sqrt (x * x + 1.0) - 1.0) + = log1p (x + x * x / (sqrt (x * x + 1.0) + 1.0)) */ + + z = __fast_log1pl (z + z * z / (__fast_sqrtl (z * z + 1.0L) + 1.0L)); + + return ( x > 0.0 ? z : -z); +} diff --git a/libc/mingw/math/x86/asinl.c b/libc/mingw/math/x86/asinl.c new file mode 100644 index 000000000..35df3b5dd --- /dev/null +++ b/libc/mingw/math/x86/asinl.c @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Public domain. + * Adapted for long double type by Danny Smith . + */ + +/* asin = atan (x / sqrt(1 - x^2)) */ +long double asinl (long double x); + +long double asinl (long double x) +{ + long double res = 0.0L; + + asm volatile ( + "fld %%st\n\t" + "fmul %%st(0)\n\t" /* x^2 */ + "fld1\n\t" + "fsubp\n\t" /* 1 - x^2 */ + "fsqrt\n\t" /* sqrt (1 - x^2) */ + "fpatan" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/atan2.c b/libc/mingw/math/x86/atan2.c new file mode 100644 index 000000000..1d8a09978 --- /dev/null +++ b/libc/mingw/math/x86/atan2.c @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +double +atan2 (double y, double x) +{ + double res = 0.0; + asm volatile ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/atan2f.c b/libc/mingw/math/x86/atan2f.c new file mode 100644 index 000000000..915c3e451 --- /dev/null +++ b/libc/mingw/math/x86/atan2f.c @@ -0,0 +1,20 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Public domain. + * + */ + +#include + +float +atan2f (float y, float x) +{ + float res = 0.0F; + asm volatile ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/atan2l.c b/libc/mingw/math/x86/atan2l.c new file mode 100644 index 000000000..a4300cbf4 --- /dev/null +++ b/libc/mingw/math/x86/atan2l.c @@ -0,0 +1,14 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +long double atan2l (long double y, long double x); + +long double +atan2l (long double y, long double x) +{ + long double res = 0.0L; + asm volatile ("fpatan" : "=t" (res) : "u" (y), "0" (x) : "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/atanf.c b/libc/mingw/math/x86/atanf.c new file mode 100644 index 000000000..f11bfc65e --- /dev/null +++ b/libc/mingw/math/x86/atanf.c @@ -0,0 +1,23 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Public domain. + * + */ + +#include + +float +atanf (float x) +{ + float res = 0.0F; + + asm volatile ( + "fld1\n\t" + "fpatan" : "=t" (res) : "0" (x)); + return res; +} diff --git a/libc/mingw/math/x86/atanh.c b/libc/mingw/math/x86/atanh.c new file mode 100644 index 000000000..429bfeae7 --- /dev/null +++ b/libc/mingw/math/x86/atanh.c @@ -0,0 +1,36 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include "fastmath.h" + +/* atanh (x) = 0.5 * log ((1.0 + x)/(1.0 - x)) */ + +double atanh(double x) +{ + double z; + if (isnan (x)) + return x; + z = fabs (x); + if (z == 1.0) + { + errno = ERANGE; + return (x > 0 ? INFINITY : -INFINITY); + } + if (z > 1.0) + { + errno = EDOM; + return nan(""); + } + /* Rearrange formula to avoid precision loss for small x. + + atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x)) + = 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0) + = 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) + = 0.5 * log1p ((2.0 * x ) / (1.0 - x)) */ + z = 0.5 * __fast_log1p ((z + z) / (1.0 - z)); + return x >= 0 ? z : -z; +} diff --git a/libc/mingw/math/x86/atanhf.c b/libc/mingw/math/x86/atanhf.c new file mode 100644 index 000000000..96d1e9b22 --- /dev/null +++ b/libc/mingw/math/x86/atanhf.c @@ -0,0 +1,35 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include "fastmath.h" + +/* atanh (x) = 0.5 * log ((1.0 + x)/(1.0 - x)) */ +float atanhf (float x) +{ + float z; + if (isnan (x)) + return x; + z = fabsf (x); + if (z == 1.0) + { + errno = ERANGE; + return (x > 0 ? INFINITY : -INFINITY); + } + if ( z > 1.0) + { + errno = EDOM; + return nanf(""); + } + /* Rearrange formula to avoid precision loss for small x. + + atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x)) + = 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0) + = 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) + = 0.5 * log1p ((2.0 * x ) / (1.0 - x)) */ + z = 0.5 * __fast_log1p ((z + z) / (1.0 - z)); + return x >= 0 ? z : -z; +} diff --git a/libc/mingw/math/x86/atanhl.c b/libc/mingw/math/x86/atanhl.c new file mode 100644 index 000000000..59eb1bd91 --- /dev/null +++ b/libc/mingw/math/x86/atanhl.c @@ -0,0 +1,34 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include "fastmath.h" + +/* atanh (x) = 0.5 * log ((1.0 + x)/(1.0 - x)) */ +long double atanhl (long double x) +{ + long double z; + if (isnan (x)) + return x; + z = fabsl (x); + if (z == 1.0L) + { + errno = ERANGE; + return (x > 0 ? INFINITY : -INFINITY); + } + if ( z > 1.0L) + { + errno = EDOM; + return nanl(""); + } + /* Rearrange formula to avoid precision loss for small x. + atanh(x) = 0.5 * log ((1.0 + x)/(1.0 - x)) + = 0.5 * log1p ((1.0 + x)/(1.0 - x) - 1.0) + = 0.5 * log1p ((1.0 + x - 1.0 + x) /(1.0 - x)) + = 0.5 * log1p ((2.0 * x ) / (1.0 - x)) */ + z = 0.5L * __fast_log1pl ((z + z) / (1.0L - z)); + return x >= 0 ? z : -z; +} diff --git a/libc/mingw/math/x86/atanl.c b/libc/mingw/math/x86/atanl.c new file mode 100644 index 000000000..d289ef08c --- /dev/null +++ b/libc/mingw/math/x86/atanl.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +long double atanl (long double x); + +long double +atanl (long double x) +{ + long double res = 0.0L; + + asm volatile ( + "fld1\n\t" + "fpatan" + : "=t" (res) : "0" (x)); + return res; +} diff --git a/libc/mingw/math/x86/ceil.S b/libc/mingw/math/x86/ceil.S new file mode 100644 index 000000000..c20343aa4 --- /dev/null +++ b/libc/mingw/math/x86/ceil.S @@ -0,0 +1,115 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceil.S" + .text + .align 4 + .globl __MINGW_USYMBOL(ceil) + .def __MINGW_USYMBOL(ceil); .scl 2; .type 32; .endef +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(ceil) +#endif + +__MINGW_USYMBOL(ceil): +#if defined(_AMD64_) || defined(__x86_64__) + .seh_endprologue + movd %xmm0, %rax + movq %rax, %rcx + sarq $52, %rcx + andl $2047, %ecx + subl $1023, %ecx + cmpl $51, %ecx + jg .is_intnaninf + /* Is x zero? */ + testq %rax, %rax + je .ret_org + /* Is x signed? */ + testl %ecx, %ecx + js .signed_val + /* Is x integral? */ + movabsq $4503599627370495, %rdx + sarq %cl, %rdx + testq %rax, %rdx + je .ret_org + addsd .huge(%rip), %xmm0 + ucomisd .zero(%rip), %xmm0 + jbe .doret + testq %rax, %rax + jle .l1 + /* inexact ... */ + movabsq $4503599627370496, %r8 + shrq %cl, %r8 + addq %r8, %rax +.l1: + notq %rdx + andq %rdx, %rax +.doret: + movd %rax, %xmm0 + ret + .p2align 4,,10 +.signed_val: + addsd .huge(%rip), %xmm0 + ucomisd .zero(%rip), %xmm0 + jbe .doret2 + testq %rax, %rax + movabsq $4607182418800017408, %rdx + movabsq $-9223372036854775808, %rax + cmovns %rdx, %rax + .p2align 4,,10 +.doret2: + movd %rax, %xmm0 + ret + + .p2align 4,,10 +.is_intnaninf: + /* Is Nan or Inf? */ + cmpl $1024, %ecx + je .ret_naninf + .p2align 4,,10 +.ret_org: + /* return x. */ + rep + ret + .p2align 4,,10 +.ret_naninf: + /* return x + x; */ + addsd %xmm0, %xmm0 + ret + .seh_endproc + +/* local data. */ + .section .rdata,"dr" + .align 8 +.huge: + .long -2013235812 + .long 2117592124 + .align 8 +.zero: + .long 0 + .long 0 +#elif defined(_X86_) || defined(__i386__) + fldl 4(%esp) + subl $8,%esp + + fstcw 4(%esp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x0800,%edx /* round towards +oo */ + orl 4(%esp),%edx + andl $0xfbff,%edx + movl %edx,(%esp) + fldcw (%esp) /* load modified control word */ + + frndint /* round */ + + fldcw 4(%esp) /* restore original control word */ + + addl $8,%esp + ret +#endif diff --git a/libc/mingw/math/x86/ceilf.S b/libc/mingw/math/x86/ceilf.S new file mode 100644 index 000000000..9096dbc2b --- /dev/null +++ b/libc/mingw/math/x86/ceilf.S @@ -0,0 +1,111 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceilf.S" + .text + .align 4 + .globl __MINGW_USYMBOL(ceilf) + .def __MINGW_USYMBOL(ceilf); .scl 2; .type 32; .endef +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(ceilf) +#endif + +__MINGW_USYMBOL(ceilf): +#if defined(_AMD64_) || defined(__x86_64__) + subq $24, %rsp + .seh_stackalloc 24 + .seh_endprologue + movd %xmm0, 12(%rsp) + movl 12(%rsp), %eax + movl %eax, %ecx + movl %eax, %edx + sarl $23, %ecx + andl $255, %ecx + subl $127, %ecx + cmpl $22, %ecx + jg .l4 + testl %ecx, %ecx + js .l5 + movl $8388607, %r8d + sarl %cl, %r8d + testl %eax, %r8d + je .l3 + addss .hugeval(%rip), %xmm0 + ucomiss .zeroval(%rip), %xmm0 + jbe .l2 + testl %eax, %eax + jle .l1 + movl $8388608, %eax + sarl %cl, %eax + addl %eax, %edx +.l1: + movl %r8d, %eax + notl %eax + andl %edx, %eax +.l2: + movl %eax, 8(%rsp) + movss 8(%rsp), %xmm0 +.l3: + addq $24, %rsp + ret + .p2align 4,,10 +.l4: + addl $-128, %ecx + jne .l3 + addss %xmm0, %xmm0 + addq $24, %rsp + ret + .p2align 4,,10 +.l5: + addss .hugeval(%rip), %xmm0 + ucomiss .zeroval(%rip), %xmm0 + jbe .islesseqzero + testl %eax, %eax + js .l6 + movl $1065353216, %edx + cmovne %edx, %eax +.islesseqzero: + movl %eax, 8(%rsp) + movss 8(%rsp), %xmm0 + addq $24, %rsp + ret + .p2align 4,,10 +.l6: + movl $-2147483648, 8(%rsp) + movss 8(%rsp), %xmm0 + addq $24, %rsp + ret + .seh_endproc + .section .rdata,"dr" + .align 4 +.hugeval: + .long 1900671690 + .align 4 +.zeroval: + .long 0 +#elif defined(_X86_) || defined(__i386__) + flds 4(%esp) + subl $8,%esp + + fstcw 4(%esp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x0800,%edx /* round towards +oo */ + orl 4(%esp),%edx + andl $0xfbff,%edx + movl %edx,(%esp) + fldcw (%esp) /* load modified control word */ + + frndint /* round */ + + fldcw 4(%esp) /* restore original control word */ + + addl $8,%esp + ret +#endif diff --git a/libc/mingw/math/x86/ceill.S b/libc/mingw/math/x86/ceill.S new file mode 100644 index 000000000..04b609333 --- /dev/null +++ b/libc/mingw/math/x86/ceill.S @@ -0,0 +1,55 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ceill.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + .globl __MINGW_USYMBOL(ceill) + .def __MINGW_USYMBOL(ceill); .scl 2; .type 32; .endef +__MINGW_USYMBOL(ceill): +#if defined(_AMD64_) || defined(__x86_64__) + fldt (%rdx) + subq $24,%rsp + + fstcw 8(%rsp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x0800,%edx /* round towards +oo */ + orl 8(%rsp),%edx + andl $0xfbff,%edx + movl %edx,(%rsp) + fldcw (%rsp) /* load modified control word */ + + frndint /* round */ + + fldcw 8(%rsp) /* restore original control word */ + + addq $24,%rsp + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#elif defined(_X86_) || defined(__i386__) + fldt 4(%esp) + subl $8,%esp + fstcw 4(%esp) + movl $0x0800,%edx + orl 4(%esp),%edx + andl $0xfbff,%edx + movl %edx,(%esp) + fldcw (%esp) + frndint + fldcw 4(%esp) + addl $8,%esp + ret +#endif diff --git a/libc/mingw/math/x86/copysignl.S b/libc/mingw/math/x86/copysignl.S new file mode 100644 index 000000000..6f98c7a5d --- /dev/null +++ b/libc/mingw/math/x86/copysignl.S @@ -0,0 +1,44 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ +#include <_mingw_mac.h> + + .file "copysignl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + + .globl __MINGW_USYMBOL(copysignl) + .def __MINGW_USYMBOL(copysignl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(copysignl): +#if defined(_AMD64_) || defined(__x86_64__) + movq (%rdx), %rax + movq %rax, (%rcx) + movq 8(%rdx), %rax + movq 8(%r8), %rdx + andq $0x7fff, %rax + andq $0x8000, %rdx + orq %rdx, %rax + movq %rax, 8(%rcx) + movq %rcx, %rax + ret +#elif defined(_X86_) || defined(__i386__) + movl 24(%esp),%edx + movl 12(%esp),%eax + andl $0x8000,%edx + andl $0x7fff,%eax + orl %edx,%eax + movl %eax,12(%esp) + fldt 4(%esp) + ret +#endif diff --git a/libc/mingw/math/x86/cos.c b/libc/mingw/math/x86/cos.c new file mode 100644 index 000000000..eea812b76 --- /dev/null +++ b/libc/mingw/math/x86/cos.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "cos.def.h" diff --git a/libc/mingw/math/x86/cos.def.h b/libc/mingw/math/x86/cos.def.h new file mode 100644 index 000000000..f082f3740 --- /dev/null +++ b/libc/mingw/math/x86/cos.def.h @@ -0,0 +1,65 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "../complex/complex_internal.h" +#include + +extern long double __cosl_internal (long double); + +__FLT_TYPE +__FLT_ABI(cos) (__FLT_TYPE x) +{ + int x_class = fpclassify (x); + if (x_class == FP_NAN) + { + __FLT_RPT_DOMAIN ("cos", x, 0.0, x); + return x; + } + else if (x_class == FP_INFINITE) + { + __FLT_RPT_DOMAIN ("cos", x, 0.0, __FLT_NAN); + return __FLT_NAN; + } + return (__FLT_TYPE) __cosl_internal ((long double) x); +} diff --git a/libc/mingw/math/x86/cosf.c b/libc/mingw/math/x86/cosf.c new file mode 100644 index 000000000..41e2c774c --- /dev/null +++ b/libc/mingw/math/x86/cosf.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float cosf(float _X) +{ + return ((float)cos((double)_X)); +} diff --git a/libc/mingw/math/x86/cosl.c b/libc/mingw/math/x86/cosl.c new file mode 100644 index 000000000..f798862d3 --- /dev/null +++ b/libc/mingw/math/x86/cosl.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "cos.def.h" diff --git a/libc/mingw/math/x86/cosl_internal.S b/libc/mingw/math/x86/cosl_internal.S new file mode 100644 index 000000000..3c8f60d14 --- /dev/null +++ b/libc/mingw/math/x86/cosl_internal.S @@ -0,0 +1,55 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "cosl_internal.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(__cosl_internal) + .def __MINGW_USYMBOL(__cosl_internal); .scl 2; .type 32; .endef +__MINGW_USYMBOL(__cosl_internal): +#ifdef __x86_64__ + fldt (%rdx) + fcos + fnstsw %ax + testl $0x400,%eax + jz 1f + fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fcos +1: movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldt 4(%esp) + fcos + fnstsw %ax + testl $0x400,%eax + jnz 1f + ret +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fcos + ret +#endif + diff --git a/libc/mingw/math/x86/cossin.c b/libc/mingw/math/x86/cossin.c new file mode 100644 index 000000000..cb3340545 --- /dev/null +++ b/libc/mingw/math/x86/cossin.c @@ -0,0 +1,75 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +void sincos (double __x, double *p_sin, double *p_cos); +void sincosl (long double __x, long double *p_sin, long double *p_cos); +void sincosf (float __x, float *p_sin, float *p_cos); + +void sincos (double __x, double *p_sin, double *p_cos) +{ + long double c, s; + + __asm__ __volatile__ ("fsincos\n\t" + "fnstsw %%ax\n\t" + "testl $0x400, %%eax\n\t" + "jz 1f\n\t" + "fldpi\n\t" + "fadd %%st(0)\n\t" + "fxch %%st(1)\n\t" + "2: fprem1\n\t" + "fnstsw %%ax\n\t" + "testl $0x400, %%eax\n\t" + "jnz 2b\n\t" + "fstp %%st(1)\n\t" + "fsincos\n\t" + "1:" : "=t" (c), "=u" (s) : "0" (__x) : "eax"); + *p_sin = (double) s; + *p_cos = (double) c; +} + +void sincosf (float __x, float *p_sin, float *p_cos) +{ + long double c, s; + + __asm__ __volatile__ ("fsincos\n\t" + "fnstsw %%ax\n\t" + "testl $0x400, %%eax\n\t" + "jz 1f\n\t" + "fldpi\n\t" + "fadd %%st(0)\n\t" + "fxch %%st(1)\n\t" + "2: fprem1\n\t" + "fnstsw %%ax\n\t" + "testl $0x400, %%eax\n\t" + "jnz 2b\n\t" + "fstp %%st(1)\n\t" + "fsincos\n\t" + "1:" : "=t" (c), "=u" (s) : "0" (__x) : "eax"); + *p_sin = (float) s; + *p_cos = (float) c; +} + +void sincosl (long double __x, long double *p_sin, long double *p_cos) +{ + long double c, s; + + __asm__ __volatile__ ("fsincos\n\t" + "fnstsw %%ax\n\t" + "testl $0x400, %%eax\n\t" + "jz 1f\n\t" + "fldpi\n\t" + "fadd %%st(0)\n\t" + "fxch %%st(1)\n\t" + "2: fprem1\n\t" + "fnstsw %%ax\n\t" + "testl $0x400, %%eax\n\t" + "jnz 2b\n\t" + "fstp %%st(1)\n\t" + "fsincos\n\t" + "1:" : "=t" (c), "=u" (s) : "0" (__x) : "eax"); + *p_sin = s; + *p_cos = c; +} diff --git a/libc/mingw/math/x86/exp.c b/libc/mingw/math/x86/exp.c new file mode 100644 index 000000000..5df131af1 --- /dev/null +++ b/libc/mingw/math/x86/exp.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "exp.def.h" diff --git a/libc/mingw/math/x86/exp.def.h b/libc/mingw/math/x86/exp.def.h new file mode 100644 index 000000000..33a176aec --- /dev/null +++ b/libc/mingw/math/x86/exp.def.h @@ -0,0 +1,137 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "../complex/complex_internal.h" +#include + +static long double c0 = 1.44268798828125L; // INV_LN2 +static long double c1 = 7.05260771340735992468e-6L; + +static long double +__expl_internal (long double x) +{ + long double res = 0.0L; + asm volatile ( + "fldl2e\n\t" /* 1 log2(e) */ + "fmul %%st(1),%%st\n\t" /* 1 x log2(e) */ + +#ifdef __x86_64__ + "subq $8, %%rsp\n" + "fnstcw 4(%%rsp)\n" + "movzwl 4(%%rsp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%rsp)\n" + "fldcw (%%rsp)\n" + "frndint\n\t" /* 1 i */ + "fld %%st(1)\n\t" /* 2 x */ + "frndint\n\t" /* 2 xi */ + "fldcw 4(%%rsp)\n" + "addq $8, %%rsp\n" +#else + "push %%eax\n\tsubl $8, %%esp\n" + "fnstcw 4(%%esp)\n" + "movzwl 4(%%esp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%esp)\n" + "fldcw (%%esp)\n" + "frndint\n\t" /* 1 i */ + "fld %%st(1)\n\t" /* 2 x */ + "frndint\n\t" /* 2 xi */ + "fldcw 4(%%esp)\n" + "addl $8, %%esp\n\tpop %%eax\n" +#endif + "fld %%st(1)\n\t" /* 3 i */ + "fldt %2\n\t" /* 4 c0 */ + "fld %%st(2)\n\t" /* 5 xi */ + "fmul %%st(1),%%st\n\t" /* 5 c0 xi */ + "fsubp %%st,%%st(2)\n\t" /* 4 f = c0 xi - i */ + "fld %%st(4)\n\t" /* 5 x */ + "fsub %%st(3),%%st\n\t" /* 5 xf = x - xi */ + "fmulp %%st,%%st(1)\n\t" /* 4 c0 xf */ + "faddp %%st,%%st(1)\n\t" /* 3 f = f + c0 xf */ + "fldt %3\n\t" /* 4 */ + "fmul %%st(4),%%st\n\t" /* 4 c1 * x */ + "faddp %%st,%%st(1)\n\t" /* 3 f = f + c1 * x */ + "f2xm1\n\t" /* 3 2^(fract(x * log2(e))) - 1 */ + "fld1\n\t" /* 4 1.0 */ + "faddp\n\t" /* 3 2^(fract(x * log2(e))) */ + "fstp %%st(1)\n\t" /* 2 */ + "fscale\n\t" /* 2 scale factor is st(1); e^x */ + "fstp %%st(1)\n\t" /* 1 */ + "fstp %%st(1)\n\t" /* 0 */ + : "=t" (res) : "0" (x), "m" (c0), "m" (c1) : "ax", "dx"); + return res; +} + +__FLT_TYPE +__FLT_ABI(exp) (__FLT_TYPE x) +{ + int x_class = fpclassify (x); + if (x_class == FP_NAN) + { + __FLT_RPT_DOMAIN ("exp", x, 0.0, x); + return x; + } + else if (x_class == FP_INFINITE) + { + __FLT_TYPE r = (signbit (x) ? __FLT_CST (0.0) : __FLT_HUGE_VAL); + __FLT_RPT_ERANGE ("exp", x, 0.0, r, signbit (x)); + return r; + } + else if (x_class == FP_ZERO) + { + return __FLT_CST (1.0); + } + else if (x > __FLT_MAXLOG) + { + __FLT_RPT_ERANGE ("exp", x, 0.0, __FLT_HUGE_VAL, 1); + return __FLT_HUGE_VAL; + } + else if (x < __FLT_MINLOG) + { + return __FLT_CST(0.0); + } + else + return (__FLT_TYPE) __expl_internal ((long double) x); +} diff --git a/libc/mingw/math/x86/exp2.S b/libc/mingw/math/x86/exp2.S new file mode 100644 index 000000000..37d4a2b89 --- /dev/null +++ b/libc/mingw/math/x86/exp2.S @@ -0,0 +1,94 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "exp2.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(exp2) + .def __MINGW_USYMBOL(exp2); .scl 2; .type 32; .endef +__MINGW_USYMBOL(exp2): +#ifdef __x86_64__ + subq $24, %rsp + movsd %xmm0,(%rsp) + fldl (%rsp) + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + subq $8, %rsp /* int(x) */ + fnstcw 4(%rsp) + movzwl 4(%rsp), %eax + orb $12, %ah + movw %ax, (%rsp) + fldcw (%rsp) + frndint + fldcw 4(%rsp) + addq $8, %rsp + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + fstpl (%rsp) + movsd (%rsp),%xmm0 + addq $24, %rsp + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: fstpl (%rsp) + movsd (%rsp),%xmm0 + addq $24,%rsp + ret +#else + fldl 4(%esp) +/* I added the following ugly construct because exp(+-Inf) resulted + in NaN. The ugliness results from the bright minds at Intel. + For the i686 the code can be written better. + -- drepper@cygnus.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + subl $8, %esp /* int(x) */ + fnstcw 4(%esp) + movzwl 4(%esp), %eax + orb $12, %ah + movw %ax, (%esp) + fldcw (%esp) + frndint + fldcw 4(%esp) + addl $8, %esp + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: ret +#endif diff --git a/libc/mingw/math/x86/exp2f.S b/libc/mingw/math/x86/exp2f.S new file mode 100644 index 000000000..fa9f19c55 --- /dev/null +++ b/libc/mingw/math/x86/exp2f.S @@ -0,0 +1,94 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "exp2f.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(exp2f) + .def __MINGW_USYMBOL(exp2f); .scl 2; .type 32; .endef +__MINGW_USYMBOL(exp2f): +#ifdef __x86_64__ + subq $24, %rsp + movss %xmm0,(%rsp) + flds (%rsp) + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + subq $8, %rsp /* int(x) */ + fnstcw 4(%rsp) + movzwl 4(%rsp), %eax + orb $12, %ah + movw %ax, (%rsp) + fldcw (%rsp) + frndint + fldcw 4(%rsp) + addq $8, %rsp + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + fstps (%rsp) + movss (%rsp),%xmm0 + addq $24, %rsp + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: fstps (%rsp) + movss (%rsp),%xmm0 + addq $24, %rsp + ret +#else + flds 4(%esp) +/* I added the following ugly construct because exp(+-Inf) resulted + in NaN. The ugliness results from the bright minds at Intel. + For the i686 the code can be written better. + -- drepper@cygnus.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + subl $8, %esp /* int(x) */ + fnstcw 4(%esp) + movzwl 4(%esp), %eax + orb $12, %ah + movw %ax, (%esp) + fldcw (%esp) + frndint + fldcw 4(%esp) + addl $8, %esp + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: ret +#endif diff --git a/libc/mingw/math/x86/exp2l.S b/libc/mingw/math/x86/exp2l.S new file mode 100644 index 000000000..2e58c37b8 --- /dev/null +++ b/libc/mingw/math/x86/exp2l.S @@ -0,0 +1,92 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "exp2l.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(exp2l) + .def __MINGW_USYMBOL(exp2l); .scl 2; .type 32; .endef +__MINGW_USYMBOL(exp2l): +#ifdef __x86_64__ + fldt (%rdx) + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + subq $8, %rsp /* int(x) */ + fnstcw 4(%rsp) + movzwl 4(%rsp), %eax + orb $12, %ah + movw %ax, (%rsp) + fldcw (%rsp) + frndint + fldcw 4(%rsp) + addq $8, %rsp + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldt 4(%esp) +/* I added the following ugly construct because exp(+-Inf) resulted + in NaN. The ugliness results from the bright minds at Intel. + For the i686 the code can be written better. + -- drepper@cygnus.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + fld %st + subl $8, %esp /* int(x) */ + fnstcw 4(%esp) + movzwl 4(%esp), %eax + orb $12, %ah + movw %ax, (%esp) + fldcw (%esp) + frndint + fldcw 4(%esp) + addl $8, %esp + fsubr %st,%st(1) /* fract(x) */ + fxch + f2xm1 /* 2^(fract(x)) - 1 */ + fld1 + faddp /* 2^(fract(x)) */ + fscale /* e^x */ + fstp %st(1) + ret + +1: testl $0x200, %eax /* Test sign. */ + jz 2f /* If positive, jump. */ + fstp %st + fldz /* Set result to 0. */ +2: ret +#endif diff --git a/libc/mingw/math/x86/expl.c b/libc/mingw/math/x86/expl.c new file mode 100644 index 000000000..7f4be6239 --- /dev/null +++ b/libc/mingw/math/x86/expl.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "exp.def.h" diff --git a/libc/mingw/math/x86/expm1.c b/libc/mingw/math/x86/expm1.c new file mode 100644 index 000000000..65fd64bc5 --- /dev/null +++ b/libc/mingw/math/x86/expm1.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "expm1.def.h" diff --git a/libc/mingw/math/x86/expm1.def.h b/libc/mingw/math/x86/expm1.def.h new file mode 100644 index 000000000..934603164 --- /dev/null +++ b/libc/mingw/math/x86/expm1.def.h @@ -0,0 +1,72 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "../complex/complex_internal.h" +#include + +__FLT_TYPE +__FLT_ABI(expm1) (__FLT_TYPE x) +{ + int x_class = fpclassify (x); + if (x_class == FP_NAN) + { + __FLT_RPT_DOMAIN ("expm1", x, 0.0, x); + return x; + } + else if (x_class == FP_INFINITE) + { + return (signbit (x) ? -__FLT_CST(1.0) : __FLT_HUGE_VAL); + } + else if (x_class == FP_ZERO) + { + return x; + } + if (__FLT_ABI (fabs) (x) < __FLT_LOGE2) + { + x /= __FLT_LOGE2; + __asm__ __volatile__ ("f2xm1" : "=t" (x) : "0" (x)); + return x; + } + return __FLT_ABI (exp) (x) - __FLT_CST (1.0); +} diff --git a/libc/mingw/math/x86/expm1f.c b/libc/mingw/math/x86/expm1f.c new file mode 100644 index 000000000..ab80717eb --- /dev/null +++ b/libc/mingw/math/x86/expm1f.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_FLOAT 1 +#include "expm1.def.h" diff --git a/libc/mingw/math/x86/expm1l.c b/libc/mingw/math/x86/expm1l.c new file mode 100644 index 000000000..625fbb1d7 --- /dev/null +++ b/libc/mingw/math/x86/expm1l.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "expm1.def.h" diff --git a/libc/mingw/math/x86/fastmath.h b/libc/mingw/math/x86/fastmath.h new file mode 100644 index 000000000..a6bb467c2 --- /dev/null +++ b/libc/mingw/math/x86/fastmath.h @@ -0,0 +1,120 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef _MINGWEX_FASTMATH_H_ +#define _MINGWEX_FASTMATH_H_ + +/* Fast math inlines + No range or domain checks. No setting of errno. No tweaks to + protect precision near range limits. */ + +/* For now this is an internal header with just the functions that + are currently used in building libmingwex.a math components */ + +/* FIXME: We really should get rid of the code duplication using euther + C++ templates or tgmath-type macros. */ + +static __inline__ double __fast_sqrt (double x) +{ + double res; + asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); + return res; +} + +static __inline__ long double __fast_sqrtl (long double x) +{ + long double res; + asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); + return res; +} + +static __inline__ float __fast_sqrtf (float x) +{ + float res; + asm __volatile__ ("fsqrt" : "=t" (res) : "0" (x)); + return res; +} + + +static __inline__ double __fast_log (double x) +{ + double res; + asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} + +static __inline__ long double __fast_logl (long double x) +{ + long double res; + asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} + + +static __inline__ float __fast_logf (float x) +{ + float res; + asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2x" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} + +static __inline__ double __fast_log1p (double x) +{ + double res; + /* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ + if (fabs (x) >= 1.0 - 0.5 * 1.41421356237309504880) + res = __fast_log (1.0 + x); + else + asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2xp1" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} + +static __inline__ long double __fast_log1pl (long double x) +{ + long double res; + /* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ + if (fabsl (x) >= 1.0L - 0.5L * 1.41421356237309504880L) + res = __fast_logl (1.0L + x); + else + asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2xp1" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} + +static __inline__ float __fast_log1pf (float x) +{ + float res; + /* fyl2xp1 accurate only for |x| <= 1.0 - 0.5 * sqrt (2.0) */ + if (fabsf (x) >= 1.0 - 0.5 * 1.41421356237309504880) + res = __fast_logf (1.0 + x); + else + asm __volatile__ + ("fldln2\n\t" + "fxch\n\t" + "fyl2xp1" + : "=t" (res) : "0" (x) : "st(1)"); + return res; +} + +#endif diff --git a/libc/mingw/math/x86/floor.S b/libc/mingw/math/x86/floor.S new file mode 100644 index 000000000..6e436a873 --- /dev/null +++ b/libc/mingw/math/x86/floor.S @@ -0,0 +1,167 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "floor.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(floor) + .def __MINGW_USYMBOL(floor); .scl 2; .type 32; .endef +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(floor) +#endif +__MINGW_USYMBOL(floor): +#if defined(_AMD64_) || defined(__x86_64__) + pushq %rbx + .seh_pushreg %rbx + subq $16, %rsp + .seh_stackalloc 16 + .seh_endprologue + movsd %xmm0, 8(%rsp) + movq 8(%rsp), %r9 + movq %r9, %rdx + movl %r9d, %r10d + shrq $32, %rdx + movl %edx, %eax + movl %edx, %r11d + sarl $20, %eax + andl $2047, %eax + leal -1023(%rax), %r8d + cmpl $51, %r8d + jle .L2 + cmpl $1024, %r8d + je .L27 +.L3: + addq $16, %rsp + popq %rbx + ret + .p2align 4,,10 +.L2: + cmpl $19, %r8d + jg .L4 + testl %r8d, %r8d + js .L28 + movl $1048575, %eax + movl %r8d, %ecx + shrl %cl, %eax + testl %r9d, %r9d + jne .L8 + testl %edx, %eax + je .L3 +.L8: + movsd .hugeval(%rip), %xmm1 + xorpd %xmm2, %xmm2 + addsd %xmm0, %xmm1 + ucomisd %xmm1, %xmm2 + jae .L3 + xorl %r9d, %r9d + testl %edx, %edx + jns .L9 + movl $1048576, %r9d + movl %r8d, %ecx + sarl %cl, %r9d +.L9: + addl %r9d, %edx + notl %eax + andl %edx, %eax + salq $32, %rax + movq %rax, 8(%rsp) + movsd 8(%rsp), %xmm0 + addq $16, %rsp + popq %rbx + ret + .p2align 4,,10 +.L4: + leal -1043(%rax), %ecx + movl $-1, %ebx + shrl %cl, %ebx + testl %r9d, %ebx + je .L3 + movsd .hugeval(%rip), %xmm1 + xorpd %xmm2, %xmm2 + addsd %xmm0, %xmm1 + ucomisd %xmm1, %xmm2 + jae .L3 + testl %edx, %edx + js .L29 +.L11: + notl %ebx + salq $32, %r11 + andl %ebx, %r10d + orq %r10, %r11 + movq %r11, 8(%rsp) + movsd 8(%rsp), %xmm0 + addq $16, %rsp + popq %rbx + ret + .p2align 4,,10 +.L27: + addsd %xmm0, %xmm0 + addq $16, %rsp + popq %rbx + ret + .p2align 4,,10 +.L28: + movsd .hugeval(%rip), %xmm2 + xorpd %xmm1, %xmm1 + addsd %xmm0, %xmm2 + ucomisd %xmm1, %xmm2 + jbe .L3 + testl %edx, %edx + js .L7 + movapd %xmm1, %xmm0 + jmp .L3 + .p2align 4,,10 +.L7: + andl $2147483647, %edx + orl %r9d, %edx + je .L3 + movabsq $-4616189618054758400, %rax + movq %rax, 8(%rsp) + movsd 8(%rsp), %xmm0 + jmp .L3 + .p2align 4,,10 +.L29: + cmpl $20, %r8d + je .L25 + movl $1075, %ecx + movl $1, %r10d + subl %eax, %ecx + sall %cl, %r10d + addl %r9d, %r10d + jae .L11 +.L25: + leal 1(%rdx), %r11d + jmp .L11 + .seh_endproc + + .section .rdata,"dr" + .align 8 +.hugeval: + .long -2013235812 + .long 2117592124 +#elif defined(_X86_) || defined(__i386__) + fldl 4(%esp) + subl $8,%esp + + fstcw 4(%esp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x400,%edx /* round towards -oo */ + orl 4(%esp),%edx + andl $0xf7ff,%edx + movl %edx,(%esp) + fldcw (%esp) /* load modified control word */ + + frndint /* round */ + + fldcw 4(%esp) /* restore original control word */ + + addl $8,%esp + ret +#endif diff --git a/libc/mingw/math/x86/floorf.S b/libc/mingw/math/x86/floorf.S new file mode 100644 index 000000000..c6226f82b --- /dev/null +++ b/libc/mingw/math/x86/floorf.S @@ -0,0 +1,51 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + #include <_mingw_mac.h> + + .file "floorf.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(floorf) + .def __MINGW_USYMBOL(floorf); .scl 2; .type 32; .endef +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(floorf) +#endif +__MINGW_USYMBOL(floorf): +#if defined(_AMD64_) || defined(__x86_64__) + subq $40, %rsp + .seh_stackalloc 40 + .seh_endprologue + unpcklps %xmm0, %xmm0 + cvtps2pd %xmm0, %xmm0 + call floor + unpcklpd %xmm0, %xmm0 + cvtpd2ps %xmm0, %xmm0 + addq $40, %rsp + ret + .seh_endproc + .def __MINGW_USYMBOL(floor); .scl 2; .type 32; .endef +#elif defined(_X86_) || defined(__i386__) + flds 4(%esp) + subl $8,%esp + + fstcw 4(%esp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x400,%edx /* round towards -oo */ + orl 4(%esp),%edx + andl $0xf7ff,%edx + movl %edx,(%esp) + fldcw (%esp) /* load modified control word */ + + frndint /* round */ + + fldcw 4(%esp) /* restore original control word */ + + addl $8,%esp + ret +#endif diff --git a/libc/mingw/math/x86/floorl.S b/libc/mingw/math/x86/floorl.S new file mode 100644 index 000000000..6a08d590a --- /dev/null +++ b/libc/mingw/math/x86/floorl.S @@ -0,0 +1,63 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "floorl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + .globl __MINGW_USYMBOL(floorl) + .def __MINGW_USYMBOL(floorl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(floorl): +#if defined(_AMD64_) || defined(__x86_64__) + fldt (%rdx) + subq $24,%rsp + + fstcw 8(%rsp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x400,%edx /* round towards -oo */ + orl 8(%rsp),%edx + andl $0xf7ff,%edx + movl %edx,(%rsp) + fldcw (%rsp) /* load modified control word */ + + frndint /* round */ + + fldcw 8(%rsp) /* restore original control word */ + + addq $24,%rsp + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#elif defined(_X86_) || defined(__i386__) + fldt 4(%esp) + subl $8,%esp + + fstcw 4(%esp) /* store fpu control word */ + + /* We use here %edx although only the low 1 bits are defined. + But none of the operations should care and they are faster + than the 16 bit operations. */ + movl $0x400,%edx /* round towards -oo */ + orl 4(%esp),%edx + andl $0xf7ff,%edx + movl %edx,(%esp) + fldcw (%esp) /* load modified control word */ + + frndint /* round */ + + fldcw 4(%esp) /* restore original control word */ + + addl $8,%esp + ret +#endif diff --git a/libc/mingw/math/x86/fmod.c b/libc/mingw/math/x86/fmod.c new file mode 100644 index 000000000..5764db035 --- /dev/null +++ b/libc/mingw/math/x86/fmod.c @@ -0,0 +1,21 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +double fmod (double x, double y); + +double +fmod (double x, double y) +{ + double res = 0.0; + + asm volatile ( + "1:\tfprem\n\t" + "fstsw %%ax\n\t" + "sahf\n\t" + "jp 1b\n\t" + "fstp %%st(1)" + : "=t" (res) : "0" (x), "u" (y) : "ax", "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/fmodf.c b/libc/mingw/math/x86/fmodf.c new file mode 100644 index 000000000..45106adaa --- /dev/null +++ b/libc/mingw/math/x86/fmodf.c @@ -0,0 +1,29 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Public domain. + * + * Adapted for float type by Danny Smith + * . + */ + +#include + +float +fmodf (float x, float y) +{ + float res = 0.0F; + + asm volatile ( + "1:\tfprem\n\t" + "fstsw %%ax\n\t" + "sahf\n\t" + "jp 1b\n\t" + "fstp %%st(1)" + : "=t" (res) : "0" (x), "u" (y) : "ax", "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/fmodl.c b/libc/mingw/math/x86/fmodl.c new file mode 100644 index 000000000..462b6fa79 --- /dev/null +++ b/libc/mingw/math/x86/fmodl.c @@ -0,0 +1,21 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +long double fmodl (long double x, long double y); + +long double +fmodl (long double x, long double y) +{ + long double res = 0.0L; + + asm volatile ( + "1:\tfprem\n\t" + "fstsw %%ax\n\t" + "sahf\n\t" + "jp 1b\n\t" + "fstp %%st(1)" + : "=t" (res) : "0" (x), "u" (y) : "ax", "st(1)"); + return res; +} diff --git a/libc/mingw/math/x86/frexpl.S b/libc/mingw/math/x86/frexpl.S new file mode 100644 index 000000000..f9fcc6be1 --- /dev/null +++ b/libc/mingw/math/x86/frexpl.S @@ -0,0 +1,130 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + +/* + * frexpl(long double x, int* expnt) extracts the exponent from x. + * It returns an integer power of two to expnt and the significand + * between 0.5 and 1 to y. Thus x = y * 2**expn. + */ +#ifdef __x86_64__ + .align 8 +#else + .align 2 +#endif +.globl __MINGW_USYMBOL(frexpl) +__MINGW_USYMBOL(frexpl): +#ifdef __x86_64__ + pushq %rbp + movq %rsp,%rbp + subq $48,%rsp + pushq %rsi + fldt (%rdx) + movq %rcx,%r9 + fld %st(0) + fstpt -12(%rbp) + leaq -4(%rbp),%rcx + movw -4(%rbp),%dx + andl $32767,%edx + jne L25 + fldz + fucompp + fnstsw %ax + andb $68,%ah + xorb $64,%ah + jne L21 + movl $0,(%r8) + fldz + jmp L24 + .align 4,0x90 + .align 4,0x90 +L21: + fldt -12(%rbp) + fadd %st(0),%st + fstpt -12(%rbp) + decl %edx + movw (%rcx),%si + andl $32767,%esi + jne L22 + cmpl $-66,%edx + jg L21 +L22: + add %esi,%edx + jmp L19 + .align 2,0x90 +L25: + fstp %st(0) +L19: + addl $-16382,%edx + movl %edx,(%r8) + movw (%rcx),%ax + andl $-32768,%eax + orl $16382,%eax + movw %ax,(%rcx) + fldt -12(%rbp) +L24: + popq %rsi + movq %r9,%rax + movq $0,8(%r9) + fstpt (%r9) + leave + ret +#else + pushl %ebp + movl %esp,%ebp + subl $24,%esp + pushl %esi + pushl %ebx + fldt 8(%ebp) + movl 20(%ebp),%ebx + fld %st(0) + fstpt -12(%ebp) + leal -4(%ebp),%ecx + movw -4(%ebp),%dx + andl $32767,%edx + jne L25 + fldz + fucompp + fnstsw %ax + andb $68,%ah + xorb $64,%ah + jne L21 + movl $0,(%ebx) + fldz + jmp L24 + .align 2,0x90 + .align 2,0x90 +L21: + fldt -12(%ebp) + fadd %st(0),%st + fstpt -12(%ebp) + decl %edx + movw (%ecx),%si + andl $32767,%esi + jne L22 + cmpl $-66,%edx + jg L21 +L22: + addl %esi,%edx + jmp L19 + .align 2,0x90 +L25: + fstp %st(0) +L19: + addl $-16382,%edx + movl %edx,(%ebx) + movw (%ecx),%ax + andl $-32768,%eax + orl $16382,%eax + movw %ax,(%ecx) + fldt -12(%ebp) +L24: + leal -32(%ebp),%esp + popl %ebx + popl %esi + leave + ret +#endif diff --git a/libc/mingw/math/x86/fucom.c b/libc/mingw/math/x86/fucom.c new file mode 100644 index 000000000..722af842d --- /dev/null +++ b/libc/mingw/math/x86/fucom.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +int __fp_unordered_compare (long double x, long double y); + +int +__fp_unordered_compare (long double x, long double y){ + unsigned short retval; + __asm__ __volatile__ ( + "fucom %%st(1);" + "fnstsw;" + : "=a" (retval) + : "t" (x), "u" (y) + ); + return retval; +} diff --git a/libc/mingw/math/x86/ilogb.S b/libc/mingw/math/x86/ilogb.S new file mode 100644 index 000000000..c54f350d0 --- /dev/null +++ b/libc/mingw/math/x86/ilogb.S @@ -0,0 +1,143 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ilogb.S" + .text + .p2align 4,,15 +.globl __MINGW_USYMBOL(ilogb) + .def __MINGW_USYMBOL(ilogb); .scl 2; .type 32; .endef +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(ilogb) +#endif +__MINGW_USYMBOL(ilogb): +#ifdef __x86_64__ +/* Generated code by: +int +ilogb (double x) +{ + __mingw_dbl_type_t hlp; + int hx, lx, ix; + + hlp.x = x; + hx = hpl.lh.high & 0x7fffffff; + if (hx < 0x100000) + { + lx = hlp.lh.low; + if ((hx | lx) == 0) + return 0x80000000; // ilogb(0) = FP_ILOGB0 + // subnormal x + if (hx == 0) + { + for (ix = -1043; lx > 0; lx <<= 1) + ix -=1; + } + else + { + for (ix = -1022,hx <<= 11; hx > 0; hx <<= 1) + ix -=1; + } + return ix; + } + if (hx < 0x7ff00000) + return (hx >> 20) - 1023; + lx = hlp.lh.low; + if (((hx ^ 0x7ff00000) | lx) == 0) + return 0x7fffffff; + return 0x80000000; +} */ + subq $24, %rsp + .seh_stackalloc 24 + .seh_endprologue + movsd %xmm0, 8(%rsp) + movq 8(%rsp), %rdx + shrq $32, %rdx + andl $2147483647, %edx + cmpl $1048575, %edx + jg .L2 + movq 8(%rsp), %rcx + movl %edx, %eax + orl %ecx, %eax + je .L8 + testl %edx, %edx + jne .L4 + testl %ecx, %ecx + movl %ecx, %edx + movl $-1043, %eax + jle .L3 + .p2align 4,,10 +.L5: + addl %edx, %edx + subl $1, %eax + testl %edx, %edx + jg .L5 + addq $24, %rsp + ret + .p2align 4,,10 +.L2: + cmpl $2146435071, %edx + jle .L13 + movsd %xmm0, 8(%rsp) + movq 8(%rsp), %rax + xorl $2146435072, %edx + orl %eax, %edx + cmpl $1, %edx + sbbl %eax, %eax + addl $-2147483648, %eax +.L3: + addq $24, %rsp + ret + .p2align 4,,10 +.L4: + sall $11, %edx + movl $-1022, %eax + testl %edx, %edx + jle .L3 + .p2align 4,,10 +.L6: + addl %edx, %edx + subl $1, %eax + testl %edx, %edx + jg .L6 + addq $24, %rsp + ret + .p2align 4,,10 +.L13: + sarl $20, %edx + leal -1023(%rdx), %eax + addq $24, %rsp + ret +.L8: + movl $-2147483648, %eax + jmp .L3 + .seh_endproc +#else + + fldl 4(%esp) +/* I added the following ugly construct because ilogb(+-Inf) is + required to return INT_MAX in ISO C99. + -- jakub@redhat.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + + fxtract + pushl %eax + fstp %st + + fistpl (%esp) + fwait + popl %eax + + ret + +1: fstp %st + movl $0x7fffffff, %eax + ret +#endif diff --git a/libc/mingw/math/x86/ilogbf.S b/libc/mingw/math/x86/ilogbf.S new file mode 100644 index 000000000..8b2465564 --- /dev/null +++ b/libc/mingw/math/x86/ilogbf.S @@ -0,0 +1,109 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ilogbf.S" + .text + .p2align 4,,15 +.globl __MINGW_USYMBOL(ilogbf) + .def __MINGW_USYMBOL(ilogbf); .scl 2; .type 32; .endef +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(ilogbf) +#endif +__MINGW_USYMBOL(ilogbf): +#ifdef __x86_64__ +/* generated code for: +int +ilogbf (float x) +{ + __mingw_flt_type_t hlp; + int hx, ix; + + hlp.x = x; + hx = (int) hlp.val & 0x7fffffff; + if (hx < 0x800000) + { + if (hx == 0) + return 0x80000000; // ilogb(0) = FP_ILOGB0 + for (ix = -126, hx <<= 8; hx > 0; hx <<= 1) + ix -= 1; + return ix; + } + if (hx < 0x7f800000) + return (hx >> 23) - 127; + if (hx == 0x7f800000) + return 0x7fffffff; + return 0x80000000; +} */ + subq $24, %rsp + .seh_stackalloc 24 + .seh_endprologue + movss %xmm0, 12(%rsp) + movl 12(%rsp), %edx + andl $2147483647, %edx + cmpl $8388607, %edx + jg .L2 + testl %edx, %edx + je .L6 + sall $8, %edx + movl $-126, %eax + testl %edx, %edx + jle .L3 + .p2align 4,,10 +.L4: + addl %edx, %edx + subl $1, %eax + testl %edx, %edx + jg .L4 +.L3: + addq $24, %rsp + ret + .p2align 4,,10 +.L2: + cmpl $2139095039, %edx + jle .L10 + cmpl $2139095040, %edx + movl $2147483647, %eax + movl $-2147483648, %edx + cmovne %edx, %eax + addq $24, %rsp + ret + .p2align 4,,10 +.L10: + sarl $23, %edx + leal -127(%rdx), %eax + addq $24, %rsp + ret +.L6: + movl $-2147483648, %eax + jmp .L3 + .seh_endproc +#else + flds 4(%esp) +/* I added the following ugly construct because ilogb(+-Inf) is + required to return INT_MAX in ISO C99. + -- jakub@redhat.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + + fxtract + pushl %eax + fstp %st + + fistpl (%esp) + fwait + popl %eax + + ret + +1: fstp %st + movl $0x7fffffff, %eax + ret +#endif diff --git a/libc/mingw/math/x86/ilogbl.S b/libc/mingw/math/x86/ilogbl.S new file mode 100644 index 000000000..f68082ce6 --- /dev/null +++ b/libc/mingw/math/x86/ilogbl.S @@ -0,0 +1,65 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "ilogbl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(ilogbl) + .def __MINGW_USYMBOL(ilogbl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(ilogbl): +#ifdef __x86_64__ + fldt (%rcx) + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + + fxtract + pushq %rax + fstp %st + + fistpl (%rsp) + fwait + popq %rax + + ret + +1: fstp %st + movl $0x7fffffff, %eax + ret +#else + fldt 4(%esp) +/* I added the following ugly construct because ilogb(+-Inf) is + required to return INT_MAX in ISO C99. + -- jakub@redhat.com. */ + fxam /* Is NaN or +-Inf? */ + fstsw %ax + movb $0x45, %dh + andb %ah, %dh + cmpb $0x05, %dh + je 1f /* Is +-Inf, jump. */ + + fxtract + pushl %eax + fstp %st + + fistpl (%esp) + fwait + popl %eax + + ret + +1: fstp %st + movl $0x7fffffff, %eax + ret +#endif diff --git a/libc/mingw/math/x86/internal_logl.S b/libc/mingw/math/x86/internal_logl.S new file mode 100644 index 000000000..f8a075774 --- /dev/null +++ b/libc/mingw/math/x86/internal_logl.S @@ -0,0 +1,66 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "internal_logl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +one: .double 1.0 + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ +limit: .double 0.29 + +.globl __MINGW_USYMBOL(__logl_internal) + .def __MINGW_USYMBOL(__logl_internal); .scl 2; .type 32; .endef +__MINGW_USYMBOL(__logl_internal): +#ifdef __x86_64__ + fldln2 // log(2) + fldt (%rdx) // x : log(2) + fld %st // x : x : log(2) + fsubl one(%rip) // x-1 : x : log(2) + fld %st // x-1 : x-1 : x : log(2) + fabs // |x-1| : x-1 : x : log(2) + fcompl limit(%rip) // x-1 : x : log(2) + fnstsw // x-1 : x : log(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log(2) + fyl2xp1 // log(x) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +2: fstp %st(0) // x : log(2) + fyl2x // log(x) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldln2 // log(2) + fldt 4(%esp) // x : log(2) + fld %st // x : x : log(2) + fsubl one // x-1 : x : log(2) + fld %st // x-1 : x-1 : x : log(2) + fabs // |x-1| : x-1 : x : log(2) + fcompl limit // x-1 : x : log(2) + fnstsw // x-1 : x : log(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log(2) + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : log(2) + fyl2x // log(x) + ret +#endif diff --git a/libc/mingw/math/x86/ldexp.c b/libc/mingw/math/x86/ldexp.c new file mode 100644 index 000000000..59917ac8d --- /dev/null +++ b/libc/mingw/math/x86/ldexp.c @@ -0,0 +1,23 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +double ldexp(double x, int expn) +{ + double res = 0.0; + if (!isfinite (x) || x == 0.0) + return x; + + __asm__ __volatile__ ("fscale" + : "=t" (res) + : "0" (x), "u" ((double) expn)); + + if (!isfinite (res) || res == 0.0L) + errno = ERANGE; + + return res; +} diff --git a/libc/mingw/math/x86/ldexpl.c b/libc/mingw/math/x86/ldexpl.c new file mode 100644 index 000000000..fde31a23c --- /dev/null +++ b/libc/mingw/math/x86/ldexpl.c @@ -0,0 +1,23 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +long double ldexpl(long double x, int expn) +{ + long double res = 0.0L; + if (!isfinite (x) || x == 0.0L) + return x; + + __asm__ __volatile__ ("fscale" + : "=t" (res) + : "0" (x), "u" ((long double) expn)); + + if (!isfinite (res) || res == 0.0L) + errno = ERANGE; + + return res; +} diff --git a/libc/mingw/math/x86/log.c b/libc/mingw/math/x86/log.c new file mode 100644 index 000000000..aa74445b7 --- /dev/null +++ b/libc/mingw/math/x86/log.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "log.def.h" diff --git a/libc/mingw/math/x86/log.def.h b/libc/mingw/math/x86/log.def.h new file mode 100644 index 000000000..9428f90ce --- /dev/null +++ b/libc/mingw/math/x86/log.def.h @@ -0,0 +1,69 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "../complex/complex_internal.h" +#include + +extern long double __cdecl __logl_internal (long double); + +__FLT_TYPE __cdecl +__FLT_ABI(log) (__FLT_TYPE x) +{ + int x_class = fpclassify (x); + if (x_class == FP_ZERO) + { + __FLT_RPT_ERANGE ("log", x, 0.0, -__FLT_HUGE_VAL, 1); + return -__FLT_HUGE_VAL; + } + else if (signbit (x)) + { + __FLT_RPT_DOMAIN ("log", x, 0.0, __FLT_NAN); + return __FLT_NAN; + } + else if (x_class == FP_INFINITE) + return __FLT_HUGE_VAL; + else if (x_class == FP_NAN) + return __FLT_NAN; + return (__FLT_TYPE) __logl_internal ((long double) x); +} diff --git a/libc/mingw/math/x86/log10l.S b/libc/mingw/math/x86/log10l.S new file mode 100644 index 000000000..33d45a3a8 --- /dev/null +++ b/libc/mingw/math/x86/log10l.S @@ -0,0 +1,93 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "log10l.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +one: .double 1.0 + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ +limit: .double 0.29 + + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(log10l) + .def __MINGW_USYMBOL(log10l); .scl 2; .type 32; .endef +__MINGW_USYMBOL(log10l): +#ifdef __x86_64__ + fldlg2 // log10(2) + fldt (%rdx) // x : log10(2) + fxam + fnstsw + fld %st // x : x : log10(2) + sahf + jc 3f // in case x is NaN or ±Inf +4: fsubl one(%rip) // x-1 : x : log10(2) + fld %st // x-1 : x-1 : x : log10(2) + fabs // |x-1| : x-1 : x : log10(2) + fcompl limit(%rip) // x-1 : x : log10(2) + fnstsw // x-1 : x : log10(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log10(2) + fyl2xp1 // log10(x) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +2: fstp %st(0) // x : log10(2) + fyl2x // log10(x) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldlg2 // log10(2) + fldt 4(%esp) // x : log10(2) + fxam + fnstsw + fld %st // x : x : log10(2) + sahf + jc 3f // in case x is NaN or ±Inf +4: fsubl one // x-1 : x : log10(2) + fld %st // x-1 : x-1 : x : log10(2) + fabs // |x-1| : x-1 : x : log10(2) + fcompl limit // x-1 : x : log10(2) + fnstsw // x-1 : x : log10(2) + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : log10(2) + fyl2xp1 // log10(x) + ret + +2: fstp %st(0) // x : log10(2) + fyl2x // log10(x) + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/log1p.S b/libc/mingw/math/x86/log1p.S new file mode 100644 index 000000000..c1a1d2fa6 --- /dev/null +++ b/libc/mingw/math/x86/log1p.S @@ -0,0 +1,85 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "log1p.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + /* The fyl2xp1 can only be used for values in + -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 + 0.29 is a safe value. + */ +limit: .double 0.29 +one: .double 1.0 +/* + * Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, + * otherwise fyl2x with the needed extra computation. + */ +.globl __MINGW_USYMBOL(log1p) + .def __MINGW_USYMBOL(log1p); .scl 2; .type 32; .endef +__MINGW_USYMBOL(log1p): +#ifdef __x86_64__ + movsd %xmm0,-16(%rsp) + fldln2 + fldl -16(%rsp) + fxam + fnstsw + fld %st + sahf + jc 3f // in case x is NaN or ±Inf + +4: fabs + fcompl limit(%rip) + fnstsw + sahf + jc 2f + faddl one(%rip) + fyl2x + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret + +2: fyl2xp1 + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret +#else + fldln2 + fldl 4(%esp) + fxam + fnstsw + fld %st + sahf + jc 3f // in case x is NaN or ±Inf + +4: fabs + fcompl limit + fnstsw + sahf + jc 2f + faddl one + fyl2x + ret + +2: fyl2xp1 + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/log1pf.S b/libc/mingw/math/x86/log1pf.S new file mode 100644 index 000000000..259e8a8ec --- /dev/null +++ b/libc/mingw/math/x86/log1pf.S @@ -0,0 +1,85 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "log1pf.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + /* The fyl2xp1 can only be used for values in + -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 + 0.29 is a safe value. + */ +limit: .float 0.29 +one: .float 1.0 +/* + * Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, + * otherwise fyl2x with the needed extra computation. + */ +.globl __MINGW_USYMBOL(log1pf) + .def __MINGW_USYMBOL(log1pf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(log1pf): +#ifdef __x86_64__ + movss %xmm0,-12(%rsp) + fldln2 + flds -12(%rsp) + fxam + fnstsw + fld %st + sahf + jc 3f // in case x is NaN or ±Inf + +4: fabs + fcomps limit(%rip) + fnstsw + sahf + jc 2f + fadds one(%rip) + fyl2x + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret + +2: fyl2xp1 + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret +#else + fldln2 + flds 4(%esp) + fxam + fnstsw + fld %st + sahf + jc 3f // in case x is NaN or ±Inf + +4: fabs + fcomps limit + fnstsw + sahf + jc 2f + fadds one + fyl2x + ret + +2: fyl2xp1 + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/log1pl.S b/libc/mingw/math/x86/log1pl.S new file mode 100644 index 000000000..a56bcf4ec --- /dev/null +++ b/libc/mingw/math/x86/log1pl.S @@ -0,0 +1,102 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "log1pl.S" + .text + /* The fyl2xp1 can only be used for values in + -1 + sqrt(2) / 2 <= x <= 1 - sqrt(2) / 2 + 0.29 is a safe value. + */ + + /* Only gcc understands the .tfloat type + The series of .long below represents + limit: .tfloat 0.29 + */ + .align 16 +limit: + .long 2920577761 + .long 2491081031 + .long 16381 +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + /* Please note: we use a double value here. Since 1.0 has + an exact representation this does not effect the accuracy + but it helps to optimize the code. */ +one: .double 1.0 + +/* + * Use the fyl2xp1 function when the argument is in the range -0.29 to 0.29, + * otherwise fyl2x with the needed extra computation. + */ +.globl __MINGW_USYMBOL(log1pl) + .def __MINGW_USYMBOL(log1pl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(log1pl): +#ifdef __x86_64__ + fldln2 + fldt (%rdx) + fxam + fnstsw + fld %st + sahf + jc 3f // in case x is NaN or ±Inf +4: + fabs + fldt limit(%rip) + fcompp + fnstsw + sahf + jnc 2f + faddl one(%rip) + fyl2x + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +2: fyl2xp1 + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldln2 + fldt 4(%esp) + fxam + fnstsw + fld %st + sahf + jc 3f // in case x is NaN or ±Inf +4: + fabs + fldt limit + fcompp + fnstsw + sahf + jnc 2f + faddl one + fyl2x + ret + +2: fyl2xp1 + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/log2.S b/libc/mingw/math/x86/log2.S new file mode 100644 index 000000000..54eecf753 --- /dev/null +++ b/libc/mingw/math/x86/log2.S @@ -0,0 +1,85 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "log2.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +one: .double 1.0 + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ +limit: .double 0.29 + +.globl __MINGW_USYMBOL(log2) + .def __MINGW_USYMBOL(log2); .scl 2; .type 32; .endef +__MINGW_USYMBOL(log2): +#ifdef __x86_64__ + movsd %xmm0,-16(%rsp) + fldl one(%rip) + fldl -16(%rsp) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + sahf + jc 3f // in case x is NaN or ±Inf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl limit(%rip) // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret +#else + fldl one + fldl 4(%esp) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + sahf + jc 3f // in case x is NaN or ±Inf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl limit // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/log2f.S b/libc/mingw/math/x86/log2f.S new file mode 100644 index 000000000..5b01d15ef --- /dev/null +++ b/libc/mingw/math/x86/log2f.S @@ -0,0 +1,85 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "log2f.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +one: .double 1.0 + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ +limit: .double 0.29 + +.globl __MINGW_USYMBOL(log2f) + .def __MINGW_USYMBOL(log2f); .scl 2; .type 32; .endef +__MINGW_USYMBOL(log2f): +#ifdef __x86_64__ + movss %xmm0,-12(%rsp) + fldl one(%rip) + flds -12(%rsp) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + sahf + jc 3f // in case x is NaN or ±Inf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl limit(%rip) // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret +#else + fldl one + flds 4(%esp) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + sahf + jc 3f // in case x is NaN or ±Inf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl limit // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/log2l.S b/libc/mingw/math/x86/log2l.S new file mode 100644 index 000000000..771cd8ae4 --- /dev/null +++ b/libc/mingw/math/x86/log2l.S @@ -0,0 +1,87 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "log2l.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +one: .double 1.0 + /* It is not important that this constant is precise. It is only + a value which is known to be on the safe side for using the + fyl2xp1 instruction. */ +limit: .double 0.29 + +.globl __MINGW_USYMBOL(log2l) + .def __MINGW_USYMBOL(log2l); .scl 2; .type 32; .endef +__MINGW_USYMBOL(log2l): +#ifdef __x86_64__ + fldl one(%rip) + fldt (%rdx) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + sahf + jc 3f // in case x is NaN or ±Inf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl limit(%rip) // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldl one + fldt 4(%esp) // x : 1 + fxam + fnstsw + fld %st // x : x : 1 + sahf + jc 3f // in case x is NaN or ±Inf +4: fsub %st(2), %st // x-1 : x : 1 + fld %st // x-1 : x-1 : x : 1 + fabs // |x-1| : x-1 : x : 1 + fcompl limit // x-1 : x : 1 + fnstsw // x-1 : x : 1 + andb $0x45, %ah + jz 2f + fstp %st(1) // x-1 : 1 + fyl2xp1 // log(x) + ret + +2: fstp %st(0) // x : 1 + fyl2x // log(x) + ret + +3: jp 4b // in case x is ±Inf + fstp %st(1) + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/logb.c b/libc/mingw/math/x86/logb.c new file mode 100644 index 000000000..0c0475d93 --- /dev/null +++ b/libc/mingw/math/x86/logb.c @@ -0,0 +1,38 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include + +double +logb (double x) +{ +#ifdef __x86_64__ + __mingw_dbl_type_t hlp; + int lx, hx; + + hlp.x = x; + lx = hlp.lh.low; + hx = hlp.lh.high & 0x7fffffff; /* high |x| */ + if ((hx | lx) == 0) + return -1.0 / fabs (x); + if (hx >= 0x7ff00000) + return x * x; + if ((hx >>= 20) == 0) /* IEEE 754 logb */ + return -1022.0; + return (double) (hx - 1023); +#else + double res = 0.0; + asm volatile ( + "fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; +#endif +} diff --git a/libc/mingw/math/x86/logbf.c b/libc/mingw/math/x86/logbf.c new file mode 100644 index 000000000..158b29b7b --- /dev/null +++ b/libc/mingw/math/x86/logbf.c @@ -0,0 +1,37 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include + +float +logbf (float x) +{ +#ifdef __x86_64__ + int v; + __mingw_flt_type_t hlp; + + hlp.x = x; + v = hlp.val & 0x7fffffff; /* high |x| */ + if (!v) + return (float)-1.0 / fabsf (x); + if (v >= 0x7f800000) + return x * x; + if ((v >>= 23) == 0) /* IEEE 754 logb */ + return -126.0; + return (float) (v - 127); +#else + float res = 0.0F; + asm volatile ( + "fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; +#endif +} diff --git a/libc/mingw/math/x86/logbl.c b/libc/mingw/math/x86/logbl.c new file mode 100644 index 000000000..5e533c07c --- /dev/null +++ b/libc/mingw/math/x86/logbl.c @@ -0,0 +1,23 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + * Written by J.T. Conklin . + * Changes for long double by Ulrich Drepper + * Public domain. + */ + +#include + +long double +logbl (long double x) +{ + long double res = 0.0L; + + asm volatile ( + "fxtract\n\t" + "fstp %%st" : "=t" (res) : "0" (x)); + return res; +} diff --git a/libc/mingw/math/x86/logl.c b/libc/mingw/math/x86/logl.c new file mode 100644 index 000000000..a0fa386dc --- /dev/null +++ b/libc/mingw/math/x86/logl.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "log.def.h" diff --git a/libc/mingw/math/x86/nearbyint.S b/libc/mingw/math/x86/nearbyint.S new file mode 100644 index 000000000..a0a85348c --- /dev/null +++ b/libc/mingw/math/x86/nearbyint.S @@ -0,0 +1,51 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyint.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + .globl __MINGW_USYMBOL(nearbyint) + .def __MINGW_USYMBOL(nearbyint); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyint): +#if defined(_AMD64_) || defined(__x86_64__) + movsd %xmm0,-16(%rsp) + fldl -16(%rsp) + pushq %rax + pushq %rcx + fnstcw (%rsp) + movq (%rsp), %rax + orq $0x20, %rax + movq %rax, 8(%rsp) + fldcw 8(%rsp) + frndint + fclex + fldcw (%rsp) + popq %rcx + popq %rax + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret +#elif defined(_X86_) || defined(__i386__) + fldl 4(%esp) + pushl %eax + pushl %ecx + fnstcw (%esp) + movl (%esp), %eax + orl $0x20, %eax + movl %eax, 4(%esp) + fldcw 4(%esp) + frndint + fclex + fldcw (%esp) + popl %ecx + popl %eax + ret +#endif diff --git a/libc/mingw/math/x86/nearbyintf.S b/libc/mingw/math/x86/nearbyintf.S new file mode 100644 index 000000000..4be7124ac --- /dev/null +++ b/libc/mingw/math/x86/nearbyintf.S @@ -0,0 +1,51 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyintf.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + .globl __MINGW_USYMBOL(nearbyintf) + .def __MINGW_USYMBOL(nearbyintf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyintf): +#if defined(_AMD64_) || defined(__x86_64__) + movss %xmm0,-12(%rsp) + flds -12(%rsp) + pushq %rax + pushq %rcx + fnstcw (%rsp) + movq (%rsp), %rax + orq $0x20, %rax + movq %rax, 8(%rsp) + fldcw 8(%rsp) + frndint + fclex + fldcw (%rsp) + popq %rcx + popq %rax + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret +#elif defined(_X86_) || defined(__i386__) + flds 4(%esp) + pushl %eax + pushl %ecx + fnstcw (%esp) + movl (%esp), %eax + orl $0x20, %eax + movl %eax, 4(%esp) + fldcw 4(%esp) + frndint + fclex + fldcw (%esp) + popl %ecx + popl %eax + ret +#endif diff --git a/libc/mingw/math/x86/nearbyintl.S b/libc/mingw/math/x86/nearbyintl.S new file mode 100644 index 000000000..38825344f --- /dev/null +++ b/libc/mingw/math/x86/nearbyintl.S @@ -0,0 +1,52 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "nearbyintl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif + .globl __MINGW_USYMBOL(nearbyintl) + .def __MINGW_USYMBOL(nearbyintl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(nearbyintl): +#if defined(_AMD64_) || defined(__x86_64__) + fldt (%rdx) + movq %rcx,%r8 + pushq %rax + pushq %rcx + fnstcw (%rsp) + movl (%rsp), %eax + orl $0x20, %eax + movl %eax, 8(%rsp) + fldcw 8(%rsp) + frndint + fclex + fldcw (%rsp) + popq %rcx + popq %rax + movq %r8,%rax + movq $0,8(%r8) + fstpt (%r8) + ret +#elif defined(_X86_) || defined(__i386__) + fldt 4(%esp) + pushl %eax + pushl %ecx + fnstcw (%esp) + movl (%esp), %eax + orl $0x20, %eax + movl %eax, 4(%esp) + fldcw 4(%esp) + frndint + fclex + fldcw (%esp) + popl %ecx + popl %eax + ret +#endif diff --git a/libc/mingw/math/x86/pow.c b/libc/mingw/math/x86/pow.c new file mode 100644 index 000000000..72a0f6eae --- /dev/null +++ b/libc/mingw/math/x86/pow.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "pow.def.h" diff --git a/libc/mingw/math/x86/pow.def.h b/libc/mingw/math/x86/pow.def.h new file mode 100644 index 000000000..375b02b9d --- /dev/null +++ b/libc/mingw/math/x86/pow.def.h @@ -0,0 +1,215 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* IEEE 754 - Elementary Functions - Special Cases + * pow(+/-0, oo) is +0 + * pow(+/-0, -oo) is +oo + * pow (x, +/-0) is 1 for any x (even a zero, quiet NaN, or infinity) + * pow (+1, y) is 1 for any y (even a quiet NaN) + * pow (+/-0, y) is +/-oo and signals the divideByZero exception for y an odd integer < 0 + * pow (+/-0, y) is +oo and signals the divideByZero exception for finite y < 0 and not an odd integer + * pow (+/-0, y) is +/-0 for finite y > 0 an odd integer + * pow (+/-0, y) is +0 for finite y > 0 and not an odd integer + * pow (-1, +/-oo) is 1 with no exception + pow( -inf, y) = +0 for y<0 and not an odd integer + pow( -inf, y) = -inf for y an odd integer > 0 + pow( -inf, y) = +inf for y>0 and not an odd integer + pow (+/-inf, y) is +/-0 with no exception for y an odd integer < 0 + pow (+/-inf, -inf) is +0 with no exception + pow (+/-inf, +inf) is +inf with no exception + pow (+/-inf, y) is +0 with no exception for finite y < 0 and not an odd integer + pow (+/-inf, y) is +/-inf with no exception for finite y > 0 an odd integer + pow (+/-inf, y) is +inf with no exception for finite y > 0 and not an odd integer + pow (x, y) signals the invalid operation exception for finite x < 0 and finite non-integer y. + + For x /= 0: lim y->oo (1/x)^y results as: for |x| < 1 that sgn(x)*0 and for |x| > 0 that sgn(x)*Infinity + +*/ +#include "../complex/complex_internal.h" +#include +#include +#include +#include +#include +#define FE_ROUNDING_MASK \ + (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO) + +static __FLT_TYPE +internal_modf (__FLT_TYPE value, __FLT_TYPE *iptr) +{ + __FLT_TYPE int_part = (__FLT_TYPE) 0.0; + /* truncate */ + /* truncate */ +#ifdef __x86_64__ + asm volatile ("pushq %%rax\n\tsubq $8, %%rsp\n" + "fnstcw 4(%%rsp)\n" + "movzwl 4(%%rsp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%rsp)\n" + "fldcw (%%rsp)\n" + "frndint\n" + "fldcw 4(%%rsp)\n" + "addq $8, %%rsp\npopq %%rax" : "=t" (int_part) : "0" (value)); /* round */ +#else + asm volatile ("push %%eax\n\tsubl $8, %%esp\n" + "fnstcw 4(%%esp)\n" + "movzwl 4(%%esp), %%eax\n" + "orb $12, %%ah\n" + "movw %%ax, (%%esp)\n" + "fldcw (%%esp)\n" + "frndint\n" + "fldcw 4(%%esp)\n" + "addl $8, %%esp\n\tpop %%eax\n" : "=t" (int_part) : "0" (value)); /* round */ +#endif + if (iptr) + *iptr = int_part; + return (isinf (value) ? (__FLT_TYPE) 0.0 : value - int_part); +} + +__FLT_TYPE __cdecl __FLT_ABI(__powi) (__FLT_TYPE x, int n); + +__FLT_TYPE __cdecl +__FLT_ABI(pow) (__FLT_TYPE x, __FLT_TYPE y) +{ + int x_class = fpclassify (x); + int y_class = fpclassify (y); + long odd_y = 0; + __FLT_TYPE d, rslt; + + if (y_class == FP_ZERO || x == __FLT_CST(1.0)) + return __FLT_CST(1.0); + else if (x_class == FP_NAN || y_class == FP_NAN) + { + rslt = (signbit(x) ? -__FLT_NAN : __FLT_NAN); + __FLT_RPT_DOMAIN ("pow", x, y, rslt); + return rslt; + } + else if (x_class == FP_ZERO) + { + if (y_class == FP_INFINITE) + return (signbit(y) ? __FLT_HUGE_VAL : __FLT_CST(0.0)); + + if (signbit(x) && internal_modf (y, &d) != 0.0) + { + return signbit (y) ? (1.0 / -x) : __FLT_CST (0.0); + /*__FLT_RPT_DOMAIN ("pow", x, y, -__FLT_NAN); + return -__FLT_NAN; */ + } + odd_y = (internal_modf (__FLT_ABI (ldexp) (y, -1), &d) != 0.0) ? 1 : 0; + if (!signbit(y)) + { + if (!odd_y || !signbit (x)) + return __FLT_CST (0.0); + return -__FLT_CST(0.0); + } + + if (!odd_y || !signbit (x)) + return __FLT_HUGE_VAL; + return (signbit(x) ? -__FLT_HUGE_VAL : __FLT_HUGE_VAL); + } + else if (y_class == FP_INFINITE) + { + __FLT_TYPE a_x; + + if (x_class == FP_INFINITE) + return (signbit (y) ? __FLT_CST (0.0) : __FLT_HUGE_VAL); + a_x = (signbit (x) ? -x : x); + if (a_x == 1.0) + return __FLT_CST (1.0); + if (a_x > 1.0) + return (signbit (y) == 0 ? __FLT_HUGE_VAL : __FLT_CST (0.0)); + return (!signbit (y) ? __FLT_CST (0.0) : __FLT_HUGE_VAL); + } + else if (x_class == FP_INFINITE) + { + /* pow (x, y) signals the invalid operation exception for finite x < 0 and finite non-integer y. */ + if (signbit(x) && internal_modf (y, &d) != 0.0) + { + return signbit(y) ? 1.0 / -x : -x; + /*__FLT_RPT_DOMAIN ("pow", x, y, -__FLT_NAN); + return -__FLT_NAN;*/ + } + odd_y = (internal_modf (__FLT_ABI (ldexp) (y, -1), &d) != 0.0) ? 1 : 0; + /* pow( -inf, y) = +0 for y<0 and not an odd integer, */ + if (signbit(x) && signbit(y) && !odd_y) + return __FLT_CST(0.0); + /* pow( -inf, y) = -inf for y an odd integer > 0. */ + if (signbit(x) && !signbit(y) && odd_y) + return -__FLT_HUGE_VAL; + /* pow( -inf, y) = +inf for y>0 and not an odd integer. */ + if (signbit(x) && !signbit(y) && !odd_y) + return __FLT_HUGE_VAL; + /* pow (+/-inf, y) is +/-0 with no exception for y an odd integer < 0. */ + if (signbit(y)) + { + /* pow (+/-inf, y) is +0 with no exception for finite y < 0 and not an odd integer. */ + return (odd_y && signbit(x) ? -__FLT_CST(0.0) : __FLT_CST(0.0)); + } + /* pow (+/-inf, y) is +/-inf with no exception for finite y > 0 an odd integer. */ + /* pow (+/-inf, y) is +inf with no exception for finite y > 0 and not an odd integer. */ + return (odd_y && signbit(x) ? -__FLT_HUGE_VAL : __FLT_HUGE_VAL); + } + + if (internal_modf (y, &d) != 0.0) + { + if (signbit (x)) + { + __FLT_RPT_DOMAIN ("pow", x, y, -__FLT_NAN); + return -__FLT_NAN; + } + if (y == __FLT_CST(0.5)) + { + asm volatile ("fsqrt" : "=t" (rslt) : "0" (x)); + return rslt; + } + } + else if ((d <= (__FLT_TYPE) INT_MAX && d >= (__FLT_TYPE) INT_MIN)) + return __FLT_ABI (__powi) (x, (int) y); + /* As exp already checks for minlog and maxlog no further checks are necessary. */ + rslt = (__FLT_TYPE) exp2l ((long double) y * log2l ((long double) __FLT_ABI(fabs) (x))); + + if (signbit (x) && internal_modf (__FLT_ABI (ldexp) (y, -1), &d) != 0.0) + rslt = -rslt; + return rslt; +} diff --git a/libc/mingw/math/x86/powl.c b/libc/mingw/math/x86/powl.c new file mode 100644 index 000000000..686437069 --- /dev/null +++ b/libc/mingw/math/x86/powl.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "pow.def.h" diff --git a/libc/mingw/math/x86/remainder.S b/libc/mingw/math/x86/remainder.S new file mode 100644 index 000000000..5a713f904 --- /dev/null +++ b/libc/mingw/math/x86/remainder.S @@ -0,0 +1,40 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "remainder.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(remainder) + .def __MINGW_USYMBOL(remainder); .scl 2; .type 32; .endef +__MINGW_USYMBOL(remainder): +#ifdef __x86_64__ + movsd %xmm0,-16(%rsp) + movsd %xmm1,-32(%rsp) + fldl -32(%rsp) + fldl -16(%rsp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret +#else + fldl 12(%esp) + fldl 4(%esp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/remainderf.S b/libc/mingw/math/x86/remainderf.S new file mode 100644 index 000000000..c3a3a3dc5 --- /dev/null +++ b/libc/mingw/math/x86/remainderf.S @@ -0,0 +1,40 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "remainderf.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(remainder) + .def __MINGW_USYMBOL(remainderf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(remainderf): +#ifdef __x86_64__ + movss %xmm1,-12(%rsp) + flds -12(%rsp) + movss %xmm0,-12(%rsp) + flds -12(%rsp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret +#else + flds 8(%esp) + flds 4(%esp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/remainderl.S b/libc/mingw/math/x86/remainderl.S new file mode 100644 index 000000000..a69e38296 --- /dev/null +++ b/libc/mingw/math/x86/remainderl.S @@ -0,0 +1,39 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "remainderl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(remainderl) + .def __MINGW_USYMBOL(remainderl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(remainderl): +#ifdef __x86_64__ + fldt (%r8) + fldt (%rdx) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldt 16(%esp) + fldt 4(%esp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + ret +#endif diff --git a/libc/mingw/math/x86/remquo.S b/libc/mingw/math/x86/remquo.S new file mode 100644 index 000000000..e90d4926b --- /dev/null +++ b/libc/mingw/math/x86/remquo.S @@ -0,0 +1,75 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "remquo.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(remquo) +__MINGW_USYMBOL(remquo): +#ifdef __x86_64__ + movsd %xmm1,-16(%rsp) + fldl -16(%rsp) + movsd %xmm0,-16(%rsp) + fldl -16(%rsp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + movl %eax, %ecx + shrl $8, %eax + shrl $12, %ecx + andl $4, %ecx + andl $3, %eax + orl %eax, %ecx + leal (%ecx,%ecx,2),%ecx + movl $0xef2a60, %eax + shrl %cl, %eax + andl $7, %eax + movl -12(%rsp), %edx + movsd %xmm1,-16(%rsp) + xorl -12(%rsp), %edx + testl $0x80000000, %edx + jz 1f + negl %eax +1: movl %eax, (%r8) + + fstpl -16(%rsp) + movsd -16(%rsp),%xmm0 + ret +#else + fldl 4 +8(%esp) + fldl 4(%esp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + movl %eax, %ecx + shrl $8, %eax + shrl $12, %ecx + andl $4, %ecx + andl $3, %eax + orl %eax, %ecx + leal (%ecx,%ecx,2),%ecx + movl $0xef2a60, %eax + shrl %cl, %eax + andl $7, %eax + movl 4 +8 +8(%esp), %ecx + movl 4 +4(%esp), %edx + xorl 4 +8 +4(%esp), %edx + testl $0x80000000, %edx + jz 1f + negl %eax +1: movl %eax, (%ecx) + + ret +#endif diff --git a/libc/mingw/math/x86/remquof.S b/libc/mingw/math/x86/remquof.S new file mode 100644 index 000000000..b78de9742 --- /dev/null +++ b/libc/mingw/math/x86/remquof.S @@ -0,0 +1,76 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "remquof.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(remquof) +__MINGW_USYMBOL(remquof): +#ifdef __x86_64__ + movss %xmm1,-12(%rsp) + flds -12(%rsp) + movss %xmm0,-12(%rsp) + flds -12(%rsp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + movl %eax, %ecx + shrl $8, %eax + shrl $12, %ecx + andl $4, %ecx + andl $3, %eax + orl %eax, %ecx + movl $0xef2a60, %eax + leal (%ecx,%ecx,2),%ecx + shrl %cl, %eax + andl $7, %eax + movss %xmm0,-12(%rsp) + movl -12(%rsp), %edx + movss %xmm1,-12(%rsp) + xorl -12(%rsp), %edx + testl $0x80000000, %edx + jz 1f + negl %eax +1: movl %eax, (%r8) + + fstps -12(%rsp) + movss -12(%rsp),%xmm0 + ret +#else + flds 4 +4(%esp) + flds 4(%esp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + movl %eax, %ecx + shrl $8, %eax + shrl $12, %ecx + andl $4, %ecx + andl $3, %eax + orl %eax, %ecx + movl $0xef2a60, %eax + leal (%ecx,%ecx,2),%ecx + shrl %cl, %eax + andl $7, %eax + movl 4 +4 +4(%esp), %ecx + movl 4(%esp), %edx + xorl 4 +4(%esp), %edx + testl $0x80000000, %edx + jz 1f + negl %eax +1: movl %eax, (%ecx) + + ret +#endif diff --git a/libc/mingw/math/x86/remquol.S b/libc/mingw/math/x86/remquol.S new file mode 100644 index 000000000..42cc2a78d --- /dev/null +++ b/libc/mingw/math/x86/remquol.S @@ -0,0 +1,75 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "remquol.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(remquol) +__MINGW_USYMBOL(remquol): +#ifdef __x86_64__ + pushq %rcx + fldt (%r8) + fldt (%rdx) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + movl %eax, %ecx + shrl $8, %eax + shrl $12, %ecx + andl $4, %ecx + andl $3, %eax + orl %eax, %ecx + movl $0xef2a60, %eax + leal (%ecx,%ecx,2),%ecx + shrl %cl, %eax + andl $7, %eax + movl 8(%rdx), %edx + xorl 8(%r8), %edx + testl $0x8000, %edx + jz 1f + negl %eax +1: movl %eax, (%r9) + + popq %rcx + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldt 4 +12(%esp) + fldt 4(%esp) +1: fprem1 + fstsw %ax + sahf + jp 1b + fstp %st(1) + movl %eax, %ecx + shrl $8, %eax + shrl $12, %ecx + andl $4, %ecx + andl $3, %eax + orl %eax, %ecx + movl $0xef2a60, %eax + leal (%ecx,%ecx,2),%ecx + shrl %cl, %eax + andl $7, %eax + movl 4 +12 +12(%esp), %ecx + movl 4 +8(%esp), %edx + xorl 4 +12 +8(%esp), %edx + testl $0x8000, %edx + jz 1f + negl %eax +1: movl %eax, (%ecx) + + ret +#endif diff --git a/libc/mingw/math/x86/scalbn.S b/libc/mingw/math/x86/scalbn.S new file mode 100644 index 000000000..8afcf7536 --- /dev/null +++ b/libc/mingw/math/x86/scalbn.S @@ -0,0 +1,41 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "scalbn.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(scalbn) + .def __MINGW_USYMBOL(scalbn); .scl 2; .type 32; .endef +__MINGW_USYMBOL(scalbn): +#ifdef __x86_64__ + subq $24, %rsp + movq %rdx,(%rsp) + fildl (%rsp) + movsd %xmm0,(%rsp) + fldl (%rsp) + fscale + fstp %st(1) + fstpl (%rsp) + movsd (%rsp),%xmm0 + addq $24, %rsp + ret + +#else + fildl 12(%esp) + fldl 4(%esp) + fscale + fstp %st(1) + ret +#endif + +.globl __MINGW_USYMBOL(scalbln) + .set __MINGW_USYMBOL(scalbln),__MINGW_USYMBOL(scalbn) + diff --git a/libc/mingw/math/x86/scalbnf.S b/libc/mingw/math/x86/scalbnf.S new file mode 100644 index 000000000..93a11f2ab --- /dev/null +++ b/libc/mingw/math/x86/scalbnf.S @@ -0,0 +1,40 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "scalbnf.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(scalbnf) + .def __MINGW_USYMBOL(scalbnf); .scl 2; .type 32; .endef +__MINGW_USYMBOL(scalbnf): +#ifdef __x86_64__ + subq $24, %rsp + movq %rdx,(%rsp) + fildl (%rsp) + movss %xmm0,(%rsp) + flds (%rsp) + fscale + fstp %st(1) + fstps (%rsp) + movss (%rsp),%xmm0 + addq $24, %rsp + ret +#else + fildl 8(%esp) + flds 4(%esp) + fscale + fstp %st(1) + ret +#endif + +.globl __MINGW_USYMBOL(scalblnf) + .set __MINGW_USYMBOL(scalblnf),__MINGW_USYMBOL(scalbnf) + diff --git a/libc/mingw/math/x86/scalbnl.S b/libc/mingw/math/x86/scalbnl.S new file mode 100644 index 000000000..5ff0a68f3 --- /dev/null +++ b/libc/mingw/math/x86/scalbnl.S @@ -0,0 +1,41 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "scalbnl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(scalbnl) + .def __MINGW_USYMBOL(scalbnl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(scalbnl): +#ifdef __x86_64__ + subq $24, %rsp + andl $-1, %r8d + movq %r8, (%rsp) + fildl (%rsp) + fldt (%rdx) + fscale + fstp %st(1) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + addq $24, %rsp + ret +#else + fildl 16(%esp) + fldt 4(%esp) + fscale + fstp %st(1) + ret +#endif + +.globl __MINGW_USYMBOL(scalblnl) + .set __MINGW_USYMBOL(scalblnl),__MINGW_USYMBOL(scalbnl) + diff --git a/libc/mingw/math/x86/sin.c b/libc/mingw/math/x86/sin.c new file mode 100644 index 000000000..b32ed6e5c --- /dev/null +++ b/libc/mingw/math/x86/sin.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_DOUBLE 1 +#include "sin.def.h" diff --git a/libc/mingw/math/x86/sin.def.h b/libc/mingw/math/x86/sin.def.h new file mode 100644 index 000000000..1673b34be --- /dev/null +++ b/libc/mingw/math/x86/sin.def.h @@ -0,0 +1,65 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "../complex/complex_internal.h" +#include + +extern long double __sinl_internal (long double); + +__FLT_TYPE +__FLT_ABI(sin) (__FLT_TYPE x) +{ + int x_class = fpclassify (x); + if (x_class == FP_NAN) + { + __FLT_RPT_DOMAIN ("sin", x, 0.0, x); + return x; + } + else if (x_class == FP_INFINITE) + { + __FLT_RPT_DOMAIN ("sin", x, 0.0, __FLT_NAN); + return __FLT_NAN; + } + return (__FLT_TYPE) __sinl_internal ((long double) x); +} diff --git a/libc/mingw/math/x86/sinf.c b/libc/mingw/math/x86/sinf.c new file mode 100644 index 000000000..29fd3a2a8 --- /dev/null +++ b/libc/mingw/math/x86/sinf.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float sinf(float _X) +{ + return ((float) sin ((double) _X)); +} diff --git a/libc/mingw/math/x86/sinl.c b/libc/mingw/math/x86/sinl.c new file mode 100644 index 000000000..0bbb71d37 --- /dev/null +++ b/libc/mingw/math/x86/sinl.c @@ -0,0 +1,46 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2009, 2010 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#define _NEW_COMPLEX_LDOUBLE 1 +#include "sin.def.h" diff --git a/libc/mingw/math/x86/sinl_internal.S b/libc/mingw/math/x86/sinl_internal.S new file mode 100644 index 000000000..6d766b098 --- /dev/null +++ b/libc/mingw/math/x86/sinl_internal.S @@ -0,0 +1,58 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "sinl_internal.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(__sinl_internal) + .def __MINGW_USYMBOL(__sinl_internal); .scl 2; .type 32; .endef +__MINGW_USYMBOL(__sinl_internal): +#ifdef __x86_64__ + fldt (%rdx) + fsin + fnstsw %ax + testl $0x400,%eax + jnz 1f + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fsin + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldt 4(%esp) + fsin + fnstsw %ax + testl $0x400,%eax + jnz 1f + ret +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fnstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fsin + ret +#endif diff --git a/libc/mingw/math/x86/tanf.c b/libc/mingw/math/x86/tanf.c new file mode 100644 index 000000000..72b4cc4bb --- /dev/null +++ b/libc/mingw/math/x86/tanf.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float tanf(float _X) +{ + return ((float)tan((double)_X)); +} diff --git a/libc/mingw/math/x86/tanl.S b/libc/mingw/math/x86/tanl.S new file mode 100644 index 000000000..f11b53920 --- /dev/null +++ b/libc/mingw/math/x86/tanl.S @@ -0,0 +1,62 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "tanl.S" + .text +#ifdef __x86_64__ + .align 8 +#else + .align 4 +#endif +.globl __MINGW_USYMBOL(tanl) + .def __MINGW_USYMBOL(tanl); .scl 2; .type 32; .endef +__MINGW_USYMBOL(tanl): +#ifdef __x86_64__ + fldt (%rdx) + fptan + fnstsw %ax + testl $0x400,%eax + jnz 1f + fstp %st(0) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fptan + fstp %st(0) + movq %rcx,%rax + movq $0,8(%rcx) + fstpt (%rcx) + ret +#else + fldt 4(%esp) + fptan + fnstsw %ax + testl $0x400,%eax + jnz 1f + fstp %st(0) + ret +1: fldpi + fadd %st(0) + fxch %st(1) +2: fprem1 + fstsw %ax + testl $0x400,%eax + jnz 2b + fstp %st(1) + fptan + fstp %st(0) + ret +#endif diff --git a/libc/mingw/math/x86/trunc.S b/libc/mingw/math/x86/trunc.S new file mode 100644 index 000000000..4f1fa2b0d --- /dev/null +++ b/libc/mingw/math/x86/trunc.S @@ -0,0 +1,91 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "trunc.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(trunc) + .def __MINGW_USYMBOL(trunc); .scl 2; .type 32; .endef + +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(trunc) +#endif +__MINGW_USYMBOL(trunc): +#if defined(_AMD64_) || defined(__x86_64__) + subq $24, %rsp + .seh_stackalloc 24 + .seh_endprologue + movsd %xmm0, 8(%rsp) + movq 8(%rsp), %r8 + movq %r8, %rdx + shrq $32, %rdx + movl %edx, %eax + sarl $20, %eax + andl $2047, %eax + leal -1023(%rax), %ecx + cmpl $19, %ecx + jg .l1 + movl %edx, %r8d + andl $-2147483648, %r8d + testl %ecx, %ecx + js .l3 + movl $1048575, %eax + sarl %cl, %eax + notl %eax + andl %edx, %eax + orl %r8d, %eax + salq $32, %rax + movq %rax, 8(%rsp) + movsd 8(%rsp), %xmm0 + addq $24, %rsp + ret + .p2align 4,,10 +.l1: + cmpl $51, %ecx + jle .l2 + /* Is x inf/nan? */ + cmpl $1024, %ecx + jne .noinfnan + addsd %xmm0, %xmm0 +.noinfnan: + addq $24, %rsp + ret + .p2align 4,,10 +.l2: + leal -1043(%rax), %ecx + movl $-1, %r9d + salq $32, %rdx + shrl %cl, %r9d + notl %r9d + andl %r9d, %r8d + orq %r8, %rdx + movq %rdx, 8(%rsp) + movsd 8(%rsp), %xmm0 + addq $24, %rsp + ret + .p2align 4,,10 +.l3: + salq $32, %r8 + movq %r8, 8(%rsp) + movsd 8(%rsp), %xmm0 + addq $24, %rsp + ret + .seh_endproc +#elif defined(_X86_) || defined(__i386__) + fldl 4(%esp) + subl $8, %esp + fstcw (%esp) + /* FE_TOWARDZERO */ + movzwl (%esp), %eax + orb $0xc, %ah + movw %ax, 4(%esp) + fldcw 4(%esp) + frndint + fldcw (%esp) + addl $8, %esp + ret +#endif diff --git a/libc/mingw/math/x86/truncf.S b/libc/mingw/math/x86/truncf.S new file mode 100644 index 000000000..40a3a6ea9 --- /dev/null +++ b/libc/mingw/math/x86/truncf.S @@ -0,0 +1,71 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "truncf.S" + .text + .p2align 4,,15 + .globl __MINGW_USYMBOL(truncf) + .def __MINGW_USYMBOL(truncf); .scl 2; .type 32; .endef + +#ifdef __x86_64__ + .seh_proc __MINGW_USYMBOL(truncf) +#endif +__MINGW_USYMBOL(truncf): +#if defined(_AMD64_) || defined(__x86_64__) + subq $24, %rsp + .seh_stackalloc 24 + .seh_endprologue + movd %xmm0, 12(%rsp) + movl 12(%rsp), %edx + movl %edx, %ecx + sarl $23, %ecx + andl $255, %ecx + subl $127, %ecx + cmpl $22, %ecx + jg .l1 + movl %edx, %r8d + andl $-2147483648, %r8d + testl %ecx, %ecx + js .l2 + movl $8388607, %eax + sarl %cl, %eax + notl %eax + andl %edx, %eax + orl %r8d, %eax + movl %eax, 8(%rsp) + movss 8(%rsp), %xmm0 + addq $24, %rsp + ret + .p2align 4,,10 +.l1: + addl $-128, %ecx + jne .noinfnan + addss %xmm0, %xmm0 +.noinfnan: + addq $24, %rsp + ret + .p2align 4,,10 +.l2: + movl %r8d, 8(%rsp) + movss 8(%rsp), %xmm0 + addq $24, %rsp + ret + .seh_endproc +#elif defined(_X86_) || defined(__i386__) + flds 4(%esp) + subl $8, %esp + fstcw (%esp) + /* FE_TOWARDZERO */ + movzwl (%esp), %eax + orb $0xc, %ah + movw %ax, 4(%esp) + fldcw 4(%esp) + frndint + fldcw (%esp) + addl $8, %esp + ret +#endif diff --git a/libc/mingw/misc/alarm.c b/libc/mingw/misc/alarm.c new file mode 100644 index 000000000..f0c29cccb --- /dev/null +++ b/libc/mingw/misc/alarm.c @@ -0,0 +1,14 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include <_mingw.h> + +unsigned int alarm(unsigned int); + +unsigned int alarm(unsigned int __UNUSED_PARAM(seconds)) +{ + return 0; +} diff --git a/libc/mingw/misc/assert.c b/libc/mingw/misc/assert.c new file mode 100644 index 000000000..0bebb7e97 --- /dev/null +++ b/libc/mingw/misc/assert.c @@ -0,0 +1,31 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include +#include +#include + +void __cdecl _wassert (const wchar_t *, const wchar_t *,unsigned); +void __cdecl _assert (const char *, const char *, unsigned); + +void __cdecl +_assert (const char *_Message, const char *_File, unsigned _Line) +{ + wchar_t *m, *f; + int i; + m = (wchar_t *) malloc ((strlen (_Message) + 1) * sizeof (wchar_t)); + f = (wchar_t *) malloc ((strlen (_File) + 1) * sizeof (wchar_t)); + for (i = 0; _Message[i] != 0; i++) + m[i] = ((wchar_t) _Message[i]) & 0xff; + m[i] = 0; + for (i = 0; _File[i] != 0; i++) + f[i] = ((wchar_t) _File[i]) & 0xff; + f[i] = 0; + _wassert (m, f, _Line); + free (m); + free (f); +} diff --git a/libc/mingw/misc/basename.c b/libc/mingw/misc/basename.c new file mode 100644 index 000000000..c45dbbb36 --- /dev/null +++ b/libc/mingw/misc/basename.c @@ -0,0 +1,135 @@ +/* basename.c + * + * $Id: basename.c,v 1.2 2007/03/08 23:15:58 keithmarshall Exp $ + * + * Provides an implementation of the "basename" function, conforming + * to SUSv3, with extensions to accommodate Win32 drive designators, + * and suitable for use on native Microsoft(R) Win32 platforms. + * + * Written by Keith Marshall + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ + +#include +#include +#include +#include +#include + +#ifndef __cdecl +#define __cdecl +#endif + +char * __cdecl +basename (char *path) +{ + static char *retfail = NULL; + size_t len; + /* to handle path names for files in multibyte character locales, + * we need to set up LC_CTYPE to match the host file system locale + */ + char *locale = setlocale (LC_CTYPE, NULL); + + if (locale != NULL) + locale = strdup (locale); + setlocale (LC_CTYPE, ""); + + if (path && *path) + { + /* allocate sufficient local storage space, + * in which to create a wide character reference copy of path + */ + wchar_t refcopy[1 + (len = mbstowcs (NULL, path, 0))]; + /* create the wide character reference copy of path, + * and step over the drive designator, if present ... + */ + wchar_t *refpath = refcopy; + + if ((len = mbstowcs( refpath, path, len)) > 1 && refpath[1] == L':') + { + /* FIXME: maybe should confirm *refpath is a valid drive designator */ + refpath += 2; + } + /* ensure that our wide character reference path is NUL terminated */ + refcopy[len] = L'\0'; + /* check again, just to ensure we still have a non-empty path name ... */ + if (*refpath) + { + /* and, when we do, process it in the wide character domain ... + * scanning from left to right, to the char after the final dir separator. */ + wchar_t *refname; + + for (refname = refpath; *refpath; ++refpath) + { + if (*refpath == L'/' || *refpath == L'\\') + { + /* we found a dir separator ... + * step over it, and any others which immediately follow it. */ + while (*refpath == L'/' || *refpath == L'\\') + ++refpath; + /* if we didn't reach the end of the path string ... */ + if (*refpath) + /* then we have a new candidate for the base name. */ + refname = refpath; + /* otherwise ... + * strip off any trailing dir separators which we found. */ + else + while (refpath > refname + && (*--refpath == L'/' || *refpath == L'\\') ) + *refpath = L'\0'; + } + } + /* in the wide character domain ... + * refname now points at the resolved base name ... */ + if (*refname) + { + /* if it's not empty, + * then we transform the full normalised path back into + * the multibyte character domain, and skip over the dirname, + * to return the resolved basename. */ + if ((len = wcstombs( path, refcopy, len)) != (size_t)(-1)) + path[len] = '\0'; + *refname = L'\0'; + if ((len = wcstombs( NULL, refcopy, 0 )) != (size_t)(-1)) + path += len; + } + else + { + /* the basename is empty, so return the default value of "/", + * transforming from wide char to multibyte char domain, and + * returning it in our own buffer. */ + retfail = realloc (retfail, len = 1 + wcstombs (NULL, L"/", 0)); + wcstombs (path = retfail, L"/", len); + } + /* restore the caller's locale, clean up, and return the result */ + setlocale (LC_CTYPE, locale); + free (locale); + return path; + } + /* or we had an empty residual path name, after the drive designator, + * in which case we simply fall through ... */ + } + /* and, if we get to here ... + * the path name is either NULL, or it decomposes to an empty string; + * in either case, we return the default value of "." in our own buffer, + * reloading it with the correct value, transformed from the wide char + * to the multibyte char domain, just in case the caller trashed it + * after a previous call. + */ + retfail = realloc (retfail, len = 1 + wcstombs( NULL, L".", 0)); + wcstombs (retfail, L".", len); + + /* restore the caller's locale, clean up, and return the result. */ + setlocale (LC_CTYPE, locale); + free (locale); + return retfail; +} diff --git a/libc/mingw/misc/btowc.c b/libc/mingw/misc/btowc.c new file mode 100644 index 000000000..026b491d7 --- /dev/null +++ b/libc/mingw/misc/btowc.c @@ -0,0 +1,26 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include "mb_wc_common.h" +#include +#include +#include + +wint_t btowc (int c) +{ + if (c == EOF) + return (WEOF); + else + { + unsigned char ch = c; + wchar_t wc = WEOF; + MultiByteToWideChar (___lc_codepage_func(), MB_ERR_INVALID_CHARS, + (char*)&ch, 1, &wc, 1); + return wc; + } +} diff --git a/libc/mingw/misc/delay-f.c b/libc/mingw/misc/delay-f.c new file mode 100644 index 000000000..82e0f65bd --- /dev/null +++ b/libc/mingw/misc/delay-f.c @@ -0,0 +1,13 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +PfnDliHook __pfnDliFailureHook2 = NULL; diff --git a/libc/mingw/misc/delay-n.c b/libc/mingw/misc/delay-n.c new file mode 100644 index 000000000..942963e53 --- /dev/null +++ b/libc/mingw/misc/delay-n.c @@ -0,0 +1,13 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +PfnDliHook __pfnDliNotifyHook2 = NULL; diff --git a/libc/mingw/misc/delayimp.c b/libc/mingw/misc/delayimp.c new file mode 100644 index 000000000..26afde807 --- /dev/null +++ b/libc/mingw/misc/delayimp.c @@ -0,0 +1,279 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + * + * This file is derived from Microsoft implementation file delayhlp.cpp, which + * is free for users to modify and derive. + */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +static size_t __strlen(const char *sz) +{ + const char *szEnd = sz; + while(*szEnd++ != 0) + ; + return szEnd - sz - 1; +} + +static int __memcmp(const void *pv1,const void *pv2,size_t cb) +{ + if(!cb) + return 0; + while(--cb && *(char *)pv1 == *(char *)pv2) { + pv1 = ((char *)pv1) + 1; + pv2 = ((char *)pv2) + 1; + } + return *((unsigned char *)pv1) - *((unsigned char *)pv2); +} + +static void *__memcpy(void *pvDst,const void *pvSrc,size_t cb) +{ + void *pvRet = pvDst; + while(cb--) { + *(char *)pvDst = *(char *)pvSrc; + pvDst = ((char *)pvDst) + 1; + pvSrc = ((char *)pvSrc) + 1; + } + return pvRet; +} + +static unsigned IndexFromPImgThunkData(PCImgThunkData pitdCur,PCImgThunkData pitdBase) +{ + return (unsigned) (pitdCur - pitdBase); +} + +#define __ImageBase __MINGW_LSYMBOL(_image_base__) +extern IMAGE_DOS_HEADER __ImageBase; + +#define PtrFromRVA(RVA) (((PBYTE)&__ImageBase) + (RVA)) + +typedef struct UnloadInfo *PUnloadInfo; +typedef struct UnloadInfo { + PUnloadInfo puiNext; + PCImgDelayDescr pidd; +} UnloadInfo; + +static unsigned CountOfImports(PCImgThunkData pitdBase) +{ + unsigned cRet = 0; + PCImgThunkData pitd = pitdBase; + while(pitd->u1.Function) { + pitd++; + cRet++; + } + return cRet; +} + +PUnloadInfo __puiHead = 0; + +static UnloadInfo *add_ULI(PCImgDelayDescr pidd_) +{ + UnloadInfo *ret = (UnloadInfo *) LocalAlloc(LPTR,sizeof(UnloadInfo)); + ret->pidd = pidd_; + ret->puiNext = __puiHead; + __puiHead = ret; + return ret; +} + +static void del_ULI(UnloadInfo *p) +{ + if (p) { + PUnloadInfo *ppui = &__puiHead; + while(*ppui && *ppui!=p) { + ppui = &((*ppui)->puiNext); + } + if(*ppui==p) *ppui = p->puiNext; + LocalFree((void *)p); + } +} + +typedef struct InternalImgDelayDescr { + DWORD grAttrs; + LPCSTR szName; + HMODULE *phmod; + PImgThunkData pIAT; + PCImgThunkData pINT; + PCImgThunkData pBoundIAT; + PCImgThunkData pUnloadIAT; + DWORD dwTimeStamp; +} InternalImgDelayDescr; + +typedef InternalImgDelayDescr *PIIDD; +typedef const InternalImgDelayDescr *PCIIDD; + +static PIMAGE_NT_HEADERS WINAPI PinhFromImageBase(HMODULE hmod) +{ + return (PIMAGE_NT_HEADERS) (((PBYTE)(hmod)) + ((PIMAGE_DOS_HEADER)(hmod))->e_lfanew); +} + +static void WINAPI OverlayIAT(PImgThunkData pitdDst,PCImgThunkData pitdSrc) +{ + __memcpy(pitdDst,pitdSrc,CountOfImports(pitdDst) * sizeof(IMAGE_THUNK_DATA)); +} + +static DWORD WINAPI TimeStampOfImage(PIMAGE_NT_HEADERS pinh) +{ + return pinh->FileHeader.TimeDateStamp; +} + +static int WINAPI FLoadedAtPreferredAddress(PIMAGE_NT_HEADERS pinh,HMODULE hmod) +{ + return ((UINT_PTR)(hmod)) == pinh->OptionalHeader.ImageBase; +} + +#if(defined(_X86_) && !defined(__x86_64)) +#undef InterlockedExchangePointer +#define InterlockedExchangePointer(Target,Value) (PVOID)(LONG_PTR)InterlockedExchange((PLONG)(Target),(LONG)(LONG_PTR)(Value)) +/*typedef unsigned long *PULONG_PTR;*/ +#endif + +FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry); + +FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry) +{ + InternalImgDelayDescr idd = { + pidd->grAttrs,(LPCTSTR) PtrFromRVA(pidd->rvaDLLName),(HMODULE *) PtrFromRVA(pidd->rvaHmod), + (PImgThunkData) PtrFromRVA(pidd->rvaIAT), (PCImgThunkData) PtrFromRVA(pidd->rvaINT), + (PCImgThunkData) PtrFromRVA(pidd->rvaBoundIAT), (PCImgThunkData) PtrFromRVA(pidd->rvaUnloadIAT), + pidd->dwTimeStamp}; + DelayLoadInfo dli = { + sizeof(DelayLoadInfo),pidd,ppfnIATEntry,idd.szName,{ 0, { NULL } },0,0,0 + }; + HMODULE hmod; + unsigned iIAT, iINT; + PCImgThunkData pitd; + FARPROC pfnRet; + + if(!(idd.grAttrs & dlattrRva)) { + PDelayLoadInfo rgpdli[1] = { &dli}; + RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_INVALID_PARAMETER),0,1,(PULONG_PTR)(rgpdli)); + return 0; + } + hmod = *idd.phmod; + iIAT = IndexFromPImgThunkData((PCImgThunkData)(ppfnIATEntry),idd.pIAT); + iINT = iIAT; + pitd = &(idd.pINT[iINT]); + + dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal); + if(dli.dlp.fImportByName) + dli.dlp.szProcName = + (LPCSTR) + ( + ((PIMAGE_IMPORT_BY_NAME) PtrFromRVA( + (RVA)((UINT_PTR)(pitd->u1.AddressOfData)) + ) + )->Name + ); + else dli.dlp.dwOrdinal = (DWORD)(IMAGE_ORDINAL(pitd->u1.Ordinal)); + pfnRet = NULL; + if(__pfnDliNotifyHook2) { + pfnRet = ((*__pfnDliNotifyHook2)(dliStartProcessing,&dli)); + if(pfnRet!=NULL) goto HookBypass; + } + if(hmod==0) { + if(__pfnDliNotifyHook2) + hmod = (HMODULE) (((*__pfnDliNotifyHook2)(dliNotePreLoadLibrary,&dli))); + if(hmod==0) hmod = LoadLibrary(dli.szDll); + if(hmod==0) { + dli.dwLastError = GetLastError(); + if(__pfnDliFailureHook2) + hmod = (HMODULE) ((*__pfnDliFailureHook2)(dliFailLoadLib,&dli)); + if(hmod==0) { + PDelayLoadInfo rgpdli[1] = { &dli}; + RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND),0,1,(PULONG_PTR)(rgpdli)); + return dli.pfnCur; + } + } + HMODULE hmodT = (HMODULE)(InterlockedExchangePointer((PVOID *) idd.phmod,(PVOID)(hmod))); + if(hmodT!=hmod) { + if(pidd->rvaUnloadIAT) add_ULI(pidd); + } else FreeLibrary(hmod); + } + dli.hmodCur = hmod; + if(__pfnDliNotifyHook2) pfnRet = (*__pfnDliNotifyHook2)(dliNotePreGetProcAddress,&dli); + if(pfnRet==0) { + if(pidd->rvaBoundIAT && pidd->dwTimeStamp) { + PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS) (PinhFromImageBase(hmod)); + if(pinh->Signature==IMAGE_NT_SIGNATURE && + TimeStampOfImage(pinh)==idd.dwTimeStamp && + FLoadedAtPreferredAddress(pinh,hmod)) { + pfnRet = (FARPROC) ((UINT_PTR)(idd.pBoundIAT[iIAT].u1.Function)); + if(pfnRet!=0) goto SetEntryHookBypass; + } + } + pfnRet = GetProcAddress(hmod,dli.dlp.szProcName); + } + if(!pfnRet) { + dli.dwLastError = GetLastError(); + if(__pfnDliFailureHook2) pfnRet = (*__pfnDliFailureHook2)(dliFailGetProc,&dli); + if(!pfnRet) { + PDelayLoadInfo rgpdli[1] = { &dli}; + RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND),0,1,(PULONG_PTR)(rgpdli)); + pfnRet = dli.pfnCur; + } + } +SetEntryHookBypass: + *ppfnIATEntry = pfnRet; +HookBypass: + if(__pfnDliNotifyHook2) { + dli.dwLastError = 0; + dli.hmodCur = hmod; + dli.pfnCur = pfnRet; + (*__pfnDliNotifyHook2)(dliNoteEndProcessing,&dli); + } + return pfnRet; +} + +WINBOOL WINAPI __FUnloadDelayLoadedDLL2(LPCSTR szDll) +{ + WINBOOL fRet = FALSE; + PUnloadInfo pui = __puiHead; + + for(pui = __puiHead;pui;pui = pui->puiNext) { + LPCSTR szName = (LPCTSTR) PtrFromRVA(pui->pidd->rvaDLLName); + size_t cbName = __strlen(szName); + if(cbName==__strlen(szDll) && __memcmp(szDll,szName,cbName)==0) break; + } + if(pui && pui->pidd->rvaUnloadIAT) { + PCImgDelayDescr pidd = pui->pidd; + HMODULE *phmod = (HMODULE *) PtrFromRVA(pidd->rvaHmod); + HMODULE hmod = *phmod; + OverlayIAT((PImgThunkData) PtrFromRVA(pidd->rvaIAT), (PCImgThunkData) PtrFromRVA(pidd->rvaUnloadIAT)); + FreeLibrary(hmod); + *phmod = NULL; + del_ULI((UnloadInfo *) pui); + fRet = TRUE; + } + return fRet; +} + +HRESULT WINAPI __HrLoadAllImportsForDll(LPCSTR szDll) +{ + HRESULT hrRet = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND); + PIMAGE_NT_HEADERS pinh = PinhFromImageBase((HMODULE) (&__ImageBase)); + if(pinh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size) { + PCImgDelayDescr pidd; + pidd = (PCImgDelayDescr) PtrFromRVA(pinh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress); + while(pidd->rvaDLLName) { + LPCSTR szDllCur = (LPCSTR) PtrFromRVA(pidd->rvaDLLName); + size_t cchDllCur = __strlen(szDllCur); + if(cchDllCur==__strlen(szDll) && __memcmp(szDll,szDllCur,cchDllCur)==0) break; + pidd++; + } + if(pidd->rvaDLLName) { + FARPROC *ppfnIATEntry = (FARPROC *) PtrFromRVA(pidd->rvaIAT); + size_t cpfnIATEntries = CountOfImports((PCImgThunkData) (ppfnIATEntry)); + FARPROC *ppfnIATEntryMax = ppfnIATEntry + cpfnIATEntries; + for(;ppfnIATEntry < ppfnIATEntryMax;ppfnIATEntry++) { + __delayLoadHelper2(pidd,ppfnIATEntry); + } + hrRet = S_OK; + } + } + return hrRet; +} diff --git a/libc/mingw/misc/difftime.c b/libc/mingw/misc/difftime.c new file mode 100644 index 000000000..5d49f5291 --- /dev/null +++ b/libc/mingw/misc/difftime.c @@ -0,0 +1,21 @@ +#define __CRT__NO_INLINE +#include +#include + +/* FIXME: Relying on _USE_32BIT_TIME_T, which is a user-macro, +during CRT compilation is plainly broken. Need an appropriate +implementation to provide users the ability of compiling the +CRT only with 32-bit time_t behavior. */ + +#ifndef _USE_32BIT_TIME_T +double __cdecl difftime(time_t _Time1,time_t _Time2) +{ + return _difftime64(_Time1,_Time2); +} +#else +double __cdecl difftime(time_t _Time1,time_t _Time2) +{ + return _difftime32(_Time1,_Time2); +} +#endif + diff --git a/libc/mingw/misc/difftime32.c b/libc/mingw/misc/difftime32.c new file mode 100644 index 000000000..b89394441 --- /dev/null +++ b/libc/mingw/misc/difftime32.c @@ -0,0 +1,9 @@ +#include + +double __cdecl _difftime32(__time32_t _Time1,__time32_t _Time2) +{ + __time32_t r = _Time1 - _Time2; + if (r > _Time1) + return -((double) (_Time2 - _Time1)); + return (double) r; +} diff --git a/libc/mingw/misc/difftime64.c b/libc/mingw/misc/difftime64.c new file mode 100644 index 000000000..54f9a12af --- /dev/null +++ b/libc/mingw/misc/difftime64.c @@ -0,0 +1,9 @@ +#include + +double __cdecl _difftime64(__time64_t _Time1,__time64_t _Time2) +{ + __time64_t r = _Time1 - _Time2; + if (r > _Time1) + return -((double) (_Time2 - _Time1)); + return (double) r; +} diff --git a/libc/mingw/misc/dirent.c b/libc/mingw/misc/dirent.c new file mode 100644 index 000000000..4897cf492 --- /dev/null +++ b/libc/mingw/misc/dirent.c @@ -0,0 +1,325 @@ +/* + * dirent.c + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within the package. + * + * Derived from DIRLIB.C by Matt J. Weinstein + * This note appears in the DIRLIB.H + * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 + * + * Updated by Jeremy Bettis + * Significantly revised and rewinddir, seekdir and telldir added by Colin + * Peters + * + */ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include +#include +#include + +#include /* for GetFileAttributes */ + +#include +#define SUFFIX _T("*") +#define SLASH _T("\\") + + +/* + * opendir + * + * Returns a pointer to a DIR structure appropriately filled in to begin + * searching a directory. + */ +_TDIR * +_topendir (const _TCHAR *szPath) +{ + _TDIR *nd; + unsigned int rc; + _TCHAR szFullPath[MAX_PATH]; + + errno = 0; + + if (!szPath) + { + errno = EFAULT; + return (_TDIR *) 0; + } + + if (szPath[0] == _T('\0')) + { + errno = ENOTDIR; + return (_TDIR *) 0; + } + + /* Attempt to determine if the given path really is a directory. */ + rc = GetFileAttributes (szPath); + if (rc == INVALID_FILE_ATTRIBUTES) + { + /* call GetLastError for more error info */ + errno = ENOENT; + return (_TDIR *) 0; + } + if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) + { + /* Error, entry exists but not a directory. */ + errno = ENOTDIR; + return (_TDIR *) 0; + } + + /* Make an absolute pathname. */ + _tfullpath (szFullPath, szPath, MAX_PATH); + + /* Allocate enough space to store DIR structure and the complete + * directory path given. */ + nd = (_TDIR *) malloc (sizeof (_TDIR) + (_tcslen (szFullPath) + + _tcslen (SLASH) + + _tcslen (SUFFIX) + 1) + * sizeof (_TCHAR)); + + if (!nd) + { + /* Error, out of memory. */ + errno = ENOMEM; + return (_TDIR *) 0; + } + + /* Create the search expression. */ + _tcscpy (nd->dd_name, szFullPath); + + /* Add on a slash if the path does not end with one. */ + if (nd->dd_name[0] != _T('\0') && + nd->dd_name[_tcslen (nd->dd_name) - 1] != _T('/') && + nd->dd_name[_tcslen (nd->dd_name) - 1] != _T('\\')) + { + _tcscat (nd->dd_name, SLASH); + } + + /* Add on the search pattern */ + _tcscat (nd->dd_name, SUFFIX); + + /* Initialize handle to -1 so that a premature closedir doesn't try + * to call _findclose on it. */ + nd->dd_handle = -1; + + /* Initialize the status. */ + nd->dd_stat = 0; + + /* Initialize the dirent structure. ino and reclen are invalid under + * Win32, and name simply points at the appropriate part of the + * findfirst_t structure. */ + nd->dd_dir.d_ino = 0; + nd->dd_dir.d_reclen = 0; + nd->dd_dir.d_namlen = 0; + memset (nd->dd_dir.d_name, 0, 260 * sizeof(nd->dd_dir.d_name[0]) /*FILENAME_MAX*/); + + return nd; +} + + +/* + * readdir + * + * Return a pointer to a dirent structure filled with the information on the + * next entry in the directory. + */ +struct _tdirent * +_treaddir (_TDIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return (struct _tdirent *) 0; + } + + if (dirp->dd_stat < 0) + { + /* We have already returned all files in the directory + * (or the structure has an invalid dd_stat). */ + return (struct _tdirent *) 0; + } + else if (dirp->dd_stat == 0) + { + /* We haven't started the search yet. */ + /* Start the search */ + dirp->dd_handle = _tfindfirst (dirp->dd_name, &(dirp->dd_dta)); + + if (dirp->dd_handle == -1) + { + /* Whoops! Seems there are no files in that + * directory. */ + dirp->dd_stat = -1; + } + else + { + dirp->dd_stat = 1; + } + } + else + { + /* Get the next search entry. */ + if (_tfindnext (dirp->dd_handle, &(dirp->dd_dta))) + { + /* We are off the end or otherwise error. + _findnext sets errno to ENOENT if no more file + Undo this. */ + DWORD winerr = GetLastError (); + if (winerr == ERROR_NO_MORE_FILES) + errno = 0; + _findclose (dirp->dd_handle); + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Update the status to indicate the correct + * number. */ + dirp->dd_stat++; + } + } + + if (dirp->dd_stat > 0) + { + /* Successfully got an entry. Everything about the file is + * already appropriately filled in except the length of the + * file name. */ + dirp->dd_dir.d_namlen = _tcslen (dirp->dd_dta.name); + _tcscpy (dirp->dd_dir.d_name, dirp->dd_dta.name); + return &dirp->dd_dir; + } + + return (struct _tdirent *) 0; +} + + +/* + * closedir + * + * Frees up resources allocated by opendir. + */ +int +_tclosedir (_TDIR * dirp) +{ + int rc; + + errno = 0; + rc = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + + if (dirp->dd_handle != -1) + { + rc = _findclose (dirp->dd_handle); + } + + /* Delete the dir structure. */ + free (dirp); + + return rc; +} + +/* + * rewinddir + * + * Return to the beginning of the directory "stream". We simply call findclose + * and then reset things like an opendir. + */ +void +_trewinddir (_TDIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + + dirp->dd_handle = -1; + dirp->dd_stat = 0; +} + +/* + * telldir + * + * Returns the "position" in the "directory stream" which can be used with + * seekdir to go back to an old entry. We simply return the value in stat. + */ +long +_ttelldir (_TDIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + return dirp->dd_stat; +} + +/* + * seekdir + * + * Seek to an entry previously returned by telldir. We rewind the directory + * and call readdir repeatedly until either dd_stat is the position number + * or -1 (off the end). This is not perfect, in that the directory may + * have changed while we weren't looking. But that is probably the case with + * any such system. + */ +void +_tseekdir (_TDIR * dirp, long lPos) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (lPos < -1) + { + /* Seeking to an invalid position. */ + errno = EINVAL; + return; + } + else if (lPos == -1) + { + /* Seek past end. */ + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Rewind and read forward to the appropriate index. */ + _trewinddir (dirp); + + while ((dirp->dd_stat < lPos) && _treaddir (dirp)) + ; + } +} + diff --git a/libc/mingw/misc/dirname.c b/libc/mingw/misc/dirname.c new file mode 100644 index 000000000..9c5cf87db --- /dev/null +++ b/libc/mingw/misc/dirname.c @@ -0,0 +1,183 @@ +/* dirname.c + * + * $Id: dirname.c,v 1.2 2007/03/08 23:15:58 keithmarshall Exp $ + * + * Provides an implementation of the "dirname" function, conforming + * to SUSv3, with extensions to accommodate Win32 drive designators, + * and suitable for use on native Microsoft(R) Win32 platforms. + * + * Written by Keith Marshall + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ + +#include +#include +#include +#include +#include + +#ifndef __cdecl /* If compiling on any non-Win32 platform ... */ +#define __cdecl /* this may not be defined. */ +#endif + +char * __cdecl +dirname(char *path) +{ + static char *retfail = NULL; + size_t len; + /* to handle path names for files in multibyte character locales, + * we need to set up LC_CTYPE to match the host file system locale. */ + char *locale = setlocale (LC_CTYPE, NULL); + + if (locale != NULL) + locale = strdup (locale); + setlocale (LC_CTYPE, ""); + + if (path && *path) + { + /* allocate sufficient local storage space, + * in which to create a wide character reference copy of path. */ + wchar_t refcopy[1 + (len = mbstowcs (NULL, path, 0))]; + /* create the wide character reference copy of path */ + wchar_t *refpath = refcopy; + + len = mbstowcs (refpath, path, len); + refcopy[len] = L'\0'; + /* SUSv3 identifies a special case, where path is exactly equal to "//"; + * (we will also accept "\\" in the Win32 context, but not "/\" or "\/", + * and neither will we consider paths with an initial drive designator). + * For this special case, SUSv3 allows the implementation to choose to + * return "/" or "//", (or "\" or "\\", since this is Win32); we will + * simply return the path unchanged, (i.e. "//" or "\\"). */ + if (len > 1 && (refpath[0] == L'/' || refpath[0] == L'\\')) + { + if (refpath[1] == refpath[0] && refpath[2] == L'\0') + { + setlocale (LC_CTYPE, locale); + free (locale); + return path; + } + } + /* For all other cases ... + * step over the drive designator, if present ... */ + else if (len > 1 && refpath[1] == L':') + { + /* FIXME: maybe should confirm *refpath is a valid drive designator. */ + refpath += 2; + } + /* check again, just to ensure we still have a non-empty path name ... */ + if (*refpath) + { +# undef basename +# define basename __the_basename /* avoid shadowing. */ + /* reproduce the scanning logic of the "basename" function + * to locate the basename component of the current path string, + * (but also remember where the dirname component starts). */ + wchar_t *refname, *basename; + for (refname = basename = refpath; *refpath; ++refpath) + { + if (*refpath == L'/' || *refpath == L'\\') + { + /* we found a dir separator ... + * step over it, and any others which immediately follow it. */ + while (*refpath == L'/' || *refpath == L'\\') + ++refpath; + /* if we didn't reach the end of the path string ... */ + if (*refpath) + /* then we have a new candidate for the base name. */ + basename = refpath; + else + /* we struck an early termination of the path string, + * with trailing dir separators following the base name, + * so break out of the for loop, to avoid overrun. */ + break; + } + } + /* now check, + * to confirm that we have distinct dirname and basename components. */ + if (basename > refname) + { + /* and, when we do ... + * backtrack over all trailing separators on the dirname component, + * (but preserve exactly two initial dirname separators, if identical), + * and add a NUL terminator in their place. */ + do --basename; + while (basename > refname && (*basename == L'/' || *basename == L'\\')); + if (basename == refname && (refname[0] == L'/' || refname[0] == L'\\') + && refname[1] == refname[0] && refname[2] != L'/' && refname[2] != L'\\') + ++basename; + *++basename = L'\0'; + /* if the resultant dirname begins with EXACTLY two dir separators, + * AND both are identical, then we preserve them. */ + refpath = refcopy; + while ((*refpath == L'/' || *refpath == L'\\')) + ++refpath; + if ((refpath - refcopy) > 2 || refcopy[1] != refcopy[0]) + refpath = refcopy; + /* and finally ... + * we remove any residual, redundantly duplicated separators from the dirname, + * reterminate, and return it. */ + refname = refpath; + while (*refpath) + { + if ((*refname++ = *refpath) == L'/' || *refpath++ == L'\\') + { + while (*refpath == L'/' || *refpath == L'\\') + ++refpath; + } + } + *refname = L'\0'; + /* finally ... + * transform the resolved dirname back into the multibyte char domain, + * restore the caller's locale, and return the resultant dirname. */ + if ((len = wcstombs( path, refcopy, len )) != (size_t)(-1)) + path[len] = '\0'; + } + else + { + /* either there were no dirname separators in the path name, + * or there was nothing else ... */ + if (*refname == L'/' || *refname == L'\\') + { + /* it was all separators, so return one. */ + ++refname; + } + else + { + /* there were no separators, so return '.'. */ + *refname++ = L'.'; + } + /* add a NUL terminator, in either case, + * then transform to the multibyte char domain, + * using our own buffer. */ + *refname = L'\0'; + retfail = realloc (retfail, len = 1 + wcstombs (NULL, refcopy, 0)); + wcstombs (path = retfail, refcopy, len); + } + /* restore caller's locale, clean up, and return the resolved dirname. */ + setlocale (LC_CTYPE, locale); + free (locale); + return path; + } +# undef basename + } + /* path is NULL, or an empty string; default return value is "." ... + * return this in our own buffer, regenerated by wide char transform, + * in case the caller trashed it after a previous call. + */ + retfail = realloc (retfail, len = 1 + wcstombs (NULL, L".", 0)); + wcstombs (retfail, L".", len); + /* restore caller's locale, clean up, and return the default dirname. */ + setlocale (LC_CTYPE, locale); + free (locale); + return retfail; +} diff --git a/libc/mingw/misc/execv.c b/libc/mingw/misc/execv.c new file mode 100644 index 000000000..50fd23249 --- /dev/null +++ b/libc/mingw/misc/execv.c @@ -0,0 +1,6 @@ +#include + +int __cdecl execv(const char *_Filename,char *const _ArgList[]) +{ + return _execv (_Filename, (const char *const *)_ArgList); +} diff --git a/libc/mingw/misc/execve.c b/libc/mingw/misc/execve.c new file mode 100644 index 000000000..6ab039ea1 --- /dev/null +++ b/libc/mingw/misc/execve.c @@ -0,0 +1,6 @@ +#include + +int __cdecl execve(const char *_Filename,char *const _ArgList[],char *const _Env[]) +{ + return _execve (_Filename, (const char *const *)_ArgList, (const char * const *)_Env); +} diff --git a/libc/mingw/misc/execvp.c b/libc/mingw/misc/execvp.c new file mode 100644 index 000000000..b11ab3f40 --- /dev/null +++ b/libc/mingw/misc/execvp.c @@ -0,0 +1,6 @@ +#include + +int __cdecl execvp(const char *_Filename,char *const _ArgList[]) +{ + return _execvp (_Filename, (const char *const *)_ArgList); +} diff --git a/libc/mingw/misc/execvpe.c b/libc/mingw/misc/execvpe.c new file mode 100644 index 000000000..f6fa80ad4 --- /dev/null +++ b/libc/mingw/misc/execvpe.c @@ -0,0 +1,6 @@ +#include + +int __cdecl execvpe(const char *_Filename,char *const _ArgList[],char *const _Env[]) +{ + return _execvpe (_Filename, (const char *const *)_ArgList, (const char *const *)_Env); +} diff --git a/libc/mingw/misc/feclearexcept.c b/libc/mingw/misc/feclearexcept.c new file mode 100644 index 000000000..673528b20 --- /dev/null +++ b/libc/mingw/misc/feclearexcept.c @@ -0,0 +1,74 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) +int __mingw_has_sse (void); + +int __mingw_has_sse(void) +{ + int cpuInfo[4],infoType = 1; + +#ifndef _WIN64 + int o_flag, n_flag; + + __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (o_flag)); + n_flag = o_flag ^ 0x200000; + __asm__ volatile ("pushl %0\n\tpopfl" : : "g" (n_flag)); + __asm__ volatile ("pushfl\n\tpopl %0" : "=mr" (n_flag)); + if (n_flag == o_flag) + return 0; +#endif + + __asm__ __volatile__ ( + "cpuid" + : "=a" (cpuInfo[0]), "=b" (cpuInfo[1]), "=c" (cpuInfo[2]), + "=d" (cpuInfo[3]) + : "a" (infoType)); + if (cpuInfo[3] & 0x2000000) + return 1; + return 0; +} +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ + +/* 7.6.2.1 + The feclearexcept function clears the supported exceptions + represented by its argument. */ + +int feclearexcept (int excepts) +{ + fenv_t _env; +#if defined(_ARM_) || defined(__arm__) + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + _env.__cw &= ~(excepts & FE_ALL_EXCEPT); + __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + (void) _env; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr &= ~(excepts & FE_ALL_EXCEPT); + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); +#else + int _mxcsr; + if (excepts == FE_ALL_EXCEPT) + { + __asm__ volatile ("fnclex"); + } + else + { + __asm__ volatile ("fnstenv %0" : "=m" (_env)); + _env.__status_word &= ~(excepts & FE_ALL_EXCEPT); + __asm__ volatile ("fldenv %0" : : "m" (_env)); + } + if (__mingw_has_sse ()) + { + __asm__ volatile ("stmxcsr %0" : "=m" (_mxcsr)); + _mxcsr &= ~(((excepts & FE_ALL_EXCEPT))); + __asm__ volatile ("ldmxcsr %0" : : "m" (_mxcsr)); + } +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return (0); +} diff --git a/libc/mingw/misc/fegetenv.c b/libc/mingw/misc/fegetenv.c new file mode 100644 index 000000000..31960816e --- /dev/null +++ b/libc/mingw/misc/fegetenv.c @@ -0,0 +1,39 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) +int __mingw_has_sse (void); +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ + +/* 7.6.4.1 + The fegetenv function stores the current floating-point environment + in the object pointed to by envp. */ + +int fegetenv (fenv_t * envp) +{ +#if defined(_ARM_) || defined(__arm__) + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (*envp)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + envp->__cw = fpcr; +#else + __asm__ __volatile__ ("fnstenv %0;": "=m" (*envp)); + /* fnstenv sets control word to non-stop for all exceptions, so we + need to reload our env to restore the original mask. */ + __asm__ __volatile__ ("fldenv %0" : : "m" (*envp)); + if (__mingw_has_sse ()) + { + int _mxcsr; + __asm__ __volatile__ ("stmxcsr %0" : "=m" (_mxcsr)); + envp->__unused0 = (((unsigned int) _mxcsr) >> 16); + envp->__unused1 = (((unsigned int) _mxcsr) & 0xffff); + } +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return 0; +} + diff --git a/libc/mingw/misc/fegetexceptflag.c b/libc/mingw/misc/fegetexceptflag.c new file mode 100644 index 000000000..eaa940a2a --- /dev/null +++ b/libc/mingw/misc/fegetexceptflag.c @@ -0,0 +1,39 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) +extern int __mingw_has_sse (void); +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ + +/* 7.6.2.2 + The fegetexceptflag function stores an implementation-defined + representation of the exception flags indicated by the argument + excepts in the object pointed to by the argument flagp. */ + +int fegetexceptflag (fexcept_t * flagp, int excepts) +{ +#if defined(_ARM_) || defined(__arm__) + fenv_t _env; + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + *flagp = _env.__cw & excepts & FE_ALL_EXCEPT; +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + *flagp = fpcr & excepts & FE_ALL_EXCEPT; +#else + int _mxcsr; + unsigned short _status; + + __asm__ volatile ("fnstsw %0" : "=am" (_status)); + _mxcsr = 0; + if (__mingw_has_sse ()) + __asm__ volatile ("stmxcsr %0" : "=m" (_mxcsr)); + + *flagp = (_mxcsr | _status) & excepts & FE_ALL_EXCEPT; +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return 0; +} diff --git a/libc/mingw/misc/fegetround.c b/libc/mingw/misc/fegetround.c new file mode 100644 index 000000000..d2fdb7725 --- /dev/null +++ b/libc/mingw/misc/fegetround.c @@ -0,0 +1,28 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +/* 7.6.3.1 + The fegetround function returns the value of the rounding direction + macro representing the current rounding direction. */ + +int +fegetround (void) +{ +#if defined(_ARM_) || defined(__arm__) + fenv_t _env; + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + return (_env.__cw & (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + return (fpcr & (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)); +#else + int _control; + __asm__ volatile ("fnstcw %0" : "=m" (*&_control)); + return (_control & (FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)); +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ +} diff --git a/libc/mingw/misc/feholdexcept.c b/libc/mingw/misc/feholdexcept.c new file mode 100644 index 000000000..8736faadf --- /dev/null +++ b/libc/mingw/misc/feholdexcept.c @@ -0,0 +1,35 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +/* 7.6.4.2 + The feholdexcept function saves the current floating-point + environment in the object pointed to by envp, clears the exception + flags, and then installs a non-stop (continue on exceptions) mode, + if available, for all exceptions. */ + +int feholdexcept (fenv_t * envp) +{ +#if defined(_ARM_) || defined(__arm__) + fenv_t _env; + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + envp->__cw = _env.__cw; + _env.__cw &= ~(FE_ALL_EXCEPT); + __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + envp->__cw = fpcr; + fpcr &= ~(FE_ALL_EXCEPT); + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); +#else + __asm__ __volatile__ ("fnstenv %0;" : "=m" (* envp)); /* save current into envp */ + /* fnstenv sets control word to non-stop for all exceptions, so all we + need to do is clear the exception flags. */ + __asm__ __volatile__ ("fnclex"); +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return 0; +} diff --git a/libc/mingw/misc/feraiseexcept.c b/libc/mingw/misc/feraiseexcept.c new file mode 100644 index 000000000..8ec36f732 --- /dev/null +++ b/libc/mingw/misc/feraiseexcept.c @@ -0,0 +1,36 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +/* 7.6.2.3 + The feraiseexcept function raises the supported exceptions + represented by its argument The order in which these exceptions + are raised is unspecified, except as stated in F.7.6. + Whether the feraiseexcept function additionally raises + the inexact exception whenever it raises the overflow + or underflow exception is implementation-defined. */ + +int feraiseexcept (int excepts) +{ + fenv_t _env; +#if defined(_ARM_) || defined(__arm__) + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + _env.__cw |= excepts & FE_ALL_EXCEPT; + __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + (void) _env; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr |= excepts & FE_ALL_EXCEPT; + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); +#else + __asm__ volatile ("fnstenv %0;" : "=m" (_env)); + _env.__status_word |= excepts & FE_ALL_EXCEPT; + __asm__ volatile ("fldenv %0;" + "fwait;" : : "m" (_env)); +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return 0; +} diff --git a/libc/mingw/misc/fesetenv.c b/libc/mingw/misc/fesetenv.c new file mode 100644 index 000000000..f998017b4 --- /dev/null +++ b/libc/mingw/misc/fesetenv.c @@ -0,0 +1,83 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw.h> +#include +#include + +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) +extern int __mingw_has_sse (void); +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ + +/* 7.6.4.3 + The fesetenv function establishes the floating-point environment + represented by the object pointed to by envp. The argument envp + points to an object set by a call to fegetenv or feholdexcept, or + equal the macro FE_DFL_ENV or an implementation-defined environment + macro. Note that fesetenv merely installs the state of the exception + flags represented through its argument, and does not raise these + exceptions. + */ + +extern void (* __MINGW_IMP_SYMBOL(_fpreset))(void); +extern void _fpreset(void); + +int fesetenv (const fenv_t * envp) +{ +#if defined(_ARM_) || defined(__arm__) + if (envp == FE_DFL_ENV) + /* Use the choice made at app startup */ + _fpreset(); + else + __asm__ volatile ("fmxr FPSCR, %0" : : "r" (*envp)); +#elif defined(_ARM64_) || defined(__aarch64__) + if (envp == FE_DFL_ENV) { + /* Use the choice made at app startup */ + _fpreset(); + } else { + unsigned __int64 fpcr = envp->__cw; + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); + } +#else + if (envp == FE_PC64_ENV) + /* + * fninit initializes the control register to 0x37f, + * the status register to zero and the tag word to 0FFFFh. + * The other registers are unaffected. + */ + __asm__ __volatile__ ("fninit"); + + else if (envp == FE_PC53_ENV) + /* + * MS _fpreset() does same *except* it sets control word + * to 0x27f (53-bit precison). + * We force calling _fpreset in msvcrt.dll + */ + + (* __MINGW_IMP_SYMBOL(_fpreset))(); + + else if (envp == FE_DFL_ENV) + /* Use the choice made at app startup */ + _fpreset(); + + else + { + fenv_t env = *envp; + int _mxcsr; + __asm__ ("fnstenv %0\n" + "stmxcsr %1" : "=m" (*&env), "=m" (*&_mxcsr)); + /*_mxcsr = ((int)envp->__unused0 << 16) | (int)envp->__unused1; *//* mxcsr low and high */ + env.__unused0 = 0xffff; + env.__unused1 = 0xffff; + __asm__ volatile ("fldenv %0" : : "m" (env) + : "st", "st(1)", "st(2)", "st(3)", "st(4)", + "st(5)", "st(6)", "st(7)"); + if (__mingw_has_sse ()) + __asm__ volatile ("ldmxcsr %0" : : "m" (*&_mxcsr)); + } + +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return 0; +} diff --git a/libc/mingw/misc/fesetexceptflag.c b/libc/mingw/misc/fesetexceptflag.c new file mode 100644 index 000000000..7e3361c6a --- /dev/null +++ b/libc/mingw/misc/fesetexceptflag.c @@ -0,0 +1,56 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) +extern int __mingw_has_sse (void); +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ + +/* 7.6.2.4 + The fesetexceptflag function sets the complete status for those + exception flags indicated by the argument excepts, according to the + representation in the object pointed to by flagp. The value of + *flagp shall have been set by a previous call to fegetexceptflag + whose second argument represented at least those exceptions + represented by the argument excepts. This function does not raise + exceptions, but only sets the state of the flags. */ + +int fesetexceptflag (const fexcept_t * flagp, int excepts) +{ + fenv_t _env; + + excepts &= FE_ALL_EXCEPT; + +#if defined(_ARM_) || defined(__arm__) + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + _env.__cw &= ~excepts; + _env.__cw |= (*flagp & excepts); + __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + (void) _env; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr &= ~excepts; + fpcr |= (*flagp & excepts); + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); +#else + __asm__ volatile ("fnstenv %0;" : "=m" (_env)); + _env.__status_word &= ~excepts; + _env.__status_word |= (*flagp & excepts); + __asm__ volatile ("fldenv %0;" : : "m" (_env)); + + if (__mingw_has_sse ()) + { + int sse_cw; + __asm__ volatile ("stmxcsr %0;" : "=m" (sse_cw)); + sse_cw &= ~(excepts << 7); + sse_cw |= ((*flagp & excepts) << 7); + __asm__ volatile ("ldmxcsr %0" : : "m" (sse_cw)); + } + +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return 0; +} diff --git a/libc/mingw/misc/fesetround.c b/libc/mingw/misc/fesetround.c new file mode 100644 index 000000000..624a9997d --- /dev/null +++ b/libc/mingw/misc/fesetround.c @@ -0,0 +1,57 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) +int __mingw_has_sse (void); +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ + + /* 7.6.3.2 + The fesetround function establishes the rounding direction + represented by its argument round. If the argument is not equal + to the value of a rounding direction macro, the rounding direction + is not changed. */ + +int fesetround (int mode) +{ +#if defined(_ARM_) || defined(__arm__) + fenv_t _env; + if ((mode & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) != 0) + return -1; + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + _env.__cw &= ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO); + _env.__cw |= mode; + __asm__ volatile ("fmxr FPSCR, %0" : : "r" (_env)); +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + if ((mode & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) != 0) + return -1; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + fpcr &= ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO); + fpcr |= mode; + __asm__ volatile ("msr fpcr, %0" : : "r" (fpcr)); +#else + unsigned short _cw; + if ((mode & ~(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | FE_TOWARDZERO)) + != 0) + return -1; + __asm__ volatile ("fnstcw %0;": "=m" (*&_cw)); + _cw &= ~0xc00; + _cw |= mode; + __asm__ volatile ("fldcw %0;" : : "m" (*&_cw)); + + if (__mingw_has_sse ()) + { + int mxcsr; + + __asm__ volatile ("stmxcsr %0" : "=m" (*&mxcsr)); + mxcsr &= ~0x6000; + mxcsr |= mode << 3; + __asm__ volatile ("ldmxcsr %0" : : "m" (*&mxcsr)); + } +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ + return 0; +} diff --git a/libc/mingw/misc/fetestexcept.c b/libc/mingw/misc/fetestexcept.c new file mode 100644 index 000000000..da073e6d0 --- /dev/null +++ b/libc/mingw/misc/fetestexcept.c @@ -0,0 +1,43 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include + +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) +extern int __mingw_has_sse (void); +#endif /* !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) */ + +/* 7.6.2.5 + The fetestexcept function determines which of a specified subset of + the exception flags are currently set. The excepts argument + specifies the exception flags to be queried. + The fetestexcept function returns the value of the bitwise OR of the + exception macros corresponding to the currently set exceptions + included in excepts. */ + +int fetestexcept (int excepts) +{ +#if defined(_ARM_) || defined(__arm__) + fenv_t _env; + __asm__ volatile ("fmrx %0, FPSCR" : "=r" (_env)); + return _env.__cw & excepts & FE_ALL_EXCEPT; +#elif defined(_ARM64_) || defined(__aarch64__) + unsigned __int64 fpcr; + __asm__ volatile ("mrs %0, fpcr" : "=r" (fpcr)); + return fpcr & excepts & FE_ALL_EXCEPT; +#else + unsigned short _sw; + __asm__ __volatile__ ("fnstsw %%ax" : "=a" (_sw)); + + if (__mingw_has_sse ()) + { + int sse_sw; + __asm__ __volatile__ ("stmxcsr %0;" : "=m" (sse_sw)); + _sw |= sse_sw; + } + return _sw & excepts & FE_ALL_EXCEPT; +#endif /* defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) */ +} diff --git a/libc/mingw/misc/feupdateenv.c b/libc/mingw/misc/feupdateenv.c new file mode 100644 index 000000000..4a89d0b2c --- /dev/null +++ b/libc/mingw/misc/feupdateenv.c @@ -0,0 +1,25 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +/* 7.6.4.4 + The feupdateenv function saves the currently raised exceptions in + its automatic storage, installs the floating-point environment + represented by the object pointed to by envp, and then raises the + saved exceptions. The argument envp shall point to an object + set by a call to feholdexcept or fegetenv, or equal the macro + FE_DFL_ENV or an implementation-defined environment macro. */ + +/* FIXME: this works but surely there must be a better way. */ + +int feupdateenv (const fenv_t * envp) +{ + unsigned int _fexcept = fetestexcept (FE_ALL_EXCEPT); /*save excepts */ + fesetenv (envp); /* install the env */ + feraiseexcept (_fexcept); /* raise the execept */ + return 0; +} + diff --git a/libc/mingw/misc/ftruncate.c b/libc/mingw/misc/ftruncate.c new file mode 100644 index 000000000..4ee59d67b --- /dev/null +++ b/libc/mingw/misc/ftruncate.c @@ -0,0 +1,8 @@ + +int _chsize(int _FileHandle,long _Size); +int ftruncate(int __fd,int __length); + +int ftruncate(int __fd,int __length) +{ + return _chsize (__fd,__length); +} diff --git a/libc/mingw/misc/ftw.c b/libc/mingw/misc/ftw.c new file mode 100644 index 000000000..74d05aa71 --- /dev/null +++ b/libc/mingw/misc/ftw.c @@ -0,0 +1,463 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef IMPL_FTW64 +#define stat stat64 +#define nftw nftw64 +#define ftw ftw64 +#endif + +typedef struct dir_data_t { + DIR *h; + char *buf; +} dir_data_t; + +typedef struct node_t { + struct node_t *l, *r; + unsigned int colored : 1; +} node_t; + +typedef struct ctx_t { + node_t *objs; + dir_data_t **dirs; + char *buf; + struct FTW ftw; + int (*fcb) (const char *, const struct stat *, int , struct FTW *); + size_t cur_dir, msz_dir, buf_sz; + int flags; + dev_t dev; +} ctx_t; + +static int add_object (ctx_t *); +static int do_dir (ctx_t *, struct stat *, dir_data_t *); +static int do_entity (ctx_t *, dir_data_t *, const char *, size_t); +static int do_it (const char *, int, void *, int, int); + +static int open_directory (ctx_t *, dir_data_t *); + +static void +prepare_for_insert (int forced, node_t **bp, node_t **pp1, node_t **pp2, int p1_c, int p2_c) +{ + node_t *p1, *p2, **rp, **lp, *b = *bp; + + rp = &(*bp)->r; + lp = &(*bp)->l; + + if (!forced && ((*lp) == NULL || (*lp)->colored == 0 || (*rp) == NULL || (*rp)->colored == 0)) + return; + + b->colored = 1; + + if (*rp) + (*rp)->colored = 0; + + if (*lp) + (*lp)->colored = 0; + + if (!pp1 || (*pp1)->colored == 0) + return; + + p1 = *pp1; + p2 = *pp2; + + if ((p1_c > 0) == (p2_c > 0)) + { + *pp2 = *pp1; + p1->colored = 0; + p2->colored = 1; + *(p1_c < 0 ? &p2->l : &p2->r) = (p1_c < 0 ? p1->r : p1->l); + *(p1_c < 0 ? &p1->r : &p1->l) = p2; + return; + } + + b->colored = 0; + p1->colored = p2->colored = 1; + *(p1_c < 0 ? &p1->l : &p1->r) = (p1_c < 0 ? *rp : *lp); + *(p1_c < 0 ? rp : lp) = p1; + *(p1_c < 0 ? &p2->r : &p2->l) = (p1_c < 0 ? *lp : *rp); + *(p1_c < 0 ? lp : rp) = p2; + *pp2 = b; +} + +static int +add_object (ctx_t *ctx) +{ + node_t **bp, **np, *b, *n, **pp1 = NULL, **pp2 = NULL; + int c = 0, p1_c = 0, p2_c = 0; + + if (ctx->objs) + ctx->objs->colored = 0; + + np = bp = &ctx->objs; + + if (ctx->objs != NULL) + { + c = 1; + + do + { + b = *bp; + prepare_for_insert (0, bp, pp1, pp2, p1_c, p2_c); + np = &b->r; + + if (*np == NULL) + break; + + pp2 = pp1; + p2_c = p1_c; + pp1 = bp; + p1_c = 1; + bp = np; + } + while (*np != NULL); + } + + if (!(n = (node_t *) malloc (sizeof (node_t)))) + return -1; + + *np = n; + n->l = n->r = NULL; + n->colored = 1; + + if (np != bp) + prepare_for_insert (1, np, bp, pp1, c, p1_c); + + return 0; +} + +static int +open_directory (ctx_t *ctx, dir_data_t *dirp) +{ + DIR *st; + struct dirent *d; + char *buf, *h; + size_t cur_sz, buf_sz, sz; + int sv_e, ret = 0; + + if (ctx->dirs[ctx->cur_dir] != NULL) + { + if (!(buf = malloc (1024))) + return -1; + + st = ctx->dirs[ctx->cur_dir]->h; + + buf_sz = 1024; + cur_sz = 0; + + while ((d = readdir (st)) != NULL) + { + sz = strlen (d->d_name); + + if ((cur_sz + sz + 2) >= buf_sz) + { + buf_sz += ((2 * sz) < 1024 ? 1024 : (2 * sz)); + if (!(h = (char *) realloc (buf, buf_sz))) + { + sv_e = errno; + free (buf); + errno = (sv_e); + + return -1; + } + + buf = h; + } + + *((char *) memcpy (buf + cur_sz, d->d_name, sz) + sz) = 0; + cur_sz += sz + 1; + } + + buf[cur_sz++] = 0; + + ctx->dirs[ctx->cur_dir]->buf = realloc (buf, cur_sz); + + if (ctx->dirs[ctx->cur_dir]->buf == NULL) + { + sv_e = errno; + free (buf); + errno = sv_e; + ret = -1; + } + else + { + closedir (st); + + ctx->dirs[ctx->cur_dir]->h = NULL; + ctx->dirs[ctx->cur_dir] = NULL; + } + } + + if (!ret) + { + dirp->h = opendir (ctx->buf); + + if (dirp->h == NULL) + ret = -1; + else + { + dirp->buf = NULL; + ctx->dirs[ctx->cur_dir] = dirp; + ctx->cur_dir += 1; + + if (ctx->cur_dir == ctx->msz_dir) + ctx->cur_dir = 0; + } + } + + return ret; +} + + +static int +do_entity (ctx_t *ctx, dir_data_t *dir, const char *name, size_t namlen) +{ + struct stat st; + char *h; + size_t cnt_sz; + int ret = 0, flag = 0; + + if (name[0] == '.' && (name[1] == 0 || (name[1] == '.' && name[2] == 0))) + return 0; + + cnt_sz = ctx->ftw.base + namlen + 2; + + if (ctx->buf_sz < cnt_sz) + { + ctx->buf_sz = cnt_sz * 2; + + if (!(h = (char *) realloc (ctx->buf, ctx->buf_sz))) + return -1; + + ctx->buf = h; + } + + *((char *) memcpy (ctx->buf + ctx->ftw.base, name, namlen) + namlen) = 0; + + name = ctx->buf; + + if (stat (name, &st) < 0) + { + if (errno != EACCES && errno != ENOENT) + ret = -1; + else + flag = FTW_NS; + + if (!(ctx->flags & FTW_PHYS)) + stat (name, &st); + } + else + flag = (S_ISDIR (st.st_mode) ? FTW_D : FTW_F); + + if (!ret && (flag == FTW_NS || !(ctx->flags & FTW_MOUNT) || st.st_dev == ctx->dev)) + { + if (flag == FTW_D) + { + if ((ctx->flags & FTW_PHYS) || !(ret = add_object (ctx))) + ret = do_dir (ctx, &st, dir); + } + else + ret = (*ctx->fcb) (ctx->buf, &st, flag, &ctx->ftw); + } + + if ((ctx->flags & FTW_ACTIONRETVAL) && ret == FTW_SKIP_SUBTREE) + ret = 0; + + return ret; +} + + +static int +do_dir (ctx_t *ctx, struct stat *st, __UNUSED_PARAM(dir_data_t *old_dir)) +{ + dir_data_t dir; + struct dirent *d; + char *startp, *runp, *endp; + int sv_e, ret, previous_base = ctx->ftw.base; + + if ((ret = open_directory (ctx, &dir)) != 0) + { + if (errno == EACCES) + ret = (*ctx->fcb) (ctx->buf, st, FTW_DNR, &ctx->ftw); + + return ret; + } + + if (!(ctx->flags & FTW_DEPTH) && (ret = (*ctx->fcb) (ctx->buf, st, FTW_D, &ctx->ftw)) != 0) + { + sv_e = errno; + closedir (dir.h); + errno = sv_e; + + if (ctx->cur_dir-- == 0) + ctx->cur_dir = ctx->msz_dir - 1; + + ctx->dirs[ctx->cur_dir] = NULL; + + return ret; + } + + ctx->ftw.level += 1; + startp = memchr (ctx->buf, 0, 1024); + + if (startp[-1] != '/') + *startp++ = '/'; + + ctx->ftw.base = (startp - ctx->buf); + + while (dir.h != NULL && (d = readdir (dir.h)) != NULL + && !(ret = do_entity (ctx, &dir, d->d_name, strlen (d->d_name)))) + ; + + if (dir.h != NULL) + { + sv_e = errno; + closedir (dir.h); + errno = sv_e; + + if (ctx->cur_dir-- == 0) + ctx->cur_dir = ctx->msz_dir - 1; + + ctx->dirs[ctx->cur_dir] = NULL; + } + else + { + runp = dir.buf; + + while (!ret && *runp != 0) + { + endp = strchr (runp, 0); + ret = do_entity (ctx, &dir, runp, endp - runp); + runp = endp + 1; + } + + sv_e = errno; + free (dir.buf); + errno = sv_e; + } + + if ((ctx->flags & FTW_ACTIONRETVAL) && ret == FTW_SKIP_SIBLINGS) + ret = 0; + + ctx->buf[ctx->ftw.base - 1] = 0; + ctx->ftw.level -= 1; + ctx->ftw.base = previous_base; + + if (!ret && (ctx->flags & FTW_DEPTH)) + ret = (*ctx->fcb) (ctx->buf, st, FTW_DP, &ctx->ftw); + + return ret; +} + +static void +free_objs (node_t *r) +{ + if (r->l) + free_objs (r->l); + + if (r->r) + free_objs (r->r); + + free (r); +} + +static int +do_it (const char *dir, __UNUSED_PARAM(int is_nftw), void *fcb, int descriptors, int flags) +{ + struct ctx_t ctx; + struct stat st; + int ret = 0; + int sv_e; + char *cp; + + if (dir[0] == 0) + { + errno = (ENOENT); + return -1; + } + + ctx.msz_dir = descriptors < 1 ? 1 : descriptors; + ctx.cur_dir = 0; + ctx.dirs = (dir_data_t **) alloca (ctx.msz_dir * sizeof (dir_data_t *)); + memset (ctx.dirs, 0, ctx.msz_dir * sizeof (dir_data_t *)); + + ctx.buf_sz = 2 * strlen (dir); + + if (ctx.buf_sz <= 1024) + ctx.buf_sz = 1024; + + ctx.buf = (char *) malloc (ctx.buf_sz); + + if (ctx.buf == NULL) + return -1; + + cp = strcpy (ctx.buf, dir) + strlen (dir); + + while (cp > (ctx.buf + 1) && cp[-1] == '/') + --cp; + + *cp = 0; + + while (cp > ctx.buf && cp[-1] != '/') + --cp; + + ctx.ftw.level = 0; + ctx.ftw.base = cp - ctx.buf; + ctx.flags = flags; + ctx.fcb = (int (*) (const char *, const struct stat *, int , struct FTW *)) fcb; + ctx.objs = NULL; + + if (!ret) + { + if (stat (ctx.buf, &st) < 0) + ret = -1; + else if (S_ISDIR (st.st_mode)) + { + ctx.dev = st.st_dev; + + if (!(flags & FTW_PHYS)) + ret = add_object (&ctx); + + if (!ret) + ret = do_dir (&ctx, &st, NULL); + } + else + ret = (*ctx.fcb) (ctx.buf, &st, FTW_F, &ctx.ftw); + + if ((flags & FTW_ACTIONRETVAL) && (ret == FTW_SKIP_SUBTREE || ret == FTW_SKIP_SIBLINGS)) + ret = 0; + } + + sv_e = errno; + if (ctx.objs) + free_objs (ctx.objs); + free (ctx.buf); + errno = (sv_e); + + return ret; +} + +int +ftw (const char *path, int (*fcb) (const char *, const struct stat *, int), int descriptors) +{ + return do_it (path, 0, fcb, descriptors, 0); +} + +int +nftw (const char *path, int (*fcb) (const char *, const struct stat *, int , struct FTW *), int descriptors, int flags) +{ + return do_it (path, 1, fcb, descriptors, flags); +} diff --git a/libc/mingw/misc/ftw64.c b/libc/mingw/misc/ftw64.c new file mode 100644 index 000000000..3e45847ef --- /dev/null +++ b/libc/mingw/misc/ftw64.c @@ -0,0 +1,8 @@ +/** + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER within this package. + */ + +#define IMPL_FTW64 1 + +#include "ftw.c" diff --git a/libc/mingw/misc/fwide.c b/libc/mingw/misc/fwide.c new file mode 100644 index 000000000..a9662f404 --- /dev/null +++ b/libc/mingw/misc/fwide.c @@ -0,0 +1,23 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#define __CRT__NO_INLINE +#include +#include + +#if 0 +int fwide(FILE *stream,int mode) +{ + return -1; /* limited to byte orientation */ +} +#endif + +int __cdecl fwide(FILE *_F,int _M) +{ + (void)_F; + return (_M); +} + diff --git a/libc/mingw/misc/getlogin.c b/libc/mingw/misc/getlogin.c new file mode 100644 index 000000000..cb130f30b --- /dev/null +++ b/libc/mingw/misc/getlogin.c @@ -0,0 +1,22 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include +#include + +char *getlogin(void); + +char *getlogin(void) +{ + static char user_name[MAX_PATH]; + DWORD length = sizeof (user_name); + + if (GetUserName (user_name, &length)) + return user_name; + return NULL; +} + diff --git a/libc/mingw/misc/getopt.c b/libc/mingw/misc/getopt.c new file mode 100644 index 000000000..ac1fda426 --- /dev/null +++ b/libc/mingw/misc/getopt.c @@ -0,0 +1,562 @@ +/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +#undef optreset /* see getopt.h */ +#define optreset __mingw_optreset +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#ifndef __CYGWIN__ +#define __progname __argv[0] +#else +extern char __declspec(dllimport) *__progname; +#endif + +#ifdef __CYGWIN__ +static char EMSG[] = ""; +#else +#define EMSG "" +#endif + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +static void +_vwarnx(const char *fmt,va_list ap) +{ + (void)fprintf(stderr,"%s: ",__progname); + if (fmt != NULL) + (void)vfprintf(stderr,fmt,ap); + (void)fprintf(stderr,"\n"); +} + +static void +warnx(const char *fmt,...) +{ + va_list ap; + va_start(ap,fmt); + _vwarnx(fmt,ap); + va_end(ap); +} + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, ambiguous, match; + +#define IDENTICAL_INTERPRETATION(_x, _y) \ + (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ + long_options[(_x)].flag == long_options[(_y)].flag && \ + long_options[(_x)].val == long_options[(_y)].val) + + current_argv = place; + match = -1; + ambiguous = 0; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + ambiguous = 0; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else if (!IDENTICAL_INTERPRETATION(i, match)) + ambiguous = 1; + } + if (ambiguous) { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +#undef IDENTICAL_INTERPRETATION +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + * + * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or + * optreset != 0 for GNU compatibility. + */ + if (posixly_correct == -1 || optreset != 0) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); + if (*options == '-') + flags |= FLAG_ALLARGS; + else if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + if (*options == '+' || *options == '-') + options++; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} diff --git a/libc/mingw/misc/gettimeofday.c b/libc/mingw/misc/gettimeofday.c new file mode 100644 index 000000000..50ffcfc7c --- /dev/null +++ b/libc/mingw/misc/gettimeofday.c @@ -0,0 +1,73 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include +#include +#include + +#define FILETIME_1970 116444736000000000ull /* seconds between 1/1/1601 and 1/1/1970 */ +#define HECTONANOSEC_PER_SEC 10000000ull + +int getntptimeofday (struct timespec *, struct timezone *); + +int getntptimeofday (struct timespec *tp, struct timezone *z) +{ + int res = 0; + union { + unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } _now; + TIME_ZONE_INFORMATION TimeZoneInformation; + DWORD tzi; + + if (z != NULL) + { + if ((tzi = GetTimeZoneInformation(&TimeZoneInformation)) != TIME_ZONE_ID_INVALID) { + z->tz_minuteswest = TimeZoneInformation.Bias; + if (tzi == TIME_ZONE_ID_DAYLIGHT) + z->tz_dsttime = 1; + else + z->tz_dsttime = 0; + } + else + { + z->tz_minuteswest = 0; + z->tz_dsttime = 0; + } + } + + if (tp != NULL) { + GetSystemTimeAsFileTime (&_now.ft); /* 100-nanoseconds since 1-1-1601 */ + /* The actual accuracy on XP seems to be 125,000 nanoseconds = 125 microseconds = 0.125 milliseconds */ + _now.ns100 -= FILETIME_1970; /* 100 nano-seconds since 1-1-1970 */ + tp->tv_sec = _now.ns100 / HECTONANOSEC_PER_SEC; /* seconds since 1-1-1970 */ + tp->tv_nsec = (long) (_now.ns100 % HECTONANOSEC_PER_SEC) * 100; /* nanoseconds */ + } + return res; +} + +int __cdecl gettimeofday (struct timeval *p, void *z) +{ + struct timespec tp; + + if (getntptimeofday (&tp, (struct timezone *) z)) + return -1; + p->tv_sec=tp.tv_sec; + p->tv_usec=(tp.tv_nsec/1000); + return 0; +} + +int __cdecl mingw_gettimeofday (struct timeval *p, struct timezone *z) +{ + struct timespec tp; + + if (getntptimeofday (&tp, z)) + return -1; + p->tv_sec=tp.tv_sec; + p->tv_usec=(tp.tv_nsec/1000); + return 0; +} diff --git a/libc/mingw/misc/imaxabs.c b/libc/mingw/misc/imaxabs.c new file mode 100644 index 000000000..2ee550d1e --- /dev/null +++ b/libc/mingw/misc/imaxabs.c @@ -0,0 +1,22 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + This source code was extracted from the Q8 package created and + placed in the PUBLIC DOMAIN by Doug Gwyn + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E). + + This particular implementation requires the matching . +*/ +#define __CRT__NO_INLINE +#include + +intmax_t +imaxabs (intmax_t _j) + { return _j >= 0 ? _j : -_j; } + +long long __attribute__ ((alias ("imaxabs"))) llabs (long long); diff --git a/libc/mingw/misc/imaxdiv.c b/libc/mingw/misc/imaxdiv.c new file mode 100644 index 000000000..6faf4943a --- /dev/null +++ b/libc/mingw/misc/imaxdiv.c @@ -0,0 +1,31 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + This source code was extracted from the Q8 package created and + placed in the PUBLIC DOMAIN by Doug Gwyn + last edit: 1999/11/05 gwyn@arl.mil + + + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E). + +*/ + +#include +#include + +imaxdiv_t +imaxdiv(intmax_t numer, intmax_t denom) +{ + imaxdiv_t result; + result.quot = numer / denom; + result.rem = numer % denom; + return result; +} + +lldiv_t __attribute__ ((alias ("imaxdiv"))) +lldiv (long long, long long); diff --git a/libc/mingw/misc/isblank.c b/libc/mingw/misc/isblank.c new file mode 100644 index 000000000..ce6247c1c --- /dev/null +++ b/libc/mingw/misc/isblank.c @@ -0,0 +1,7 @@ +#define __NO_CTYPE_LINES +#include + +int __cdecl isblank (int _C) +{ + return (_isctype(_C, _BLANK) || _C == '\t'); +} diff --git a/libc/mingw/misc/iswblank.c b/libc/mingw/misc/iswblank.c new file mode 100644 index 000000000..bdf73e564 --- /dev/null +++ b/libc/mingw/misc/iswblank.c @@ -0,0 +1,7 @@ +#define _CRT_WCTYPE_NOINLINE +#include + +int __cdecl iswblank (wint_t _C) +{ + return (iswctype(_C, _BLANK) || _C == '\t'); +} diff --git a/libc/mingw/misc/mb_wc_common.h b/libc/mingw/misc/mb_wc_common.h new file mode 100644 index 000000000..c640fb776 --- /dev/null +++ b/libc/mingw/misc/mb_wc_common.h @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include <_mingw.h> + +unsigned int __cdecl ___lc_codepage_func(void); diff --git a/libc/mingw/misc/mbrtowc.c b/libc/mingw/misc/mbrtowc.c new file mode 100644 index 000000000..c3091cb4b --- /dev/null +++ b/libc/mingw/misc/mbrtowc.c @@ -0,0 +1,159 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include "mb_wc_common.h" +#include +#include +#include +#include + +static int __MINGW_ATTRIB_NONNULL(1) __MINGW_ATTRIB_NONNULL(4) +__mbrtowc_cp (wchar_t * __restrict__ pwc, const char * __restrict__ s, + size_t n, mbstate_t* __restrict__ ps, + const unsigned int cp, const unsigned int mb_max) +{ + union { + mbstate_t val; + char mbcs[4]; + } shift_state; + + /* Do the prelim checks */ + if (s == NULL) + return 0; + + if (n == 0) + /* The standard doesn't mention this case explicitly. Tell + caller that the conversion from a non-null s is incomplete. */ + return -2; + + /* Save the current shift state, in case we need it in DBCS case. */ + shift_state.val = *ps; + *ps = 0; + + if (!*s) + { + *pwc = 0; + return 0; + } + + if (mb_max > 1) + { + if (shift_state.mbcs[0] != 0) + { + /* Complete the mb char with the trailing byte. */ + shift_state.mbcs[1] = *s; /* the second byte */ + if (MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, + shift_state.mbcs, 2, pwc, 1) + == 0) + { + /* An invalid trailing byte */ + errno = EILSEQ; + return -1; + } + return 2; + } + else if (IsDBCSLeadByteEx (cp, *s)) + { + /* If told to translate one byte, just save the leadbyte + in *ps. */ + if (n < 2) + { + ((char*) ps)[0] = *s; + return -2; + } + /* Else translate the first two bytes */ + else if (MultiByteToWideChar (cp, MB_ERR_INVALID_CHARS, + s, 2, pwc, 1) + == 0) + { + errno = EILSEQ; + return -1; + } + return 2; + } + } + + /* Fall through to single byte char */ + if (cp == 0) + *pwc = (wchar_t)(unsigned char)*s; + + else if (MultiByteToWideChar (cp, MB_ERR_INVALID_CHARS, s, 1, pwc, 1) + == 0) + { + errno = EILSEQ; + return -1; + } + + return 1; +} + +size_t +mbrtowc (wchar_t * __restrict__ pwc, const char * __restrict__ s, + size_t n, mbstate_t* __restrict__ ps) +{ + static mbstate_t internal_mbstate = 0; + wchar_t byte_bucket = 0; + wchar_t* dst = pwc ? pwc : &byte_bucket; + + return (size_t) __mbrtowc_cp (dst, s, n, ps ? ps : &internal_mbstate, + ___lc_codepage_func(), MB_CUR_MAX); +} + + +size_t +mbsrtowcs (wchar_t* __restrict__ dst, const char ** __restrict__ src, + size_t len, mbstate_t* __restrict__ ps) +{ + int ret =0 ; + size_t n = 0; + static mbstate_t internal_mbstate = 0; + mbstate_t* internal_ps = ps ? ps : &internal_mbstate; + const unsigned int cp = ___lc_codepage_func(); + const unsigned int mb_max = MB_CUR_MAX; + + if (src == NULL || *src == NULL) /* undefined behavior */ + return 0; + + if (dst != NULL) + { + while (n < len + && (ret = __mbrtowc_cp(dst, *src, len - n, + internal_ps, cp, mb_max)) + > 0) + { + ++dst; + *src += ret; + n += ret; + } + + if (n < len && ret == 0) + *src = (char *)NULL; + } + else + { + wchar_t byte_bucket = 0; + while ((ret = __mbrtowc_cp (&byte_bucket, *src, mb_max, + internal_ps, cp, mb_max)) + > 0) + { + *src += ret; + n += ret; + } + } + return n; +} + +size_t +mbrlen (const char * __restrict__ s, size_t n, + mbstate_t * __restrict__ ps) +{ + static mbstate_t s_mbstate = 0; + wchar_t byte_bucket = 0; + return __mbrtowc_cp (&byte_bucket, s, n, (ps) ? ps : &s_mbstate, + ___lc_codepage_func(), MB_CUR_MAX); +} diff --git a/libc/mingw/misc/mbsinit.c b/libc/mingw/misc/mbsinit.c new file mode 100644 index 000000000..d745402d7 --- /dev/null +++ b/libc/mingw/misc/mbsinit.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* This source code was extracted from the Q8 package created and placed + in the PUBLIC DOMAIN by Doug Gwyn + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.24 of ISO/IEC 9899:1999 (E). + + It supports an encoding where all char codes are mapped + to the *same* code values within a wchar_t or wint_t, + so long as no other wchar_t codes are used by the program. + +*/ + +#define __CRT__NO_INLINE +#include + +#if 0 +int mbsinit(const mbstate_t *ps) +{ + return 1; /* don't have shift states */ +} +#endif + +int __cdecl mbsinit(const mbstate_t *_P) +{ + return (!_P || *_P == 0); +} + diff --git a/libc/mingw/misc/mempcpy.c b/libc/mingw/misc/mempcpy.c new file mode 100644 index 000000000..f4e7ed9f6 --- /dev/null +++ b/libc/mingw/misc/mempcpy.c @@ -0,0 +1,12 @@ +#define __CRT__NO_INLINE +#include + +void * __cdecl +mempcpy (void *d, const void *s, size_t len) +{ + char *r = ((char *) d) + len; + if (len != 0) + memcpy (d, s, len); + return r; +} + diff --git a/libc/mingw/misc/mingw-aligned-malloc.c b/libc/mingw/misc/mingw-aligned-malloc.c new file mode 100644 index 000000000..ca5f866e2 --- /dev/null +++ b/libc/mingw/misc/mingw-aligned-malloc.c @@ -0,0 +1,123 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + __mingw_aligned_malloc and friends, implemented using Microsoft's public + interfaces and with the help of the algorithm description provided + by Wu Yongwei: http://sourceforge.net/mailarchive/message.php?msg_id=3847075 + + I hereby place this implementation in the public domain. + -- Steven G. Johnson (stevenj@alum.mit.edu) +*/ + +#include +#include +#include /* ptrdiff_t */ +#include /* uintptr_t */ +#include /* memmove */ + +/* Forward declarations: */ +void *__mingw_aligned_offset_malloc (size_t, size_t, size_t); + +#define NOT_POWER_OF_TWO(n) (((n) & ((n) - 1))) +#define UI(p) ((uintptr_t) (p)) +#define CP(p) ((char *) p) + +#define PTR_ALIGN(p0, alignment, offset) \ + ((void *) (((UI(p0) + (alignment + sizeof(void*)) + offset) \ + & (~UI(alignment - 1))) \ + - offset)) + +/* Pointer must sometimes be aligned; assume sizeof(void*) is a power of two. */ +#define ORIG_PTR(p) (*(((void **) (UI(p) & (~UI(sizeof(void*) - 1)))) - 1)) + +void * +__mingw_aligned_offset_malloc (size_t size, size_t alignment, size_t offset) +{ + void *p0, *p; + + if (NOT_POWER_OF_TWO (alignment)) + { + errno = EINVAL; + return ((void *) 0); + } + if (size == 0) + return ((void *) 0); + if (alignment < sizeof (void *)) + alignment = sizeof (void *); + + /* Including the extra sizeof(void*) is overkill on a 32-bit + machine, since malloc is already 8-byte aligned, as long + as we enforce alignment >= 8 ...but oh well. */ + + p0 = malloc (size + (alignment + sizeof (void *))); + if (!p0) + return ((void *) 0); + p = PTR_ALIGN (p0, alignment, offset); + ORIG_PTR (p) = p0; + return p; +} + +void * +__mingw_aligned_malloc (size_t size, size_t alignment) +{ + return __mingw_aligned_offset_malloc (size, alignment, 0); +} + +void +__mingw_aligned_free (void *memblock) +{ + if (memblock) + free (ORIG_PTR (memblock)); +} + +void * +__mingw_aligned_offset_realloc (void *memblock, size_t size, + size_t alignment, size_t offset) +{ + void *p0, *p; + ptrdiff_t shift; + + if (!memblock) + return __mingw_aligned_offset_malloc (size, alignment, offset); + if (NOT_POWER_OF_TWO (alignment)) + goto bad; + if (size == 0) + { + __mingw_aligned_free (memblock); + return ((void *) 0); + } + if (alignment < sizeof (void *)) + alignment = sizeof (void *); + + p0 = ORIG_PTR (memblock); + /* It is an error for the alignment to change. */ + if (memblock != PTR_ALIGN (p0, alignment, offset)) + goto bad; + shift = CP (memblock) - CP (p0); + + p0 = realloc (p0, size + (alignment + sizeof (void *))); + if (!p0) + return ((void *) 0); + p = PTR_ALIGN (p0, alignment, offset); + + /* Relative shift of actual data may be different from before, ugh. */ + if (shift != CP (p) - CP (p0)) + /* ugh, moves more than necessary if size is increased. */ + memmove (CP (p), CP (p0) + shift, size); + + ORIG_PTR (p) = p0; + return p; + +bad: + errno = EINVAL; + return ((void *) 0); +} + +void * +__mingw_aligned_realloc (void *memblock, size_t size, size_t alignment) +{ + return __mingw_aligned_offset_realloc (memblock, size, alignment, 0); +} diff --git a/libc/mingw/misc/mingw-fseek.c b/libc/mingw/misc/mingw-fseek.c new file mode 100644 index 000000000..3ae7d8567 --- /dev/null +++ b/libc/mingw/misc/mingw-fseek.c @@ -0,0 +1,104 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include +#include + +#define ZEROBLOCKSIZE 512 +static int __mingw_fseek_called; + +int __mingw_fseek (FILE *fp, int offset, int whence); + +int +__mingw_fseek (FILE *fp, int offset, int whence) +{ +# undef fseek + __mingw_fseek_called = 1; + return fseek (fp, offset, whence); +} + +int __mingw_fseeko64 (FILE *fp, long offset, int whence); + +int +__mingw_fseeko64 (FILE *fp, long offset, int whence) +{ +# undef fseeko64 + __mingw_fseek_called = 1; + return fseeko64 (fp, offset, whence); +} + +size_t __mingw_fwrite (const void *buffer, size_t size, size_t count, FILE *fp); + +size_t +__mingw_fwrite (const void *buffer, size_t size, size_t count, FILE *fp) +{ +# undef fwrite + if ((_osver & 0x8000) && __mingw_fseek_called) + { + ULARGE_INTEGER actual_length; + LARGE_INTEGER current_position; + + memset (¤t_position, 0, sizeof (LARGE_INTEGER)); + __mingw_fseek_called = 0; + fflush (fp); + actual_length.LowPart = GetFileSize ((HANDLE) _get_osfhandle (fileno (fp)), + &actual_length.HighPart); + if (actual_length.LowPart == 0xFFFFFFFF + && GetLastError() != NO_ERROR ) + return -1; + current_position.LowPart = SetFilePointer ((HANDLE) _get_osfhandle (fileno (fp)), + current_position.LowPart, + ¤t_position.HighPart, + FILE_CURRENT); + if (current_position.LowPart == 0xFFFFFFFF + && GetLastError() != NO_ERROR ) + return -1; + +#ifdef DEBUG + printf ("__mingw_fwrite: current %I64u, actual %I64u\n", + current_position.QuadPart, actual_length.QuadPart); +#endif /* DEBUG */ + if ((size_t)current_position.QuadPart > (size_t)actual_length.QuadPart) + { + static char __mingw_zeros[ZEROBLOCKSIZE]; + long long numleft; + + SetFilePointer ((HANDLE) _get_osfhandle (fileno (fp)), + 0, 0, FILE_END); + numleft = current_position.QuadPart - actual_length.QuadPart; + +#ifdef DEBUG + printf ("__mingw_fwrite: Seeking %I64d bytes past end\n", numleft); +#endif /* DEBUG */ + while (numleft > 0LL) + { + DWORD nzeros = (numleft > ZEROBLOCKSIZE) + ? ZEROBLOCKSIZE : numleft; + DWORD written; + if (! WriteFile ((HANDLE) _get_osfhandle (fileno (fp)), + __mingw_zeros, nzeros, &written, NULL)) + { + /* Best we can hope for, or at least DJ says so. */ + SetFilePointer ((HANDLE) _get_osfhandle (fileno (fp)), + 0, 0, FILE_BEGIN); + return -1; + } + if (written < nzeros) + { + /* Likewise. */ + SetFilePointer ((HANDLE) _get_osfhandle (fileno (fp)), + 0, 0, FILE_BEGIN); + return -1; + } + + numleft -= written; + } + FlushFileBuffers ((HANDLE) _get_osfhandle (fileno (fp))); + } + } + return fwrite (buffer, size, count, fp); +} diff --git a/libc/mingw/misc/mingw_getsp.S b/libc/mingw/misc/mingw_getsp.S new file mode 100644 index 000000000..5d224d140 --- /dev/null +++ b/libc/mingw/misc/mingw_getsp.S @@ -0,0 +1,152 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + + .file "mingw_getsp.S" + .text +#ifdef _WIN64 + .align 8 +#else + .align 4 +#endif + .globl __MINGW_USYMBOL(mingw_getsp) + .def __MINGW_USYMBOL(mingw_getsp); .scl 2; .type 32; .endef +__MINGW_USYMBOL(mingw_getsp): +#if defined(_AMD64_) || defined(__x86_64__) + leaq 8(%rsp),%rax + ret +#elif defined(_X86_) || defined(__i386__) + lea 4(%esp),%eax + ret +#elif defined(_ARM_) || defined(__arm__) + mov r0, sp + bx lr +#elif defined(_ARM64_) || defined(__aarch64__) + mov x0, sp + ret +#endif + +/* On ARM: + * Error: cannot represent BFD_RELOC_32_PCREL relocation in this object file format + * But anyway, nothing is needed here as libarm32/libmsvcrt.a is exporting longjmp + ldr ip, 1f + ldr pc, [pc, ip] + 1: .long __imp_longjmp - (1b + 4) +*/ +#if !(defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__)) + .globl __MINGW_USYMBOL(longjmp) + .def __MINGW_USYMBOL(longjmp); .scl 2; .type 32; .endef +__MINGW_USYMBOL(longjmp): +#if defined(_AMD64_) || defined(__x86_64__) +#ifndef __SEH__ + xorq %rax,%rax + movq %rax, (%rcx) +#endif + leaq __MINGW_IMP_LSYMBOL(longjmp)(%rip), %rax + jmpq *(%rax) +#elif defined(_X86_) || defined(__i386__) + jmp *__imp__longjmp +#endif +#endif /* !(defined(_ARM_) || defined(__arm__)) */ + +#if defined(_ARM_) || defined(__arm__) || defined(_ARM64_) || defined(__aarch64__) + .globl __MINGW_USYMBOL(__mingw_setjmp) + .def __MINGW_USYMBOL(__mingw_setjmp); .scl 2; .type 32; .endef +__MINGW_USYMBOL(__mingw_setjmp): +#if defined(_ARM_) || defined(__arm__) + mov r1, #0 + str r1, [r0] /* jmp_buf->Frame */ + str r4, [r0, #0x4] /* jmp_buf->R4 */ + str r5, [r0, #0x8] /* jmp_buf->R5 */ + str r6, [r0, #0xc] /* jmp_buf->R6 */ + str r7, [r0, #0x10] /* jmp_buf->R7 */ + str r8, [r0, #0x14] /* jmp_buf->R8 */ + str r9, [r0, #0x18] /* jmp_buf->R9 */ + str r10, [r0, #0x1c] /* jmp_buf->R10 */ + str r11, [r0, #0x20] /* jmp_buf->R11 */ + str sp, [r0, #0x24] /* jmp_buf->Sp */ + str lr, [r0, #0x28] /* jmp_buf->Pc */ + vmrs r2, fpscr + str r2, [r0, #0x2c] /* jmp_buf->Fpscr */ + vstr d8, [r0, #0x30] /* jmp_buf->D[0] */ + vstr d9, [r0, #0x38] /* jmp_buf->D[1] */ + vstr d10, [r0, #0x40] /* jmp_buf->D[2] */ + vstr d11, [r0, #0x48] /* jmp_buf->D[3] */ + vstr d12, [r0, #0x50] /* jmp_buf->D[4] */ + vstr d13, [r0, #0x58] /* jmp_buf->D[5] */ + vstr d14, [r0, #0x60] /* jmp_buf->D[6] */ + vstr d15, [r0, #0x68] /* jmp_buf->D[7] */ + mov r0, #0 + bx lr +#elif defined(_ARM64_) || defined(__aarch64__) + str xzr, [x0] /* jmp_buf->Frame */ + stp x19, x20, [x0, #0x10] /* jmp_buf->X19, X20 */ + stp x21, x22, [x0, #0x20] /* jmp_buf->X21, X22 */ + stp x23, x24, [x0, #0x30] /* jmp_buf->X23, X24 */ + stp x25, x26, [x0, #0x40] /* jmp_buf->X25, X26 */ + stp x27, x28, [x0, #0x50] /* jmp_buf->X27, X28 */ + stp x29, x30, [x0, #0x60] /* jmp_buf->Fp, Lr */ + mov x2, sp + str x2, [x0, #0x70] /* jmp_buf->Sp */ + mrs x2, fpcr + str w2, [x0, #0x78] /* jmp_buf->Fpcr */ + mrs x2, fpsr + str w2, [x0, #0x7c] /* jmp_buf->Fpsr */ + stp d8, d9, [x0, #0x80] /* jmp_buf->D[0-1] */ + stp d10, d11, [x0, #0x90] /* jmp_buf->D[2-3] */ + stp d12, d13, [x0, #0xa0] /* jmp_buf->D[4-5] */ + stp d14, d15, [x0, #0xb0] /* jmp_buf->D[6-7] */ + mov x0, #0 + ret +#endif + + .globl __MINGW_USYMBOL(__mingw_longjmp) + .def __MINGW_USYMBOL(__mingw_longjmp); .scl 2; .type 32; .endef +__MINGW_USYMBOL(__mingw_longjmp): +#if defined(_ARM_) || defined(__arm__) + ldr r4, [r0, #0x4] /* jmp_buf->R4 */ + ldr r5, [r0, #0x8] /* jmp_buf->R5 */ + ldr r6, [r0, #0xc] /* jmp_buf->R6 */ + ldr r7, [r0, #0x10] /* jmp_buf->R7 */ + ldr r8, [r0, #0x14] /* jmp_buf->R8 */ + ldr r9, [r0, #0x18] /* jmp_buf->R9 */ + ldr r10, [r0, #0x1c] /* jmp_buf->R10 */ + ldr r11, [r0, #0x20] /* jmp_buf->R11 */ + ldr sp, [r0, #0x24] /* jmp_buf->Sp */ + ldr r2, [r0, #0x28] /* jmp_buf->Pc */ + ldr r3, [r0, #0x2c] /* jmp_buf->Fpscr */ + vmsr fpscr, r3 + vldr d8, [r0, #0x30] /* jmp_buf->D[0] */ + vldr d9, [r0, #0x38] /* jmp_buf->D[1] */ + vldr d10, [r0, #0x40] /* jmp_buf->D[2] */ + vldr d11, [r0, #0x48] /* jmp_buf->D[3] */ + vldr d12, [r0, #0x50] /* jmp_buf->D[4] */ + vldr d13, [r0, #0x58] /* jmp_buf->D[5] */ + vldr d14, [r0, #0x60] /* jmp_buf->D[6] */ + vldr d15, [r0, #0x68] /* jmp_buf->D[7] */ + mov r0, r1 /* retval */ + bx r2 +#elif defined(_ARM64_) || defined(__aarch64__) + ldp x19, x20, [x0, #0x10] /* jmp_buf->X19, X20 */ + ldp x21, x22, [x0, #0x20] /* jmp_buf->X21, X22 */ + ldp x23, x24, [x0, #0x30] /* jmp_buf->X23, X24 */ + ldp x25, x26, [x0, #0x40] /* jmp_buf->X25, X26 */ + ldp x27, x28, [x0, #0x50] /* jmp_buf->X27, X28 */ + ldp x29, x30, [x0, #0x60] /* jmp_buf->Fp, Lr */ + ldr x2, [x0, #0x70] /* jmp_buf->Sp */ + mov sp, x2 + ldr w2, [x0, #0x78] /* jmp_buf->Fpcr */ + msr fpcr, x2 + ldr w2, [x0, #0x7c] /* jmp_buf->Fpsr */ + msr fpsr, x2 + ldp d8, d9, [x0, #0x80] /* jmp_buf->D[0-1] */ + ldp d10, d11, [x0, #0x90] /* jmp_buf->D[2-3] */ + ldp d12, d13, [x0, #0xa0] /* jmp_buf->D[4-5] */ + ldp d14, d15, [x0, #0xb0] /* jmp_buf->D[6-7] */ + mov x0, x1 /* retval */ + ret +#endif +#endif diff --git a/libc/mingw/misc/mingw_matherr.c b/libc/mingw/misc/mingw_matherr.c new file mode 100644 index 000000000..215296829 --- /dev/null +++ b/libc/mingw/misc/mingw_matherr.c @@ -0,0 +1,2 @@ +int _MINGW_INSTALL_DEBUG_MATHERR = -1; + diff --git a/libc/mingw/misc/mingw_mbwc_convert.c b/libc/mingw/misc/mingw_mbwc_convert.c new file mode 100644 index 000000000..26e876fdc --- /dev/null +++ b/libc/mingw/misc/mingw_mbwc_convert.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include + +int __cdecl __mingw_str_wide_utf8(const wchar_t * const wptr, char **mbptr, size_t *buflen) +{ + size_t len; + char *buf; + int ret = 0; + + len = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, NULL, 0, NULL, NULL); /* Get utf-8 string length */ + buf = calloc(len + 1, sizeof (char)); /* Can we assume sizeof char always = 1? */ + + if(!buf) len = 0; + else { + if (len != 0) ret = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, buf, len, NULL, NULL); /*Do actual conversion*/ + buf[len] = '0'; /* Must terminate */ + } + *mbptr = buf; /* Set string pointer to allocated buffer */ + if(buflen != NULL) *buflen = (len) * sizeof (char); /* Give length of allocated memory if needed. */ + return ret; +} + +int __cdecl __mingw_str_utf8_wide(const char *const mbptr, wchar_t **wptr, size_t *buflen) +{ + size_t len; + wchar_t *buf; + int ret = 0; + + len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, NULL, 0); /* Get converted size */ + buf = calloc(len + 1, sizeof (wchar_t)); /* Allocate memory accordingly */ + + if(!buf) len = 0; + else { + if (len != 0) ret = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, buf, len); /* Do conversion */ + buf[len] = L'0'; /* Must terminate */ + } + *wptr = buf; /* Set string pointer to allocated buffer */ + if (buflen != NULL) *buflen = len * sizeof (wchar_t); /* Give length of allocated memory if needed. */ + return ret; /* Number of characters written */ +} + +void __cdecl __mingw_str_free(void *ptr) +{ + if (ptr) free(ptr); +} diff --git a/libc/mingw/misc/mingw_usleep.c b/libc/mingw/misc/mingw_usleep.c new file mode 100644 index 000000000..8246e0be1 --- /dev/null +++ b/libc/mingw/misc/mingw_usleep.c @@ -0,0 +1,18 @@ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include + +int __cdecl usleep (useconds_t); + +int __cdecl +usleep (useconds_t us) +{ + if (us != 0) + Sleep (us / 1000); + + return 0; +} + diff --git a/libc/mingw/misc/mingw_wcstod.c b/libc/mingw/misc/mingw_wcstod.c new file mode 100644 index 000000000..394c0f1c3 --- /dev/null +++ b/libc/mingw/misc/mingw_wcstod.c @@ -0,0 +1,15 @@ +#include + +extern long double __cdecl +__mingw_wcstold (const wchar_t * __restrict__ _Str, wchar_t ** __restrict__ _EndPtr); + +double __cdecl +__mingw_wcstod (const wchar_t * __restrict__ _Str, wchar_t ** __restrict__ _EndPtr); + +double __cdecl +__mingw_wcstod (const wchar_t * __restrict__ _Str, wchar_t ** __restrict__ _EndPtr) +{ + return (double) __mingw_wcstold (_Str, _EndPtr); +} + + diff --git a/libc/mingw/misc/mingw_wcstof.c b/libc/mingw/misc/mingw_wcstof.c new file mode 100644 index 000000000..6cdf2e060 --- /dev/null +++ b/libc/mingw/misc/mingw_wcstof.c @@ -0,0 +1,31 @@ +#include +#include + +float __cdecl +__mingw_wcstof (const wchar_t * __restrict__ _Str, wchar_t ** __restrict__ _EndPtr); + +float __cdecl +__mingw_wcstof (const wchar_t * __restrict__ _Str, wchar_t ** __restrict__ _EndPtr) +{ + float r; + char *n, *ep = NULL; + size_t l, l2; + + l = WideCharToMultiByte(CP_UTF8, 0, _Str, -1, NULL, 0, NULL, NULL); + n = alloca (l + 1); + if (l != 0) WideCharToMultiByte (CP_UTF8, 0, _Str, -1, n, l, NULL, NULL); + n[l] = 0; + r = __mingw_strtof (n, &ep); + if (ep != NULL) + { + *ep = 0; + l2 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, n, -1, NULL, 0); + if (l2 > 0) + l2 -= 1; /* Remove zero terminator from length. */ + if (_EndPtr) *_EndPtr = (wchar_t *) &_Str[l2]; + } + else + if (_EndPtr) *_EndPtr = NULL; + return r; +} + diff --git a/libc/mingw/misc/mingw_wcstold.c b/libc/mingw/misc/mingw_wcstold.c new file mode 100644 index 000000000..ce1ad5e00 --- /dev/null +++ b/libc/mingw/misc/mingw_wcstold.c @@ -0,0 +1,32 @@ +#include +#include + +long double __cdecl +__mingw_wcstold (const wchar_t * __restrict__ _Str, wchar_t ** __restrict__ _EndPtr); + +long double __cdecl +__mingw_wcstold (const wchar_t * __restrict__ _Str, wchar_t ** __restrict__ _EndPtr) +{ + long double r; + char *n, *ep = NULL; + size_t l, l2; + + l = WideCharToMultiByte(CP_UTF8, 0, _Str, -1, NULL, 0, NULL, NULL); + n = alloca (l + 1); + if (l != 0) WideCharToMultiByte (CP_UTF8, 0, _Str, -1, n, l, NULL, NULL); + n[l] = 0; + r = __mingw_strtold (n, &ep); + if (ep != NULL) + { + *ep = 0; + l2 = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, n, -1, NULL, 0); + if (l2 > 0) + l2 -= 1; /* Remove zero terminator from length. */ + if (_EndPtr) + *_EndPtr = (wchar_t *) &_Str[l2]; + } + else if (_EndPtr) + *_EndPtr = NULL; + return r; +} + diff --git a/libc/mingw/misc/mkstemp.c b/libc/mingw/misc/mkstemp.c new file mode 100644 index 000000000..c78b7c509 --- /dev/null +++ b/libc/mingw/misc/mkstemp.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* + The mkstemp() function generates a unique temporary filename from template, + creates and opens the file, and returns an open file descriptor for the + file. + + The template may be any file name with at least six trailing Xs, for example + /tmp/temp.XXXXXXXX. The trailing Xs are replaced with a unique digit and + letter combination that makes the file name unique. Since it will be + modified, template must not be a string constant, but should be declared as + a character array. + + The file is created with permissions 0600, that is, read plus write for + owner only. The returned file descriptor provides both read and write access + to the file. + */ +int __cdecl mkstemp (char *template_name) +{ + int i, j, fd, len, index; + + /* These are the (62) characters used in temporary filenames. */ + static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + + /* The last six characters of template must be "XXXXXX" */ + if (template_name == NULL || (len = strlen (template_name)) < 6 + || memcmp (template_name + (len - 6), "XXXXXX", 6)) { + errno = EINVAL; + return -1; + } + + /* User may supply more than six trailing Xs */ + for (index = len - 6; index > 0 && template_name[index - 1] == 'X'; index--); + + /* + Like OpenBSD, mkstemp() will try at least 2 ** 31 combinations before + giving up. + */ + for (i = 0; i >= 0; i++) { + for(j = index; j < len; j++) { + template_name[j] = letters[rand () % 62]; + } + fd = _sopen(template_name, + _O_RDWR | _O_CREAT | _O_EXCL | _O_BINARY, + _SH_DENYRW, _S_IREAD | _S_IWRITE); + if (fd != -1) return fd; + if (fd == -1 && errno != EEXIST) return -1; + } + + return -1; +} + +#if 0 +int main (int argc, char *argv[]) +{ + int i, fd; + + for (i = 0; i < 10; i++) { + char template_name[] = { "temp_XXXXXX" }; + fd = mkstemp (template_name); + if (fd >= 0) { + fprintf (stderr, "fd=%d, name=%s\n", fd, template_name); + _close (fd); + } else { + fprintf (stderr, "errno=%d\n", errno); + } + } + + for (i = 0; i < 10; i++) { + char template_name[] = { "temp_XXXXXXXX" }; + fd = mkstemp (template_name); + if (fd >= 0) { + fprintf (stderr, "fd=%d, name=%s\n", fd, template_name); + _close (fd); + } else { + fprintf (stderr, "errno=%d\n", errno); + } + } + + return 0; +} +#endif diff --git a/libc/mingw/misc/seterrno.c b/libc/mingw/misc/seterrno.c new file mode 100644 index 000000000..952675da0 --- /dev/null +++ b/libc/mingw/misc/seterrno.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +errno_t __cdecl _set_errno (int _Value) +{ + errno = _Value; + return errno; +} + +errno_t __cdecl _get_errno (int *_Value) +{ + if(_Value) *_Value=errno; + return errno; +} diff --git a/libc/mingw/misc/sleep.c b/libc/mingw/misc/sleep.c new file mode 100644 index 000000000..ee66d7fb6 --- /dev/null +++ b/libc/mingw/misc/sleep.c @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include +#include +#include + +unsigned int sleep (unsigned int seconds) +{ + Sleep (seconds * 1000); + return 0; +} diff --git a/libc/mingw/misc/spawnv.c b/libc/mingw/misc/spawnv.c new file mode 100644 index 000000000..88e690c8b --- /dev/null +++ b/libc/mingw/misc/spawnv.c @@ -0,0 +1,6 @@ +#include + +intptr_t __cdecl spawnv(int mode,const char *_Filename,char *const _ArgList[]) +{ + return _spawnv(mode, _Filename,(const char *const *)_ArgList); +} diff --git a/libc/mingw/misc/spawnve.c b/libc/mingw/misc/spawnve.c new file mode 100644 index 000000000..8731c33af --- /dev/null +++ b/libc/mingw/misc/spawnve.c @@ -0,0 +1,6 @@ +#include + +intptr_t __cdecl spawnve(int mode,const char *_Filename,char *const _ArgList[],char *const _Env[]) +{ + return _spawnve(mode, _Filename,(const char *const *)_ArgList,(const char *const *)_Env); +} diff --git a/libc/mingw/misc/spawnvp.c b/libc/mingw/misc/spawnvp.c new file mode 100644 index 000000000..75e17e13c --- /dev/null +++ b/libc/mingw/misc/spawnvp.c @@ -0,0 +1,6 @@ +#include + +intptr_t __cdecl spawnvp(int mode,const char *_Filename,char *const _ArgList[]) +{ + return _spawnvp(mode, _Filename,(const char *const *)_ArgList); +} diff --git a/libc/mingw/misc/spawnvpe.c b/libc/mingw/misc/spawnvpe.c new file mode 100644 index 000000000..08e41e828 --- /dev/null +++ b/libc/mingw/misc/spawnvpe.c @@ -0,0 +1,6 @@ +#include + +intptr_t __cdecl spawnvpe(int mode,const char *_Filename,char *const _ArgList[],char *const _Env[]) +{ + return _spawnvpe(mode, _Filename,(const char *const *)_ArgList,(const char *const *)_Env); +} diff --git a/libc/mingw/misc/strnlen.c b/libc/mingw/misc/strnlen.c new file mode 100644 index 000000000..6f9e80335 --- /dev/null +++ b/libc/mingw/misc/strnlen.c @@ -0,0 +1,11 @@ +#define __CRT__NO_INLINE +#include + +size_t __cdecl strnlen (const char *s, size_t maxlen) +{ + const char *s2 = s; + while ((size_t) (s2 - s) < maxlen && *s2) + ++s2; + return s2 - s; +} + diff --git a/libc/mingw/misc/strsafe.c b/libc/mingw/misc/strsafe.c new file mode 100644 index 000000000..4fb91ec8f --- /dev/null +++ b/libc/mingw/misc/strsafe.c @@ -0,0 +1,2 @@ +#define __CRT_STRSAFE_IMPL +#include diff --git a/libc/mingw/misc/strtoimax.c b/libc/mingw/misc/strtoimax.c new file mode 100644 index 000000000..eef5da97c --- /dev/null +++ b/libc/mingw/misc/strtoimax.c @@ -0,0 +1,117 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + This source code was extracted from the Q8 package created and + placed in the PUBLIC DOMAIN by Doug Gwyn + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E). + + This particular implementation requires the matching . + It also assumes that character codes for A..Z and a..z are in + contiguous ascending order; this is true for ASCII but not EBCDIC. +*/ +#include +#include +#include +#include + +/* Helper macros */ + +/* convert digit character to number, in any base */ +#define ToNumber(c) (isdigit(c) ? (c) - '0' : \ + isupper(c) ? (c) - 'A' + 10 : \ + islower(c) ? (c) - 'a' + 10 : \ + -1 /* "invalid" flag */ \ + ) +/* validate converted digit character for specific base */ +#define valid(n, b) ((n) >= 0 && (n) < (b)) + +intmax_t +strtoimax(nptr, endptr, base) + register const char * __restrict__ nptr; + char ** __restrict__ endptr; + register int base; + { + register uintmax_t accum; /* accumulates converted value */ + register int n; /* numeral from digit character */ + int minus; /* set iff minus sign seen */ + int toobig; /* set iff value overflows */ + + if ( endptr != NULL ) + *endptr = (char *)nptr; /* in case no conversion's performed */ + + if ( base < 0 || base == 1 || base > 36 ) + { + errno = EDOM; + return 0; /* unspecified behavior */ + } + + /* skip initial, possibly empty sequence of white-space characters */ + + while ( isspace(*nptr) ) + ++nptr; + + /* process subject sequence: */ + + /* optional sign */ + if ( (minus = *nptr == '-') || *nptr == '+' ) + ++nptr; + + if ( base == 0 ) { + if ( *nptr == '0' ) { + if ( nptr[1] == 'X' || nptr[1] == 'x' ) + base = 16; + else + base = 8; + } + else + base = 10; + } + /* optional "0x" or "0X" for base 16 */ + + if ( base == 16 && *nptr == '0' && (nptr[1] == 'X' || nptr[1] == 'x') ) + nptr += 2; /* skip past this prefix */ + + /* check whether there is at least one valid digit */ + + n = ToNumber(*nptr); + ++nptr; + + if ( !valid(n, base) ) + return 0; /* subject seq. not of expected form */ + + accum = n; + + for ( toobig = 0; n = ToNumber(*nptr), valid(n, base); ++nptr ) + if ( accum > (uintmax_t)(INTMAX_MAX / base + 2) ) /* major wrap-around */ + toobig = 1; /* but keep scanning */ + else + accum = base * accum + n; + + if ( endptr != NULL ) + *endptr = (char *)nptr; /* points to first not-valid-digit */ + + if ( minus ) + { + if ( accum > (uintmax_t)INTMAX_MAX + 1 ) + toobig = 1; + } + else + if ( accum > (uintmax_t)INTMAX_MAX ) + toobig = 1; + + if ( toobig ) + { + errno = ERANGE; + return minus ? INTMAX_MIN : INTMAX_MAX; + } + else + return (intmax_t)(minus ? -accum : accum); + } + +long long __attribute__ ((alias ("strtoimax"))) +strtoll (const char* __restrict__ nptr, char ** __restrict__ endptr, int base); diff --git a/libc/mingw/misc/strtold.c b/libc/mingw/misc/strtold.c new file mode 100644 index 000000000..2b99eba82 --- /dev/null +++ b/libc/mingw/misc/strtold.c @@ -0,0 +1,398 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include "math/cephes_emath.h" + +#if NE == 10 +/* 1.0E0 */ +static const unsigned short __eone[NE] = { + 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x8000, 0x3fff, +}; +#else +static const unsigned short __eone[NE] = { + 0, 0000000,0000000,0000000,0100000,0x3fff, +}; +#endif + +#if NE == 10 +static const unsigned short __etens[NTEN + 1][NE] = +{ + {0x6576, 0x4a92, 0x804a, 0x153f, + 0xc94c, 0x979a, 0x8a20, 0x5202, 0xc460, 0x7525,}, /* 10**4096 */ + {0x6a32, 0xce52, 0x329a, 0x28ce, + 0xa74d, 0x5de4, 0xc53d, 0x3b5d, 0x9e8b, 0x5a92,}, /* 10**2048 */ + {0x526c, 0x50ce, 0xf18b, 0x3d28, + 0x650d, 0x0c17, 0x8175, 0x7586, 0xc976, 0x4d48,}, + {0x9c66, 0x58f8, 0xbc50, 0x5c54, + 0xcc65, 0x91c6, 0xa60e, 0xa0ae, 0xe319, 0x46a3,}, + {0x851e, 0xeab7, 0x98fe, 0x901b, + 0xddbb, 0xde8d, 0x9df9, 0xebfb, 0xaa7e, 0x4351,}, + {0x0235, 0x0137, 0x36b1, 0x336c, + 0xc66f, 0x8cdf, 0x80e9, 0x47c9, 0x93ba, 0x41a8,}, + {0x50f8, 0x25fb, 0xc76b, 0x6b71, + 0x3cbf, 0xa6d5, 0xffcf, 0x1f49, 0xc278, 0x40d3,}, + {0x0000, 0x0000, 0x0000, 0x0000, + 0xf020, 0xb59d, 0x2b70, 0xada8, 0x9dc5, 0x4069,}, + {0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0400, 0xc9bf, 0x8e1b, 0x4034,}, + {0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x2000, 0xbebc, 0x4019,}, + {0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x9c40, 0x400c,}, + {0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xc800, 0x4005,}, + {0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0xa000, 0x4002,}, /* 10**1 */ +}; +#else +static const unsigned short __etens[NTEN+1][NE] = { + {0xc94c,0x979a,0x8a20,0x5202,0xc460,0x7525,},/* 10**4096 */ + {0xa74d,0x5de4,0xc53d,0x3b5d,0x9e8b,0x5a92,},/* 10**2048 */ + {0x650d,0x0c17,0x8175,0x7586,0xc976,0x4d48,}, + {0xcc65,0x91c6,0xa60e,0xa0ae,0xe319,0x46a3,}, + {0xddbc,0xde8d,0x9df9,0xebfb,0xaa7e,0x4351,}, + {0xc66f,0x8cdf,0x80e9,0x47c9,0x93ba,0x41a8,}, + {0x3cbf,0xa6d5,0xffcf,0x1f49,0xc278,0x40d3,}, + {0xf020,0xb59d,0x2b70,0xada8,0x9dc5,0x4069,}, + {0x0000,0x0000,0x0400,0xc9bf,0x8e1b,0x4034,}, + {0x0000,0x0000,0x0000,0x2000,0xbebc,0x4019,}, + {0x0000,0x0000,0x0000,0x0000,0x9c40,0x400c,}, + {0x0000,0x0000,0x0000,0x0000,0xc800,0x4005,}, + {0x0000,0x0000,0x0000,0x0000,0xa000,0x4002,}, /* 10**1 */ +}; +#endif + +int __asctoe64(const char * __restrict__ ss, short unsigned int * __restrict__ y) +{ + unsigned short yy[NI], xt[NI], tt[NI]; + int esign, decflg, nexp, expo, lost; + int k, c; + int valid_lead_string = 0; + int have_non_zero_mant = 0; + int prec = 0; + /* int trail = 0; */ + int lexp; + unsigned short nsign = 0; + const unsigned short *p; + char *sp, *lstr; + char *s; + + const char dec_sym = *(localeconv ()->decimal_point); + + int lenldstr = 0; + + /* Copy the input string. */ + c = strlen (ss) + 2; + lstr = (char *) alloca (c); + s = (char *) ss; + while( isspace ((int)(unsigned char)*s)) /* skip leading spaces */ + { + ++s; + ++lenldstr; + } + sp = lstr; + for (k = 0; k < c; k++) + { + if ((*sp++ = *s++) == '\0') + break; + } + *sp = '\0'; + s = lstr; + + if (*s == '-') + { + nsign = 0xffff; + ++s; + } + else if (*s == '+') + { + ++s; + } + + if (_strnicmp("INF", s , 3) == 0) + { + valid_lead_string = 1; + s += 3; + if ( _strnicmp ("INITY", s, 5) == 0) + s += 5; + __ecleaz(yy); + yy[E] = 0x7fff; /* infinity */ + goto aexit; + } + else if(_strnicmp ("NAN", s, 3) == 0) + { + valid_lead_string = 1; + s += 3; + __enan_NI16( yy ); + goto aexit; + } + + /* FIXME: Handle case of strtold ("NAN(n_char_seq)",endptr) */ + + /* Now get some digits. */ + lost = 0; + decflg = 0; + nexp = 0; + expo = 0; + __ecleaz( yy ); + + /* Ignore leading zeros */ + while (*s == '0') + { + valid_lead_string = 1; + s++; + } + +nxtcom: + + k = *s - '0'; + if ((k >= 0) && (k <= 9)) + { +#if 0 +/* The use of a special char as a flag for trailing zeroes causes problems when input + actually contains the char */ +/* Identify and strip trailing zeros after the decimal point. */ + if ((trail == 0) && (decflg != 0)) + { + sp = s; + while ((*sp >= '0') && (*sp <= '9')) + ++sp; + --sp; + while (*sp == '0') + { + *sp-- = (char)-1; + trail++; + } + if( *s == (char)-1 ) + goto donchr; + } +#endif + +/* If enough digits were given to more than fill up the yy register, + * continuing until overflow into the high guard word yy[2] + * guarantees that there will be a roundoff bit at the top + * of the low guard word after normalization. + */ + if (yy[2] == 0) + { + if( decflg ) + nexp += 1; /* count digits after decimal point */ + __eshup1( yy ); /* multiply current number by 10 */ + __emovz( yy, xt ); + __eshup1( xt ); + __eshup1( xt ); + __eaddm( xt, yy ); + __ecleaz( xt ); + xt[NI-2] = (unsigned short )k; + __eaddm( xt, yy ); + } + else + { + /* Mark any lost non-zero digit. */ + lost |= k; + /* Count lost digits before the decimal point. */ + if (decflg == 0) + nexp -= 1; + } + have_non_zero_mant |= k; + prec ++; + /* goto donchr; */ + } + else if (*s == dec_sym) + { + if( decflg ) + goto daldone; + ++decflg; + } + else if ((*s == 'E') || (*s == 'e') ) + { + if (prec || valid_lead_string) + goto expnt; + else + goto daldone; + } +#if 0 + else if (*s == (char)-1) + goto donchr; +#endif + else /* an invalid char */ + goto daldone; + + /* donchr: */ + ++s; + goto nxtcom; + +/* Exponent interpretation */ +expnt: + + esign = 1; + expo = 0; + /* Save position in case we need to fall back. */ + sp = s; + ++s; + /* check for + or - */ + if (*s == '-') + { + esign = -1; + ++s; + } + if (*s == '+') + ++s; + + /* Check for valid exponent. */ + if (!(*s >= '0' && *s <= '9')) + { + s = sp; + goto daldone; + } + + while ((*s >= '0') && (*s <= '9')) + { + /* Stop modifying exp if we are going to overflow anyway, + but keep parsing the string. */ + if (expo < 4978) + { + expo *= 10; + expo += *s - '0'; + } + s++; + } + + if (esign < 0) + expo = -expo; + + if (expo > 4977) /* maybe overflow */ + { + __ecleaz(yy); + if (have_non_zero_mant) + yy[E] = 0x7fff; + goto aexit; + } + else if (expo < -4977) /* underflow */ + { + __ecleaz(yy); + goto aexit; + } + +daldone: + + nexp = expo - nexp; + + /* Pad trailing zeros to minimize power of 10, per IEEE spec. */ + while ((nexp > 0) && (yy[2] == 0)) + { + __emovz( yy, xt ); + __eshup1( xt ); + __eshup1( xt ); + __eaddm( yy, xt ); + __eshup1( xt ); + if (xt[2] != 0) + break; + nexp -= 1; + __emovz( xt, yy ); + } + if ((k = __enormlz(yy)) > NBITS) + { + __ecleaz(yy); + goto aexit; + } + lexp = (EXONE - 1 + NBITS) - k; + __emdnorm( yy, lost, 0, lexp, 64, NBITS ); + /* convert to external format */ + + /* Multiply by 10**nexp. If precision is 64 bits, + * the maximum relative error incurred in forming 10**n + * for 0 <= n <= 324 is 8.2e-20, at 10**180. + * For 0 <= n <= 999, the peak relative error is 1.4e-19 at 10**947. + * For 0 >= n >= -999, it is -1.55e-19 at 10**-435. + */ + lexp = yy[E]; + if (nexp == 0) + { + k = 0; + goto expdon; + } + esign = 1; + if (nexp < 0) + { + nexp = -nexp; + esign = -1; + if (nexp > 4096) + { /* Punt. Can't handle this without 2 divides. */ + __emovi( __etens[0], tt ); + lexp -= tt[E]; + k = __edivm( tt, yy ); + lexp += EXONE; + nexp -= 4096; + } + } + p = &__etens[NTEN][0]; + __emov( __eone, xt ); + expo = 1; + do + { + if (expo & nexp) + __emul( p, xt, xt ); + p -= NE; + expo = expo + expo; + } + while (expo <= MAXP); + + __emovi( xt, tt ); + if (esign < 0) + { + lexp -= tt[E]; + k = __edivm( tt, yy ); + lexp += EXONE; + } + else + { + lexp += tt[E]; + k = __emulm( tt, yy ); + lexp -= EXONE - 1; + } + +expdon: + + /* Round and convert directly to the destination type */ + + __emdnorm( yy, k, 0, lexp, 64, 64 ); + +aexit: + + yy[0] = nsign; + + __toe64( yy, y ); + + /* Check for overflow, undeflow */ + if (have_non_zero_mant && + (*((long double*) y) == 0.0L || isinf (*((long double*) y)))) + errno = ERANGE; + + if (prec || valid_lead_string) + return (lenldstr + (s - lstr)); + + return 0; +} + + +long double strtold (const char * __restrict__ s, char ** __restrict__ se) +{ + int lenldstr; + union + { + unsigned short int us[6]; + long double ld; + } xx = {{0}}; + + lenldstr = __asctoe64( s, xx.us); + if (se) + *se = (char*)s + lenldstr; + + return xx.ld; +} + diff --git a/libc/mingw/misc/strtoumax.c b/libc/mingw/misc/strtoumax.c new file mode 100644 index 000000000..e86cd7613 --- /dev/null +++ b/libc/mingw/misc/strtoumax.c @@ -0,0 +1,115 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + This source code was extracted from the Q8 package created and + placed in the PUBLIC DOMAIN by Doug Gwyn + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E). + + This particular implementation requires the matching . + It also assumes that character codes for A..Z and a..z are in + contiguous ascending order; this is true for ASCII but not EBCDIC. +*/ +#include +#include +#include +#include + +/* Helper macros */ + +/* convert digit character to number, in any base */ +#define ToNumber(c) (isdigit(c) ? (c) - '0' : \ + isupper(c) ? (c) - 'A' + 10 : \ + islower(c) ? (c) - 'a' + 10 : \ + -1 /* "invalid" flag */ \ + ) +/* validate converted digit character for specific base */ +#define valid(n, b) ((n) >= 0 && (n) < (b)) + +uintmax_t +strtoumax(nptr, endptr, base) + register const char * __restrict__ nptr; + char ** __restrict__ endptr; + register int base; + { + register uintmax_t accum; /* accumulates converted value */ + register uintmax_t next; /* for computing next value of accum */ + register int n; /* numeral from digit character */ + int minus; /* set iff minus sign seen (yes!) */ + int toobig; /* set iff value overflows */ + + if ( endptr != NULL ) + *endptr = (char *)nptr; /* in case no conversion's performed */ + + if ( base < 0 || base == 1 || base > 36 ) + { + errno = EDOM; + return 0; /* unspecified behavior */ + } + + /* skip initial, possibly empty sequence of white-space characters */ + + while ( isspace(*nptr) ) + ++nptr; + + /* process subject sequence: */ + + /* optional sign (yes!) */ + + if ( (minus = *nptr == '-') || *nptr == '+' ) + ++nptr; + + if ( base == 0 ) + { + if ( *nptr == '0' ) + { + if ( nptr[1] == 'X' || nptr[1] == 'x' ) + base = 16; + else + base = 8; + } + else + base = 10; + } + + /* optional "0x" or "0X" for base 16 */ + + if ( base == 16 && *nptr == '0' && (nptr[1] == 'X' || nptr[1] == 'x') ) + nptr += 2; /* skip past this prefix */ + + /* check whether there is at least one valid digit */ + + n = ToNumber(*nptr); + ++nptr; + + if ( !valid(n, base) ) + return 0; /* subject seq. not of expected form */ + + accum = n; + + for ( toobig = 0; n = ToNumber(*nptr), valid(n, base); ++nptr ) + if ( accum > UINTMAX_MAX / base + 1 /* major wrap-around */ + || (next = base * accum + n) < accum /* minor wrap-around */ + ) + toobig = 1; /* but keep scanning */ + else + accum = next; + + if ( endptr != NULL ) + *endptr = (char *)nptr; /* points to first not-valid-digit */ + + if ( toobig ) + { + errno = ERANGE; + return UINTMAX_MAX; + } + else + return minus ? -accum : accum; /* (yes!) */ + } + +unsigned long long __attribute__ ((alias ("strtoumax"))) +strtoull (const char* __restrict__ nptr, char ** __restrict__ endptr, int base); diff --git a/libc/mingw/misc/tdelete.c b/libc/mingw/misc/tdelete.c new file mode 100644 index 000000000..609681ff2 --- /dev/null +++ b/libc/mingw/misc/tdelete.c @@ -0,0 +1,64 @@ +/* $NetBSD: tdelete.c,v 1.3 1999/09/20 04:39:43 lukem Exp $ */ + +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + */ + +#include +#define _SEARCH_PRIVATE +#include +#include + +#define _DIAGASSERT assert + + + +/* delete node with given key */ +void * +tdelete(const void *vkey, /* key to be deleted */ + void **vrootp, /* address of the root of tree */ + int (*compar)(const void *, const void *)) +{ + node_t **rootp = (node_t **)vrootp; + node_t *p, *q, *r; + int cmp; + + _DIAGASSERT((uintptr_t)compar != (uintptr_t)NULL); + + if (rootp == NULL || (p = *rootp) == NULL) + return NULL; + + while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) { + p = *rootp; + rootp = (cmp < 0) ? + &(*rootp)->llink : /* follow llink branch */ + &(*rootp)->rlink; /* follow rlink branch */ + if (*rootp == NULL) + return NULL; /* key not found */ + } + r = (*rootp)->rlink; /* D1: */ + if ((q = (*rootp)->llink) == NULL) /* Left NULL? */ + q = r; + else if (r != NULL) { /* Right link is NULL? */ + if (r->llink == NULL) { /* D2: Find successor */ + r->llink = q; + q = r; + } else { /* D3: Find NULL link */ + for (q = r->llink; q->llink != NULL; q = r->llink) + r = q; + r->llink = q->rlink; + q->llink = (*rootp)->llink; + q->rlink = (*rootp)->rlink; + } + } + free(*rootp); /* D4: Free node */ + *rootp = q; /* link parent to new node */ + return p; +} diff --git a/libc/mingw/misc/tfind.c b/libc/mingw/misc/tfind.c new file mode 100644 index 000000000..a2cb53689 --- /dev/null +++ b/libc/mingw/misc/tfind.c @@ -0,0 +1,42 @@ +/* $NetBSD: tfind.c,v 1.3.18.2 2005/03/23 11:12:21 tron Exp $ */ + +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + */ + +#include +#define _SEARCH_PRIVATE +#include +#include + + +/* find a node, or return 0 */ +void * +tfind (const void *vkey, void * const *vrootp, + int (*compar) (const void *, const void *)) +{ + node_t * const *rootp = (node_t * const*)vrootp; + + if (rootp == NULL) + return NULL; + + while (*rootp != NULL) + { + /* T1: */ + int r; + + if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */ + return *rootp; /* key found */ + rootp = (r < 0) ? + &(*rootp)->llink : /* T3: follow left branch */ + &(*rootp)->rlink; /* T4: follow right branch */ + } + return NULL; +} diff --git a/libc/mingw/misc/tsearch.c b/libc/mingw/misc/tsearch.c new file mode 100644 index 000000000..1c6df743a --- /dev/null +++ b/libc/mingw/misc/tsearch.c @@ -0,0 +1,58 @@ +/* $NetBSD: tsearch.c,v 1.4 1999/09/20 04:39:43 lukem Exp $ */ + +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + */ + +#include +#define _SEARCH_PRIVATE +#include +#include + + +/* find or insert datum into search tree */ +void * +tsearch (const void * __restrict__ vkey, /* key to be located */ + void ** __restrict__ vrootp, /* address of tree root */ + int (*compar) (const void *, const void *)) +{ + node_t *q, **n; + node_t **rootp = (node_t **)vrootp; + + if (rootp == NULL) + return NULL; + + n = rootp; + while (*n != NULL) + { + /* Knuth's T1: */ + int r; + + if ((r = (*compar)(vkey, ((*n)->key))) == 0) /* T2: */ + return *n; /* we found it! */ + + n = (r < 0) ? + &(*rootp)->llink : /* T3: follow left branch */ + &(*rootp)->rlink; /* T4: follow right branch */ + if (*n == NULL) + break; + rootp = n; + } + + q = malloc(sizeof(node_t)); /* T5: key not found */ + if (!q) + return q; + *n = q; + /* make new node */ + /* LINTED const castaway ok */ + q->key = (void *)vkey; /* initialize new node */ + q->llink = q->rlink = NULL; + return q; +} diff --git a/libc/mingw/misc/twalk.c b/libc/mingw/misc/twalk.c new file mode 100644 index 000000000..6659b805b --- /dev/null +++ b/libc/mingw/misc/twalk.c @@ -0,0 +1,49 @@ +/* $NetBSD: twalk.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ */ + +/* + * Tree search generalized from Knuth (6.2.2) Algorithm T just like + * the AT&T man page says. + * + * The node_t structure is for internal use only, lint doesn't grok it. + * + * Written by reading the System V Interface Definition, not the code. + * + * Totally public domain. + */ + +#include +#define _SEARCH_PRIVATE +#include +#include + +static void trecurse (const node_t *, void (*action)(const void *, VISIT, int), + int level) __MINGW_ATTRIB_NONNULL (1) + __MINGW_ATTRIB_NONNULL (2); +/* Walk the nodes of a tree */ +static void +trecurse (const node_t *root, /* Root of the tree to be walked */ + void (*action)(const void *, VISIT, int), + int level) +{ + if (root->llink == NULL && root->rlink == NULL) + (*action)(root, leaf, level); + else + { + (*action)(root, preorder, level); + if (root->llink != NULL) + trecurse (root->llink, action, level + 1); + (*action)(root, postorder, level); + if (root->rlink != NULL) + trecurse(root->rlink, action, level + 1); + (*action)(root, endorder, level); + } +} + +/* Walk the nodes of a tree */ +void +twalk (const void *vroot, /* Root of the tree to be walked */ + void (*action) (const void *, VISIT, int)) +{ + if (vroot != NULL && action != NULL) + trecurse(vroot, action, 0); +} diff --git a/libc/mingw/misc/uchar_c16rtomb.c b/libc/mingw/misc/uchar_c16rtomb.c new file mode 100644 index 000000000..94a2aaad0 --- /dev/null +++ b/libc/mingw/misc/uchar_c16rtomb.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* ISO C1x Unicode utilities + * Based on ISO/IEC SC22/WG14 9899 TR 19769 (SC22 N1326) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2011-09-27 + */ + +#include +#include + +size_t c16rtomb (char *__restrict__ s, + char16_t c16, + mbstate_t *__restrict__ state) +{ +/* wchar_t should compatible to char16_t on Windows */ + return wcrtomb(s, c16, state); +} + diff --git a/libc/mingw/misc/uchar_c32rtomb.c b/libc/mingw/misc/uchar_c32rtomb.c new file mode 100644 index 000000000..d05e6326f --- /dev/null +++ b/libc/mingw/misc/uchar_c32rtomb.c @@ -0,0 +1,59 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* ISO C1x Unicode utilities + * Based on ISO/IEC SC22/WG14 9899 TR 19769 (SC22 N1326) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2011-09-27 + */ + +#include +#include + +size_t c32rtomb (char *__restrict__ s, + char32_t c32, + mbstate_t *__restrict__ __UNUSED_PARAM(ps)) +{ + if (c32 <= 0x7F) /* 7 bits needs 1 byte */ + { + *s = (char)c32 & 0x7F; + return 1; + } + else if (c32 <= 0x7FF) /* 11 bits needs 2 bytes */ + { + s[1] = 0x80 | (char)(c32 & 0x3F); + s[0] = 0xC0 | (char)(c32 >> 6); + return 2; + } + else if (c32 <= 0xFFFF) /* 16 bits needs 3 bytes */ + { + s[2] = 0x80 | (char)(c32 & 0x3F); + s[1] = 0x80 | (char)((c32 >> 6) & 0x3F); + s[0] = 0xE0 | (char)(c32 >> 12); + return 3; + } + else if (c32 <= 0x1FFFFF) /* 21 bits needs 4 bytes */ + { + s[3] = 0x80 | (char)(c32 & 0x3F); + s[2] = 0x80 | (char)((c32 >> 6) & 0x3F); + s[1] = 0x80 | (char)((c32 >> 12) & 0x3F); + s[0] = 0xF0 | (char)(c32 >> 18); + return 4; + } + + errno = EILSEQ; + return (size_t)-1; +} + diff --git a/libc/mingw/misc/uchar_mbrtoc16.c b/libc/mingw/misc/uchar_mbrtoc16.c new file mode 100644 index 000000000..9de35fe07 --- /dev/null +++ b/libc/mingw/misc/uchar_mbrtoc16.c @@ -0,0 +1,33 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* ISO C1x Unicode utilities + * Based on ISO/IEC SC22/WG14 9899 TR 19769 (SC22 N1326) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2011-09-27 + */ + +#include +#include + +size_t mbrtoc16 (char16_t *__restrict__ pc16, + const char *__restrict__ s, + size_t n, + mbstate_t *__restrict__ state) +{ +/* wchar_t should compatible to char16_t on Windows */ + return mbrtowc((wchar_t *)pc16, s, n, state); +} + diff --git a/libc/mingw/misc/uchar_mbrtoc32.c b/libc/mingw/misc/uchar_mbrtoc32.c new file mode 100644 index 000000000..1d63e5ceb --- /dev/null +++ b/libc/mingw/misc/uchar_mbrtoc32.c @@ -0,0 +1,72 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* ISO C1x Unicode utilities + * Based on ISO/IEC SC22/WG14 9899 TR 19769 (SC22 N1326) + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + * + * This code is distributed in the hope that it will be useful but + * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY + * DISCLAIMED. This includes but is not limited to warranties of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Date: 2011-09-27 + */ + +#include +#include + +size_t mbrtoc32 (char32_t *__restrict__ pc32, + const char *__restrict__ s, + size_t n, + mbstate_t *__restrict__ __UNUSED_PARAM(ps)) +{ + if (*s == 0) + { + *pc32 = 0; + return 0; + } + + /* ASCII character - high bit unset */ + if ((*s & 0x80) == 0) + { + *pc32 = *s; + return 1; + } + + /* Multibyte chars */ + if ((*s & 0xE0) == 0xC0) /* 110xxxxx needs 2 bytes */ + { + if (n < 2) + return (size_t)-2; + + *pc32 = ((s[0] & 31) << 6) | (s[1] & 63); + return 2; + } + else if ((*s & 0xf0) == 0xE0) /* 1110xxxx needs 3 bytes */ + { + if (n < 3) + return (size_t)-2; + + *pc32 = ((s[0] & 15) << 12) | ((s[1] & 63) << 6) | (s[2] & 63); + return 3; + } + else if ((*s & 0xF8) == 0xF0) /* 11110xxx needs 4 bytes */ + { + if (n < 4) + return (size_t)-2; + + *pc32 = ((s[0] & 7) << 18) | ((s[1] & 63) << 12) | ((s[2] & 63) << 6) | (s[4] & 63); + return 4; + } + + errno = EILSEQ; + return (size_t)-1; +} + diff --git a/libc/mingw/misc/wassert.c b/libc/mingw/misc/wassert.c new file mode 100644 index 000000000..7d745d921 --- /dev/null +++ b/libc/mingw/misc/wassert.c @@ -0,0 +1,49 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include +#include +#include + +extern int mingw_app_type; + +void __cdecl _wassert (const wchar_t *, const wchar_t *,unsigned); +void __cdecl _assert (const char *, const char *, unsigned); + +void __cdecl +_wassert (const wchar_t *_Message, const wchar_t *_File, unsigned _Line) +{ + wchar_t *msgbuf = (wchar_t *) malloc (8192*sizeof(wchar_t)); + wchar_t fn[MAX_PATH + 1]; + DWORD nCode; + + if (!_File || _File[0] == 0) + _File = L""; + if (!_Message || _Message[0] == 0) + _Message = L"?"; + if (! GetModuleFileNameW (NULL, fn, MAX_PATH)) + wcscpy (fn, L""); + _snwprintf (msgbuf, 8191, L"Assertion failed!\n\nProgram: %ws\n" + "File: %ws, Line %u\n\nExpression: %ws", + fn, _File,_Line, _Message); + if (mingw_app_type == 0) + { + fwprintf (stderr, L"%ws\n", msgbuf); + abort (); + } + nCode = MessageBoxW (NULL, msgbuf, L"MinGW Runtime Assertion", MB_ABORTRETRYIGNORE| + MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL); + if (nCode == IDABORT) + { + raise (SIGABRT); + _exit (3); + abort (); + } + if (nCode == IDIGNORE) + return; + abort (); +} diff --git a/libc/mingw/misc/wcrtomb.c b/libc/mingw/misc/wcrtomb.c new file mode 100644 index 000000000..e96d061d0 --- /dev/null +++ b/libc/mingw/misc/wcrtomb.c @@ -0,0 +1,100 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include "mb_wc_common.h" +#include +#include +#include +#include +#include + +__attribute__((noinline)) +static int __MINGW_ATTRIB_NONNULL(1) + __wcrtomb_cp (char *dst, wchar_t wc, const unsigned int cp, + const unsigned int mb_max) +{ + if (cp == 0) + { + if (wc > 255) + { + errno = EILSEQ; + return -1; + } + *dst = (char) wc; + return 1; + } + else + { + int invalid_char = 0; + + int size = WideCharToMultiByte (cp, 0 /* Is this correct flag? */, + &wc, 1, dst, mb_max, + NULL, &invalid_char); + if (size == 0 || invalid_char) + { + errno = EILSEQ; + return -1; + } + return size; + } +} + +size_t +wcrtomb (char *dst, wchar_t wc, mbstate_t * __UNUSED_PARAM (ps)) +{ + char byte_bucket [MB_LEN_MAX]; + char* tmp_dst = dst ? dst : &byte_bucket[0]; + return (size_t)__wcrtomb_cp (tmp_dst, wc, ___lc_codepage_func(), + MB_CUR_MAX); +} + +size_t wcsrtombs (char *dst, const wchar_t **src, size_t len, + mbstate_t * __UNUSED_PARAM (ps)) +{ + int ret = 0; + size_t n = 0; + const unsigned int cp = ___lc_codepage_func(); + const unsigned int mb_max = MB_CUR_MAX; + const wchar_t *pwc = *src; + + if (src == NULL || *src == NULL) /* undefined behavior */ + return 0; + + if (dst != NULL) + { + while (n < len) + { + if ((ret = __wcrtomb_cp (dst, *pwc, cp, mb_max)) <= 0) + return (size_t) -1; + n += ret; + dst += ret; + if (*(dst - 1) == '\0') + { + *src = (wchar_t *) NULL; + return (n - 1); + } + pwc++; + } + *src = pwc; + } + else + { + char byte_bucket [MB_LEN_MAX]; + while (1) + { + if ((ret = __wcrtomb_cp (&byte_bucket[0], *pwc, cp, mb_max)) <= 0) + return (size_t) -1; + n += ret; + if (byte_bucket [ret - 1] == '\0') + return (n - 1); + pwc++; + } + } + + return n; +} diff --git a/libc/mingw/misc/wcsnlen.c b/libc/mingw/misc/wcsnlen.c new file mode 100644 index 000000000..b7dca79d5 --- /dev/null +++ b/libc/mingw/misc/wcsnlen.c @@ -0,0 +1,13 @@ +#define __CRT__NO_INLINE +#include + +size_t __cdecl +wcsnlen(const wchar_t *w, size_t ncnt) +{ + size_t n = 0; + + for (; n < ncnt && *w != 0; n++, w++) + ; + + return n; +} diff --git a/libc/mingw/misc/wcstof.c b/libc/mingw/misc/wcstof.c new file mode 100644 index 000000000..7673338a8 --- /dev/null +++ b/libc/mingw/misc/wcstof.c @@ -0,0 +1,66 @@ +/* Wide char wrapper for strtof + * Revision history: + * 25 Aug 2006 Initial version. + * + * Contributor: Danny Smith + */ + + /* This routine has been placed in the public domain.*/ + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +#include "mb_wc_common.h" + +float wcstof (const wchar_t * __restrict__ wcs, wchar_t ** __restrict__ wcse) +{ + char * cs; + char * cse; + unsigned int i; + float ret; + const unsigned int cp = ___lc_codepage_func(); + + /* Allocate enough room for (possibly) mb chars */ + cs = (char *) malloc ((wcslen(wcs)+1) * MB_CUR_MAX); + + if (cp == 0) /* C locale */ + { + for (i = 0; (wcs[i] != 0) && wcs[i] <= 255; i++) + cs[i] = (char) wcs[i]; + cs[i] = '\0'; + } + else + { + int nbytes = -1; + int mb_len = 0; + /* loop through till we hit null or invalid character */ + for (i = 0; (wcs[i] != 0) && (nbytes != 0); i++) + { + nbytes = WideCharToMultiByte(cp, WC_COMPOSITECHECK | WC_SEPCHARS, + wcs + i, 1, cs + mb_len, MB_CUR_MAX, + NULL, NULL); + mb_len += nbytes; + } + cs[mb_len] = '\0'; + } + + ret = strtof (cs, &cse); + + if (wcse) + { + /* Make sure temp mbstring cs has 0 at cse. */ + *cse = '\0'; + i = MultiByteToWideChar (cp, MB_ERR_INVALID_CHARS, cs, -1, NULL, 0); + if (i > 0) + i -= 1; /* Remove zero terminator from length. */ + *wcse = (wchar_t *) wcs + i; + } + free (cs); + + return ret; +} diff --git a/libc/mingw/misc/wcstoimax.c b/libc/mingw/misc/wcstoimax.c new file mode 100644 index 000000000..9821cf07c --- /dev/null +++ b/libc/mingw/misc/wcstoimax.c @@ -0,0 +1,124 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + This source code was extracted from the Q8 package created and + placed in the PUBLIC DOMAIN by Doug Gwyn + + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E). + + This particular implementation requires the matching . + It also assumes that character codes for A..Z and a..z are in + contiguous ascending order; this is true for ASCII but not EBCDIC. +*/ + +#include +#include +#include +#include + +/* convert digit wide character to number, in any base */ + +#define ToWNumber(c) (iswdigit(c) ? (c) - L'0' : \ + iswupper(c) ? (c) - L'A' + 10 : \ + iswlower(c) ? (c) - L'a' + 10 : \ + -1 /* "invalid" flag */ \ + ) + +/* validate converted digit character for specific base */ +#define valid(n, b) ((n) >= 0 && (n) < (b)) + +intmax_t +wcstoimax(nptr, endptr, base) + register const wchar_t * __restrict__ nptr; + wchar_t ** __restrict__ endptr; + register int base; + { + register uintmax_t accum; /* accumulates converted value */ + register int n; /* numeral from digit character */ + int minus; /* set iff minus sign seen */ + int toobig; /* set iff value overflows */ + + if ( endptr != NULL ) + *endptr = (wchar_t *)nptr; /* in case no conv performed */ + + if ( base < 0 || base == 1 || base > 36 ) + { + errno = EDOM; + return 0; /* unspecified behavior */ + } + + /* skip initial, possibly empty sequence of white-space w.characters */ + + while ( iswspace(*nptr) ) + ++nptr; + + /* process subject sequence: */ + + /* optional sign */ + + if ( (minus = *nptr == L'-') || *nptr == L'+' ) + ++nptr; + + if ( base == 0 ) + { + if ( *nptr == L'0' ) + { + if ( nptr[1] == L'X' || nptr[1] == L'x' ) + base = 16; + else + base = 8; + } + else + base = 10; + } + /* optional "0x" or "0X" for base 16 */ + + if ( base == 16 && *nptr == L'0' + && (nptr[1] == L'X' || nptr[1] == L'x') + ) + nptr += 2; /* skip past this prefix */ + + /* check whether there is at least one valid digit */ + + n = ToWNumber(*nptr); + ++nptr; + + if ( !valid(n, base) ) + return 0; /* subject seq. not of expected form */ + + accum = n; + + for ( toobig = 0; n = ToWNumber(*nptr), valid(n, base); ++nptr ) + if ( accum > (uintmax_t)(INTMAX_MAX / base + 2) ) /* major wrap-around */ + toobig = 1; /* but keep scanning */ + else + accum = base * accum + n; + + if ( endptr != NULL ) + *endptr = (wchar_t *)nptr; /* -> first not-valid-digit */ + + if ( minus ) + { + if ( accum > (uintmax_t)INTMAX_MAX + 1 ) + toobig = 1; + } + else + if ( accum > (uintmax_t)INTMAX_MAX ) + toobig = 1; + + if ( toobig ) + { + errno = ERANGE; + return minus ? INTMAX_MIN : INTMAX_MAX; + } + else + return (intmax_t)(minus ? -accum : accum); + } + +long long __attribute__ ((alias ("wcstoimax"))) +wcstoll (const wchar_t* __restrict__ nptr, wchar_t ** __restrict__ endptr, int base); diff --git a/libc/mingw/misc/wcstold.c b/libc/mingw/misc/wcstold.c new file mode 100644 index 000000000..0137b20a3 --- /dev/null +++ b/libc/mingw/misc/wcstold.c @@ -0,0 +1,74 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* Wide char wrapper for strtold + * Revision history: + * 6 Nov 2002 Initial version. + * 25 Aug 2006 Don't use strtold internal functions. + * + * Contributor: Danny Smith + */ + + /* This routine has been placed in the public domain.*/ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include +#include +#include +#include +#include + +#include "mb_wc_common.h" + +long double wcstold (const wchar_t * __restrict__ wcs, wchar_t ** __restrict__ wcse) +{ + char * cs; + char * cse; + unsigned int i; + long double ret; + const unsigned int cp = ___lc_codepage_func(); + + /* Allocate enough room for (possibly) mb chars */ + cs = (char *) malloc ((wcslen(wcs)+1) * MB_CUR_MAX); + + if (cp == 0) /* C locale */ + { + for (i = 0; (wcs[i] != 0) && wcs[i] <= 255; i++) + cs[i] = (char) wcs[i]; + cs[i] = '\0'; + } + else + { + int nbytes = -1; + int mb_len = 0; + /* loop through till we hit null or invalid character */ + for (i = 0; (wcs[i] != 0) && (nbytes != 0); i++) + { + nbytes = WideCharToMultiByte(cp, WC_COMPOSITECHECK | WC_SEPCHARS, + wcs + i, 1, cs + mb_len, MB_CUR_MAX, + NULL, NULL); + mb_len += nbytes; + } + cs[mb_len] = '\0'; + } + + ret = strtold (cs, &cse); + + if (wcse) + { + /* Make sure temp mbstring has 0 at cse. */ + *cse = '\0'; + i = MultiByteToWideChar (cp, MB_ERR_INVALID_CHARS, cs, -1, NULL, 0); + if (i > 0) + i -= 1; /* Remove zero terminator from length. */ + *wcse = (wchar_t *) wcs + i; + } + free (cs); + + return ret; +} diff --git a/libc/mingw/misc/wcstoumax.c b/libc/mingw/misc/wcstoumax.c new file mode 100644 index 000000000..0f1ed540c --- /dev/null +++ b/libc/mingw/misc/wcstoumax.c @@ -0,0 +1,118 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + This source code was extracted from the Q8 package created and + placed in the PUBLIC DOMAIN by Doug Gwyn + + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.8.2 of ISO/IEC 9899:1999 (E). + + This particular implementation requires the matching . + It also assumes that character codes for A..Z and a..z are in + contiguous ascending order; this is true for ASCII but not EBCDIC. +*/ + +#include +#include +#include +#include + +/* convert digit wide character to number, in any base */ + +#define ToWNumber(c) (iswdigit(c) ? (c) - L'0' : \ + iswupper(c) ? (c) - L'A' + 10 : \ + iswlower(c) ? (c) - L'a' + 10 : \ + -1 /* "invalid" flag */ \ + ) + +/* validate converted digit character for specific base */ +#define valid(n, b) ((n) >= 0 && (n) < (b)) + +uintmax_t +wcstoumax(nptr, endptr, base) + register const wchar_t * __restrict__ nptr; + wchar_t ** __restrict__ endptr; + register int base; + { + register uintmax_t accum; /* accumulates converted value */ + register uintmax_t next; /* for computing next value of accum */ + register int n; /* numeral from digit character */ + int minus; /* set iff minus sign seen (yes!) */ + int toobig; /* set iff value overflows */ + + if ( endptr != NULL ) + *endptr = (wchar_t *)nptr; /* in case no conv performed */ + + if ( base < 0 || base == 1 || base > 36 ) + { + errno = EDOM; + return 0; /* unspecified behavior */ + } + + /* skip initial, possibly empty sequence of white-space w.characters */ + + while ( iswspace(*nptr) ) + ++nptr; + + /* process subject sequence: */ + + /* optional sign */ + + if ( (minus = *nptr == L'-') || *nptr == L'+' ) + ++nptr; + + if ( base == 0 ) + { + if ( *nptr == L'0' ) + { + if ( nptr[1] == L'X' || nptr[1] == L'x' ) + base = 16; + else + base = 8; + } + else + base = 10; + } + /* optional "0x" or "0X" for base 16 */ + + if ( base == 16 && *nptr == L'0' + && (nptr[1] == L'X' || nptr[1] == L'x') + ) + nptr += 2; /* skip past this prefix */ + + /* check whether there is at least one valid digit */ + + n = ToWNumber(*nptr); + ++nptr; + + if ( !valid(n, base) ) + return 0; /* subject seq. not of expected form */ + + accum = n; + + for ( toobig = 0; n = ToWNumber(*nptr), valid(n, base); ++nptr ) + if ( accum > UINTMAX_MAX / base + 1 /* major wrap-around */ + || (next = base * accum + n) < accum /* minor wrap-around */ + ) + toobig = 1; /* but keep scanning */ + else + accum = next; + + if ( endptr != NULL ) + *endptr = (wchar_t *)nptr; /* -> first not-valid-digit */ + + if ( toobig ) + { + errno = ERANGE; + return UINTMAX_MAX; + } + else + return minus ? -accum : accum; /* (yes!) */ + } + +unsigned long long __attribute__ ((alias ("wcstoumax"))) +wcstoull (const wchar_t* __restrict__ nptr, wchar_t ** __restrict__ endptr, int base); diff --git a/libc/mingw/misc/wctob.c b/libc/mingw/misc/wctob.c new file mode 100644 index 000000000..008e69117 --- /dev/null +++ b/libc/mingw/misc/wctob.c @@ -0,0 +1,29 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include "mb_wc_common.h" +#include +#include +#include +#include +#include + +/* Return just the first byte after translating to multibyte. */ +int wctob (wint_t wc ) +{ + wchar_t w = wc; + char c; + int invalid_char = 0; + if (!WideCharToMultiByte (___lc_codepage_func(), + 0 /* Is this correct flag? */, + &w, 1, &c, 1, NULL, &invalid_char) + || invalid_char) + return EOF; + + return (int) c; +} diff --git a/libc/mingw/misc/wctrans.c b/libc/mingw/misc/wctrans.c new file mode 100644 index 000000000..bcd9ef9fa --- /dev/null +++ b/libc/mingw/misc/wctrans.c @@ -0,0 +1,65 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + wctrans.c + 7.25.3.2 Extensible wide-character case mapping functions + + Contributed by: Danny Smith + 2005-02-24 + + This source code is placed in the PUBLIC DOMAIN. It is modified + from the Q8 package created by Doug Gwyn + + */ + +#include +#include + +/* + This differs from the MS implementation of wctrans which + returns 0 for tolower and 1 for toupper. According to + C99, a 0 return value indicates invalid input. + + These two function go in the same translation unit so that we + can ensure that + towctrans(wc, wctrans("tolower")) == towlower(wc) + towctrans(wc, wctrans("toupper")) == towupper(wc) + It also ensures that + towctrans(wc, wctrans("")) == wc + which is not required by standard. +*/ + +static const struct { + const char *name; + wctrans_t val; } tmap[] = { + {"tolower", _LOWER}, + {"toupper", _UPPER} + }; + +#define NTMAP (sizeof tmap / sizeof tmap[0]) + +wctrans_t +wctrans (const char* property) +{ + int i; + for ( i = 0; i < (int) NTMAP; ++i ) + if (strcmp (property, tmap[i].name) == 0) + return tmap[i].val; + return 0; +} + +wint_t towctrans (wint_t wc, wctrans_t desc) +{ + switch (desc) + { + case _LOWER: + return towlower (wc); + case _UPPER: + return towupper (wc); + default: + return wc; + } +} diff --git a/libc/mingw/misc/wctype.c b/libc/mingw/misc/wctype.c new file mode 100644 index 000000000..b6cfc1ddf --- /dev/null +++ b/libc/mingw/misc/wctype.c @@ -0,0 +1,65 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* + wctype.c + 7.25.2.2.2 The wctype function + + Contributed by: Danny Smith + 2005-02-24 + + This source code is placed in the PUBLIC DOMAIN. It is modified + from the Q8 package created by Doug Gwyn + + The wctype function constructs a value with type wctype_t that + describes a class of wide characters identified by the string + argument property. + + In particular, we map the property strings so that: + + iswctype(wc, wctype("alnum")) == iswalnum(wc) + iswctype(wc, wctype("alpha")) == iswalpha(wc) + iswctype(wc, wctype("cntrl")) == iswcntrl(wc) + iswctype(wc, wctype("digit")) == iswdigit(wc) + iswctype(wc, wctype("graph")) == iswgraph(wc) + iswctype(wc, wctype("lower")) == iswlower(wc) + iswctype(wc, wctype("print")) == iswprint(wc) + iswctype(wc, wctype("punct")) == iswpunct(wc) + iswctype(wc, wctype("space")) == iswspace(wc) + iswctype(wc, wctype("upper")) == iswupper(wc) + iswctype(wc, wctype("xdigit")) == iswxdigit(wc) + +*/ + +#include +#include + +/* Using the bit-OR'd ctype character classification flags as return + values achieves compatibility with MS iswctype(). */ +static const struct { + const char *name; + wctype_t flags;} cmap[] = { + {"alnum", _ALPHA|_DIGIT}, + {"alpha", _ALPHA}, + {"cntrl", _CONTROL}, + {"digit", _DIGIT}, + {"graph", _PUNCT|_ALPHA|_DIGIT}, + {"lower", _LOWER}, + {"print", _BLANK|_PUNCT|_ALPHA|_DIGIT}, + {"punct", _PUNCT}, + {"space", _SPACE}, + {"upper", _UPPER}, + {"xdigit", _HEX} + }; + +#define NCMAP (sizeof cmap / sizeof cmap[0]) +wctype_t wctype (const char *property) +{ + int i; + for (i = 0; i < (int) NCMAP; ++i) + if (strcmp (property, cmap[i].name) == 0) + return cmap[i].flags; + return 0; +} diff --git a/libc/mingw/misc/wdirent.c b/libc/mingw/misc/wdirent.c new file mode 100644 index 000000000..6dcf42bd5 --- /dev/null +++ b/libc/mingw/misc/wdirent.c @@ -0,0 +1,5 @@ +#define _UNICODE 1 +#define UNICODE 1 + +#include +#include "dirent.c" diff --git a/libc/mingw/misc/winbs_uint64.c b/libc/mingw/misc/winbs_uint64.c new file mode 100644 index 000000000..c0b316221 --- /dev/null +++ b/libc/mingw/misc/winbs_uint64.c @@ -0,0 +1,39 @@ +unsigned long long __cdecl _byteswap_uint64(unsigned long long _Int64); + +unsigned long long __cdecl _byteswap_uint64(unsigned long long _Int64) +{ +#if defined(_AMD64_) || defined(__x86_64__) + unsigned long long retval; + __asm__ __volatile__ ("bswapq %[retval]" : [retval] "=rm" (retval) : "[retval]" (_Int64)); + return retval; +#elif defined(_X86_) || defined(__i386__) + union { + long long int64part; + struct { + unsigned long lowpart; + unsigned long hipart; + }; + } retval; + retval.int64part = _Int64; + __asm__ __volatile__ ("bswapl %[lowpart]\n" + "bswapl %[hipart]\n" + : [lowpart] "=rm" (retval.hipart), [hipart] "=rm" (retval.lowpart) : "[lowpart]" (retval.lowpart), "[hipart]" (retval.hipart)); + return retval.int64part; +#else + unsigned char *b = (void*)&_Int64; + unsigned char tmp; + tmp = b[0]; + b[0] = b[7]; + b[7] = tmp; + tmp = b[1]; + b[1] = b[6]; + b[6] = tmp; + tmp = b[2]; + b[2] = b[5]; + b[5] = tmp; + tmp = b[3]; + b[3] = b[4]; + b[4] = tmp; + return _Int64; +#endif +} diff --git a/libc/mingw/misc/winbs_ulong.c b/libc/mingw/misc/winbs_ulong.c new file mode 100644 index 000000000..9cd6b2907 --- /dev/null +++ b/libc/mingw/misc/winbs_ulong.c @@ -0,0 +1,20 @@ +unsigned long __cdecl _byteswap_ulong (unsigned long _Long); + +unsigned long __cdecl _byteswap_ulong (unsigned long _Long) +{ +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + unsigned long retval; + __asm__ __volatile__ ("bswapl %[retval]" : [retval] "=rm" (retval) : "[retval]" (_Long)); + return retval; +#else + unsigned char *b = (void*)&_Long; + unsigned char tmp; + tmp = b[0]; + b[0] = b[3]; + b[3] = tmp; + tmp = b[1]; + b[1] = b[2]; + b[2] = tmp; + return _Long; +#endif /* defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) */ +} diff --git a/libc/mingw/misc/winbs_ushort.c b/libc/mingw/misc/winbs_ushort.c new file mode 100644 index 000000000..46b57fda4 --- /dev/null +++ b/libc/mingw/misc/winbs_ushort.c @@ -0,0 +1,17 @@ +unsigned short __cdecl _byteswap_ushort(unsigned short _Short); + +unsigned short __cdecl _byteswap_ushort(unsigned short _Short) +{ +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + unsigned short retval; + __asm__ __volatile__ ("rorw $8, %w[retval]" : [retval] "=rm" (retval) : "[retval]" (_Short)); + return retval; +#else + unsigned char *b = (void*)&_Short; + unsigned char tmp; + tmp = b[0]; + b[0] = b[1]; + b[1] = tmp; + return _Short; +#endif /* defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) */ +} diff --git a/libc/mingw/misc/wmemchr.c b/libc/mingw/misc/wmemchr.c new file mode 100644 index 000000000..fb037f7f5 --- /dev/null +++ b/libc/mingw/misc/wmemchr.c @@ -0,0 +1,35 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#define __CRT__NO_INLINE +#include + +#if 0 +wchar_t *wmemchr(s, c, n) + register const wchar_t *s; + register wchar_t c; + register size_t n; +{ + if ( s != NULL ) + for ( ; n > 0; ++s, --n ) + if ( *s == c ) + return (wchar_t *)s; + + return NULL; +} +#endif + +_CONST_RETURN wchar_t *__cdecl wmemchr(const wchar_t *_S,wchar_t _C,size_t _N) +{ + if (_S != NULL) + { + for ( ; 0 < _N; ++_S, --_N) + if (*_S == _C) + return (_CONST_RETURN wchar_t *)(_S); + } + return NULL; +} + diff --git a/libc/mingw/misc/wmemcmp.c b/libc/mingw/misc/wmemcmp.c new file mode 100644 index 000000000..5917b5a62 --- /dev/null +++ b/libc/mingw/misc/wmemcmp.c @@ -0,0 +1,56 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +/* This source code was extracted from the Q8 package created and placed + in the PUBLIC DOMAIN by Doug Gwyn + last edit: 1999/11/05 gwyn@arl.mil + + Implements subclause 7.24 of ISO/IEC 9899:1999 (E). + + It supports an encoding where all char codes are mapped + to the *same* code values within a wchar_t or wint_t, + so long as no other wchar_t codes are used by the program. + +*/ + +#define __CRT__NO_INLINE +#include + +#if 0 +int +wmemcmp(s1, s2, n) + register const wchar_t *s1; + register const wchar_t *s2; + size_t n; +{ + if ( n == 0 || s1 == s2 ) + return 0; /* even for NULL pointers */ + + if ( (s1 != NULL) != (s2 != NULL) ) + return s2 == NULL ? 1 : -1; /* robust */ + + for ( ; n > 0; ++s1, ++s2, --n ) + if ( *s1 != *s2 ) + return *s1 - *s2; + + return 0; +} +#endif + +int __cdecl wmemcmp(const wchar_t *_S1,const wchar_t *_S2,size_t _N) +{ + if (_N == 0 || _S1 == _S2) + return 0; /* even for NULL pointers */ + + if ((_S1 != NULL) != (_S2 != NULL)) + return _S2 == NULL ? 1 : -1; /* robust */ + + for ( ; 0 < _N; ++_S1, ++_S2, --_N) + if (*_S1 != *_S2) + return (*_S1 < *_S2 ? -1 : +1); + + return 0; +} + diff --git a/libc/mingw/misc/wmemcpy.c b/libc/mingw/misc/wmemcpy.c new file mode 100644 index 000000000..a84091322 --- /dev/null +++ b/libc/mingw/misc/wmemcpy.c @@ -0,0 +1,33 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#define __CRT__NO_INLINE +#include + +#if 0 +wchar_t * +wmemcpy(s1, s2, n) + register wchar_t * __restrict__ s1; + register const wchar_t * __restrict__ s2; + register size_t n; +{ + wchar_t *orig_s1 = s1; + + if ( s1 == NULL || s2 == NULL || n == 0 ) + return orig_s1; /* robust */ + + for ( ; n > 0; --n ) + *s1++ = *s2++; + + return orig_s1; +} +#endif + +wchar_t *__cdecl wmemcpy(wchar_t *_S1,const wchar_t *_S2,size_t _N) +{ + return (wchar_t *)memcpy(_S1,_S2,_N*sizeof(wchar_t)); +} + diff --git a/libc/mingw/misc/wmemmove.c b/libc/mingw/misc/wmemmove.c new file mode 100644 index 000000000..1b9e42c12 --- /dev/null +++ b/libc/mingw/misc/wmemmove.c @@ -0,0 +1,45 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#define __CRT__NO_INLINE +#include +#include +#include +#include + +#if 0 +wchar_t * +wmemmove(s1, s2, n) + register wchar_t *s1; + register const wchar_t *s2; + register size_t n; +{ + wchar_t *orig_s1 = s1; + + if ( s1 == NULL || s2 == NULL || n == 0 ) + return orig_s1; /* robust */ + + /* XXX -- The following test works only within a flat address space! */ + if ( s2 >= s1 ) + for ( ; n > 0; --n ) + *s1++ = *s2++; + else { + s1 += n; + s2 += n; + + for ( ; n > 0; --n ) + *--s1 = *--s2; + } + + return orig_s1; +} +#endif + +wchar_t *__cdecl wmemmove(wchar_t *_S1,const wchar_t *_S2,size_t _N) +{ + return (wchar_t *)memmove(_S1,_S2,_N*sizeof(wchar_t)); +} + diff --git a/libc/mingw/misc/wmempcpy.c b/libc/mingw/misc/wmempcpy.c new file mode 100644 index 000000000..0ad3e5003 --- /dev/null +++ b/libc/mingw/misc/wmempcpy.c @@ -0,0 +1,12 @@ +#define __CRT__NO_INLINE +#include + +wchar_t * __cdecl +wmempcpy (wchar_t *d, const wchar_t *s, size_t len) +{ + wchar_t *r = d + len; + if (len != 0) + memcpy (d, s, len * sizeof (wchar_t)); + return r; +} + diff --git a/libc/mingw/misc/wmemset.c b/libc/mingw/misc/wmemset.c new file mode 100644 index 000000000..26917b03b --- /dev/null +++ b/libc/mingw/misc/wmemset.c @@ -0,0 +1,34 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#define __CRT__NO_INLINE +#include + +#if 0 +wchar_t * +wmemset(s, c, n) + register wchar_t *s; + register wchar_t c; + register size_t n; +{ + wchar_t *orig_s = s; + + if ( s != NULL ) + for ( ; n > 0; --n ) + *s++ = c; + + return orig_s; +} +#endif + +wchar_t *__cdecl wmemset(wchar_t *_S,wchar_t _C,size_t _N) +{ + wchar_t *_Su = _S; + for ( ; 0 < _N; ++_Su, --_N) + *_Su = _C; + return (_S); +} + diff --git a/libc/mingw/stdio/_Exit.c b/libc/mingw/stdio/_Exit.c new file mode 100644 index 000000000..5b049f566 --- /dev/null +++ b/libc/mingw/stdio/_Exit.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +void _Exit(int status) + { _exit(status); } diff --git a/libc/mingw/stdio/_findfirst64i32.c b/libc/mingw/stdio/_findfirst64i32.c new file mode 100644 index 000000000..8942dc153 --- /dev/null +++ b/libc/mingw/stdio/_findfirst64i32.c @@ -0,0 +1,21 @@ +#define __CRT__NO_INLINE +#include +#include + +intptr_t __cdecl _findfirst64i32(const char *_Filename,struct _finddata64i32_t *_FindData) +{ + struct __finddata64_t fd; + intptr_t ret = _findfirst64(_Filename,&fd); + if (ret == -1) { + memset(_FindData,0,sizeof(struct _finddata64i32_t)); + return -1; + } + _FindData->attrib=fd.attrib; + _FindData->time_create=fd.time_create; + _FindData->time_access=fd.time_access; + _FindData->time_write=fd.time_write; + _FindData->size=(_fsize_t) fd.size; + strncpy(_FindData->name,fd.name,260); + return ret; +} + diff --git a/libc/mingw/stdio/_findnext64i32.c b/libc/mingw/stdio/_findnext64i32.c new file mode 100644 index 000000000..90ae45443 --- /dev/null +++ b/libc/mingw/stdio/_findnext64i32.c @@ -0,0 +1,21 @@ +#define __CRT__NO_INLINE +#include +#include + +int __cdecl _findnext64i32(intptr_t _FindHandle,struct _finddata64i32_t *_FindData) +{ + struct __finddata64_t fd; + int ret = _findnext64(_FindHandle,&fd); + if (ret == -1) { + memset(_FindData,0,sizeof(struct _finddata64i32_t)); + return -1; + } + _FindData->attrib=fd.attrib; + _FindData->time_create=fd.time_create; + _FindData->time_access=fd.time_access; + _FindData->time_write=fd.time_write; + _FindData->size=(_fsize_t) fd.size; + strncpy(_FindData->name,fd.name,260); + return ret; +} + diff --git a/libc/mingw/stdio/_fstat.c b/libc/mingw/stdio/_fstat.c new file mode 100644 index 000000000..efc097e2c --- /dev/null +++ b/libc/mingw/stdio/_fstat.c @@ -0,0 +1,52 @@ +#define __CRT__NO_INLINE +#include + +/* FIXME: Relying on _USE_32BIT_TIME_T, which is a user-macro, +during CRT compilation is plainly broken. Need an appropriate +implementation to provide users the ability of compiling the +CRT only with 32-bit time_t behavior. */ +#if defined(_USE_32BIT_TIME_T) +int __cdecl +fstat(int _Desc,struct stat *_Stat) +{ + struct _stat32 st; + int ret=_fstat32(_Desc,&st); + if (ret == -1) { + memset(_Stat,0,sizeof(struct stat)); + return -1; + } + /* struct stat and struct _stat32 + are the same for this case. */ + memcpy(_Stat, &st, sizeof(struct _stat32)); + return ret; +} +#else +int __cdecl +fstat(int _Desc,struct stat *_Stat) +{ + struct _stat64 st; + int ret=_fstat64(_Desc,&st); + if (ret == -1) { + memset(_Stat,0,sizeof(struct stat)); + return -1; + } + /* struct stat and struct _stat64i32 + are the same for this case. */ + _Stat->st_dev=st.st_dev; + _Stat->st_ino=st.st_ino; + _Stat->st_mode=st.st_mode; + _Stat->st_nlink=st.st_nlink; + _Stat->st_uid=st.st_uid; + _Stat->st_gid=st.st_gid; + _Stat->st_rdev=st.st_rdev; + _Stat->st_size=(_off_t) st.st_size; + _Stat->st_atime=st.st_atime; + _Stat->st_mtime=st.st_mtime; + _Stat->st_ctime=st.st_ctime; + return ret; +} +#endif + +/* Add __imp__fstat and __imp__stat symbols. */ +int (*__MINGW_IMP_SYMBOL(fstat))(int, struct stat *) = &fstat; + diff --git a/libc/mingw/stdio/_fstat64i32.c b/libc/mingw/stdio/_fstat64i32.c new file mode 100644 index 000000000..57cc492d7 --- /dev/null +++ b/libc/mingw/stdio/_fstat64i32.c @@ -0,0 +1,25 @@ +#define __CRT__NO_INLINE +#include + +int __cdecl _fstat64i32(int _FileDes,struct _stat64i32 *_Stat) +{ + struct _stat64 st; + int ret=_fstat64(_FileDes,&st); + if (ret == -1) { + memset(_Stat,0,sizeof(struct _stat64i32)); + return -1; + } + _Stat->st_dev=st.st_dev; + _Stat->st_ino=st.st_ino; + _Stat->st_mode=st.st_mode; + _Stat->st_nlink=st.st_nlink; + _Stat->st_uid=st.st_uid; + _Stat->st_gid=st.st_gid; + _Stat->st_rdev=st.st_rdev; + _Stat->st_size=(_off_t) st.st_size; /* 32bit size */ + _Stat->st_atime=st.st_atime; + _Stat->st_mtime=st.st_mtime; + _Stat->st_ctime=st.st_ctime; + return ret; +} + diff --git a/libc/mingw/stdio/_ftime.c b/libc/mingw/stdio/_ftime.c new file mode 100644 index 000000000..0600790f9 --- /dev/null +++ b/libc/mingw/stdio/_ftime.c @@ -0,0 +1,19 @@ +#define __CRT__NO_INLINE +#include +#include + +/* FIXME: Relying on _USE_32BIT_TIME_T, which is a user-macro, +during CRT compilation is plainly broken. Need an appropriate +implementation to provide users the ability of compiling the +CRT only with 32-bit time_t behavior. */ +#if defined(_USE_32BIT_TIME_T) +void __cdecl ftime (struct timeb *b) +{ + return _ftime ((struct __timeb32 *)b); +} +#else +void __cdecl ftime (struct timeb *b) +{ + _ftime64((struct __timeb64 *)b); +} +#endif diff --git a/libc/mingw/stdio/_getc_nolock.c b/libc/mingw/stdio/_getc_nolock.c new file mode 100644 index 000000000..8b34d98cb --- /dev/null +++ b/libc/mingw/stdio/_getc_nolock.c @@ -0,0 +1,8 @@ +#include + +#undef _getc_nolock +int __cdecl _getc_nolock(FILE *stream); +int __cdecl _getc_nolock(FILE *stream) +{ + return _fgetc_nolock(stream); +} diff --git a/libc/mingw/stdio/_getwc_nolock.c b/libc/mingw/stdio/_getwc_nolock.c new file mode 100644 index 000000000..1d79602c1 --- /dev/null +++ b/libc/mingw/stdio/_getwc_nolock.c @@ -0,0 +1,8 @@ +#include + +#undef _getwc_nolock +wint_t __cdecl _getwc_nolock(FILE *stream); +wint_t __cdecl _getwc_nolock(FILE *stream) +{ + return _fgetwc_nolock(stream); +} diff --git a/libc/mingw/stdio/_putc_nolock.c b/libc/mingw/stdio/_putc_nolock.c new file mode 100644 index 000000000..47f1655bd --- /dev/null +++ b/libc/mingw/stdio/_putc_nolock.c @@ -0,0 +1,8 @@ +#include + +#undef _putc_nolock +int __cdecl _putc_nolock(int c, FILE *stream); +int __cdecl _putc_nolock(int c, FILE *stream) +{ + return _fputc_nolock(c, stream); +} diff --git a/libc/mingw/stdio/_putwc_nolock.c b/libc/mingw/stdio/_putwc_nolock.c new file mode 100644 index 000000000..77fe8fda7 --- /dev/null +++ b/libc/mingw/stdio/_putwc_nolock.c @@ -0,0 +1,8 @@ +#include + +#undef _putwc_nolock +wint_t __cdecl _putwc_nolock(wchar_t c, FILE *stream); +wint_t __cdecl _putwc_nolock(wchar_t c, FILE *stream) +{ + return _fputwc_nolock(c, stream); +} diff --git a/libc/mingw/stdio/_stat.c b/libc/mingw/stdio/_stat.c new file mode 100644 index 000000000..fbb985e38 --- /dev/null +++ b/libc/mingw/stdio/_stat.c @@ -0,0 +1,120 @@ +#define __CRT__NO_INLINE +#include +#include + +/** + * Returns _path without trailing slash if any + * + * - if _path has no trailing slash, the function returns it + * - if _path has a trailing slash, but is of the form C:/, then it returns it + * - otherwise, the function creates a new string, which is a copy of _path + * without the trailing slash. It is then the responsibility of the caller + * to free it. + */ + +static char* +_mingw_no_trailing_slash (const char* _path) +{ + int len; + char *p; + + p = (char*)_path; + + if (_path && *_path) { + len = strlen (_path); + + /* Ignore X:\ */ + + if (len <= 1 || ((len == 2 || len == 3) && _path[1] == ':')) + return p; + + /* Check UNC \\abc\\ */ + if ((_path[0] == '\\' || _path[0] == '/') + && (_path[1] == '\\' || _path[1] == '/')) + { + const char *r = &_path[2]; + while (*r != 0 && *r != '\\' && *r != '/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + while (*r != 0 && *r != '\\' && *r != '/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + } + + if (_path[len - 1] == '/' || _path[len - 1] == '\\') + { + p = (char*)malloc (len); + memcpy (p, _path, len - 1); + p[len - 1] = '\0'; + } + } + + return p; +} +/* FIXME: Relying on _USE_32BIT_TIME_T, which is a user-macro, +during CRT compilation is plainly broken. Need an appropriate +implementation to provide users the ability of compiling the +CRT only with 32-bit time_t behavior. */ +#if defined(_USE_32BIT_TIME_T) +int __cdecl +stat(const char *_Filename,struct stat *_Stat) +{ + struct _stat32 st; + char *_path = _mingw_no_trailing_slash(_Filename); + + int ret=_stat32(_path,&st); + + if (_path != _Filename) + free (_path); + + if (ret == -1) { + memset(_Stat,0,sizeof(struct stat)); + return -1; + } + /* struct stat and struct _stat32 + are the same for this case. */ + memcpy(_Stat, &st, sizeof(struct _stat32)); + return ret; +} +#else +int __cdecl +stat(const char *_Filename,struct stat *_Stat) +{ + struct _stat64 st; + char *_path = _mingw_no_trailing_slash(_Filename); + + int ret=_stat64(_path,&st); + + if (_path != _Filename) + free (_path); + + if (ret == -1) { + memset(_Stat,0,sizeof(struct stat)); + return -1; + } + /* struct stat and struct _stat64i32 + are the same for this case. */ + _Stat->st_dev=st.st_dev; + _Stat->st_ino=st.st_ino; + _Stat->st_mode=st.st_mode; + _Stat->st_nlink=st.st_nlink; + _Stat->st_uid=st.st_uid; + _Stat->st_gid=st.st_gid; + _Stat->st_rdev=st.st_rdev; + _Stat->st_size=(_off_t) st.st_size; + _Stat->st_atime=st.st_atime; + _Stat->st_mtime=st.st_mtime; + _Stat->st_ctime=st.st_ctime; + return ret; +} +#endif + +/* Add __imp__fstat and __imp__stat symbols. */ +int (*__MINGW_IMP_SYMBOL(stat))(const char *,struct stat *) = &stat; + diff --git a/libc/mingw/stdio/_stat64i32.c b/libc/mingw/stdio/_stat64i32.c new file mode 100644 index 000000000..19adf5b0e --- /dev/null +++ b/libc/mingw/stdio/_stat64i32.c @@ -0,0 +1,88 @@ +#define __CRT__NO_INLINE +#include +#include + +/** + * Returns _path without trailing slash if any + * + * - if _path has no trailing slash, the function returns it + * - if _path has a trailing slash, but is of the form C:/, then it returns it + * - otherwise, the function creates a new string, which is a copy of _path + * without the trailing slash. It is then the responsibility of the caller + * to free it. + */ + +static char* +_mingw_no_trailing_slash (const char* _path) +{ + int len; + char *p; + + p = (char*)_path; + + if (_path && *_path) { + len = strlen (_path); + + /* Ignore X:\ */ + + if (len <= 1 || ((len == 2 || len == 3) && _path[1] == ':')) + return p; + + /* Check UNC \\abc\\ */ + if ((_path[0] == '\\' || _path[0] == '/') + && (_path[1] == '\\' || _path[1] == '/')) + { + const char *r = &_path[2]; + while (*r != 0 && *r != '\\' && *r != '/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + while (*r != 0 && *r != '\\' && *r != '/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + } + + if (_path[len - 1] == '/' || _path[len - 1] == '\\') + { + p = (char*)malloc (len); + memcpy (p, _path, len - 1); + p[len - 1] = '\0'; + } + } + + return p; +} + +int __cdecl _stat64i32(const char *_Name,struct _stat64i32 *_Stat) +{ + struct _stat64 st; + char *_path = _mingw_no_trailing_slash(_Name); + + int ret=_stat64(_path,&st); + + if (_path != _Name) + free(_path); + + if (ret == -1) { + memset(_Stat,0,sizeof(struct _stat64i32)); + return -1; + } + _Stat->st_dev=st.st_dev; + _Stat->st_ino=st.st_ino; + _Stat->st_mode=st.st_mode; + _Stat->st_nlink=st.st_nlink; + _Stat->st_uid=st.st_uid; + _Stat->st_gid=st.st_gid; + _Stat->st_rdev=st.st_rdev; + _Stat->st_size=(_off_t) st.st_size; + _Stat->st_atime=st.st_atime; + _Stat->st_mtime=st.st_mtime; + _Stat->st_ctime=st.st_ctime; + return ret; +} + diff --git a/libc/mingw/stdio/_wfindfirst64i32.c b/libc/mingw/stdio/_wfindfirst64i32.c new file mode 100644 index 000000000..d355e524e --- /dev/null +++ b/libc/mingw/stdio/_wfindfirst64i32.c @@ -0,0 +1,21 @@ +#define __CRT__NO_INLINE +#include +#include + +intptr_t __cdecl _wfindfirst64i32(const wchar_t *_Filename,struct _wfinddata64i32_t *_FindData) +{ + struct _wfinddata64_t fd; + intptr_t ret = _wfindfirst64(_Filename,&fd); + if (ret == -1) { + memset(_FindData,0,sizeof(struct _wfinddata64i32_t)); + return -1; + } + _FindData->attrib=fd.attrib; + _FindData->time_create=fd.time_create; + _FindData->time_access=fd.time_access; + _FindData->time_write=fd.time_write; + _FindData->size=(_fsize_t) fd.size; + memcpy(_FindData->name,fd.name,260*sizeof(wchar_t)); + return ret; +} + diff --git a/libc/mingw/stdio/_wfindnext64i32.c b/libc/mingw/stdio/_wfindnext64i32.c new file mode 100644 index 000000000..c8d534275 --- /dev/null +++ b/libc/mingw/stdio/_wfindnext64i32.c @@ -0,0 +1,21 @@ +#define __CRT__NO_INLINE +#include +#include + +int __cdecl _wfindnext64i32(intptr_t _FindHandle,struct _wfinddata64i32_t *_FindData) +{ + struct _wfinddata64_t fd; + int ret = _wfindnext64(_FindHandle,&fd); + if (ret == -1) { + memset(_FindData,0,sizeof(struct _wfinddata64i32_t)); + return -1; + } + _FindData->attrib=fd.attrib; + _FindData->time_create=fd.time_create; + _FindData->time_access=fd.time_access; + _FindData->time_write=fd.time_write; + _FindData->size=(_fsize_t) fd.size; + memcpy(_FindData->name,fd.name,260*sizeof(wchar_t)); + return ret; +} + diff --git a/libc/mingw/stdio/_wstat.c b/libc/mingw/stdio/_wstat.c new file mode 100644 index 000000000..08566168f --- /dev/null +++ b/libc/mingw/stdio/_wstat.c @@ -0,0 +1,119 @@ +#define __CRT__NO_INLINE +#include +#include +#include + +/** + * Returns _path without trailing slash if any + * + * - if _path has no trailing slash, the function returns it + * - if _path has a trailing slash, but is of the form C:/, then it returns it + * - otherwise, the function creates a new string, which is a copy of _path + * without the trailing slash. It is then the responsibility of the caller + * to free it. + */ + +static wchar_t* +_mingw_no_trailing_slash (const wchar_t* _path) +{ + int len; + wchar_t *p; + + p = (wchar_t*)_path; + + if (_path && *_path) { + len = wcslen (_path); + + /* Ignore X:\ */ + + if (len <= 1 || ((len == 2 || len == 3) && _path[1] == L':')) + return p; + + /* Check UNC \\abc\\ */ + if ((_path[0] == L'\\' || _path[0] == L'/') + && (_path[1] == L'\\' || _path[1] == L'/')) + { + const wchar_t *r = &_path[2]; + while (*r != 0 && *r != L'\\' && *r != L'/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + while (*r != 0 && *r != L'\\' && *r != L'/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + } + + if (_path[len - 1] == L'/' || _path[len - 1] == L'\\') + { + p = (wchar_t*)malloc (len * sizeof(wchar_t)); + memcpy (p, _path, (len - 1) * sizeof(wchar_t)); + p[len - 1] = L'\0'; + } + } + + return p; +} + +/* FIXME: Relying on _USE_32BIT_TIME_T, which is a user-macro, +during CRT compilation is plainly broken. Need an appropriate +implementation to provide users the ability of compiling the +CRT only with 32-bit time_t behavior. */ +#if defined(_USE_32BIT_TIME_T) +int __cdecl +wstat(const wchar_t *_Filename,struct stat *_Stat) +{ + struct _stat32 st; + wchar_t *_path = _mingw_no_trailing_slash(_Filename); + + int ret=_wstat32(_path,&st); + + if (_path != _Filename) + free (_path); + + if (ret == -1) { + memset(_Stat,0,sizeof(struct stat)); + return -1; + } + /* struct stat and struct _stat32 + are the same for this case. */ + memcpy(_Stat, &st, sizeof(struct _stat32)); + return ret; +} +#else +int __cdecl +wstat(const wchar_t *_Filename,struct stat *_Stat) +{ + struct _stat64 st; + wchar_t *_path = _mingw_no_trailing_slash(_Filename); + + int ret=_wstat64(_path,&st); + + if (_path != _Filename) + free (_path); + + if (ret == -1) { + memset(_Stat,0,sizeof(struct stat)); + return -1; + } + /* struct stat and struct _stat64i32 + are the same for this case. */ + _Stat->st_dev=st.st_dev; + _Stat->st_ino=st.st_ino; + _Stat->st_mode=st.st_mode; + _Stat->st_nlink=st.st_nlink; + _Stat->st_uid=st.st_uid; + _Stat->st_gid=st.st_gid; + _Stat->st_rdev=st.st_rdev; + _Stat->st_size=(_off_t) st.st_size; + _Stat->st_atime=st.st_atime; + _Stat->st_mtime=st.st_mtime; + _Stat->st_ctime=st.st_ctime; + return ret; +} +#endif + diff --git a/libc/mingw/stdio/_wstat64i32.c b/libc/mingw/stdio/_wstat64i32.c new file mode 100644 index 000000000..d6ee07a3d --- /dev/null +++ b/libc/mingw/stdio/_wstat64i32.c @@ -0,0 +1,88 @@ +#define __CRT__NO_INLINE +#include +#include + +/** + * Returns _path without trailing slash if any + * + * - if _path has no trailing slash, the function returns it + * - if _path has a trailing slash, but is of the form C:/, then it returns it + * - otherwise, the function creates a new string, which is a copy of _path + * without the trailing slash. It is then the responsibility of the caller + * to free it. + */ + +static wchar_t* +_mingw_no_trailing_slash (const wchar_t* _path) +{ + int len; + wchar_t *p; + + p = (wchar_t*)_path; + + if (_path && *_path) { + len = wcslen (_path); + + /* Ignore X:\ */ + + if (len <= 1 || ((len == 2 || len == 3) && _path[1] == L':')) + return p; + + /* Check UNC \\abc\\ */ + if ((_path[0] == L'\\' || _path[0] == L'/') + && (_path[1] == L'\\' || _path[1] == L'/')) + { + const wchar_t *r = &_path[2]; + while (*r != 0 && *r != L'\\' && *r != L'/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + while (*r != 0 && *r != L'\\' && *r != L'/') + ++r; + if (*r != 0) + ++r; + if (*r == 0) + return p; + } + + if (_path[len - 1] == L'/' || _path[len - 1] == L'\\') + { + p = (wchar_t*)malloc (len * sizeof(wchar_t)); + memcpy (p, _path, (len - 1) * sizeof(wchar_t)); + p[len - 1] = L'\0'; + } + } + + return p; +} + +int __cdecl _wstat64i32(const wchar_t *_Name,struct _stat64i32 *_Stat) +{ + struct _stat64 st; + wchar_t *_path = _mingw_no_trailing_slash(_Name); + + int ret=_wstat64(_path,&st); + + if (_path != _Name) + free(_path); + + if (ret == -1) { + memset(_Stat,0,sizeof(struct _stat64i32)); + return -1; + } + _Stat->st_dev=st.st_dev; + _Stat->st_ino=st.st_ino; + _Stat->st_mode=st.st_mode; + _Stat->st_nlink=st.st_nlink; + _Stat->st_uid=st.st_uid; + _Stat->st_gid=st.st_gid; + _Stat->st_rdev=st.st_rdev; + _Stat->st_size=(_off_t) st.st_size; + _Stat->st_atime=st.st_atime; + _Stat->st_mtime=st.st_mtime; + _Stat->st_ctime=st.st_ctime; + return ret; +} + diff --git a/libc/mingw/stdio/asprintf.c b/libc/mingw/stdio/asprintf.c new file mode 100644 index 000000000..4e7db60da --- /dev/null +++ b/libc/mingw/stdio/asprintf.c @@ -0,0 +1,31 @@ +#define _GNU_SOURCE +#define __CRT__NO_INLINE + +#include +#include +#include + +int asprintf(char ** __restrict__ ret, + const char * __restrict__ format, + ...) { + va_list ap; + int len; + va_start(ap,format); + /* Get Length */ + len = _vsnprintf(NULL,0,format,ap); + if (len < 0) goto _end; + /* +1 for \0 terminator. */ + *ret = malloc(len + 1); + /* Check malloc fail*/ + if (!*ret) { + len = -1; + goto _end; + } + /* Write String */ + _vsnprintf(*ret,len+1,format,ap); + /* Terminate explicitly */ + (*ret)[len] = '\0'; + _end: + va_end(ap); + return len; +} diff --git a/libc/mingw/stdio/atoll.c b/libc/mingw/stdio/atoll.c new file mode 100644 index 000000000..39df0139f --- /dev/null +++ b/libc/mingw/stdio/atoll.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +long long atoll (const char * _c) + { return _atoi64 (_c); } diff --git a/libc/mingw/stdio/fgetpos64.c b/libc/mingw/stdio/fgetpos64.c new file mode 100644 index 000000000..2adb66efb --- /dev/null +++ b/libc/mingw/stdio/fgetpos64.c @@ -0,0 +1,5 @@ +#include + +int __cdecl fgetpos64(FILE * __restrict__ _File ,fpos_t * __restrict__ _Pos){ + return fgetpos(_File, _Pos); +} diff --git a/libc/mingw/stdio/fopen64.c b/libc/mingw/stdio/fopen64.c new file mode 100644 index 000000000..1c6e78db5 --- /dev/null +++ b/libc/mingw/stdio/fopen64.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +FILE* fopen64 (const char* filename, const char* mode) +{ + return fopen (filename, mode); +} diff --git a/libc/mingw/stdio/fseeko32.c b/libc/mingw/stdio/fseeko32.c new file mode 100644 index 000000000..ca222ffbe --- /dev/null +++ b/libc/mingw/stdio/fseeko32.c @@ -0,0 +1,7 @@ +/*non-standard*/ +#include + +int fseeko(FILE* stream, _off_t offset, int whence){ + _off64_t off = offset; + return fseeko64(stream,off,whence); +} diff --git a/libc/mingw/stdio/fseeko64.c b/libc/mingw/stdio/fseeko64.c new file mode 100644 index 000000000..5905aa22e --- /dev/null +++ b/libc/mingw/stdio/fseeko64.c @@ -0,0 +1,258 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include +#include +#include +#include + +struct oserr_map { + unsigned long oscode; /* OS values */ + int errnocode; /* System V codes */ +}; + +typedef union doubleint { + __int64 bigint; + struct { + unsigned long lowerhalf; + long upperhalf; + } twoints; +} DINT; + +#define _IOYOURBUF 0x0100 +#define _IOSETVBUF 0x0400 +#define _IOFEOF 0x0800 +#define _IOFLRTN 0x1000 +#define _IOCTRLZ 0x2000 +#define _IOCOMMIT 0x4000 + +/* General use macros */ + +#define inuse(s) ((s)->_flag & (_IOREAD|_IOWRT|_IORW)) +#define mbuf(s) ((s)->_flag & _IOMYBUF) +#define nbuf(s) ((s)->_flag & _IONBF) +#define ybuf(s) ((s)->_flag & _IOYOURBUF) +#define bigbuf(s) ((s)->_flag & (_IOMYBUF|_IOYOURBUF)) +#define anybuf(s) ((s)->_flag & (_IOMYBUF|_IONBF|_IOYOURBUF)) + +#define _INTERNAL_BUFSIZ 4096 +#define _SMALL_BUFSIZ 512 + +#define FOPEN 0x01 /* file handle open */ +#define FEOFLAG 0x02 /* end of file has been encountered */ +#define FCRLF 0x04 /* CR-LF across read buffer (in text mode) */ +#define FPIPE 0x08 /* file handle refers to a pipe */ +#define FNOINHERIT 0x10 /* file handle opened _O_NOINHERIT */ +#define FAPPEND 0x20 /* file handle opened O_APPEND */ +#define FDEV 0x40 /* file handle refers to device */ +#define FTEXT 0x80 /* file handle is in text mode */ + +static struct oserr_map local_errtab[] = { + { ERROR_INVALID_FUNCTION, EINVAL }, { ERROR_FILE_NOT_FOUND, ENOENT }, + { ERROR_PATH_NOT_FOUND, ENOENT }, { ERROR_TOO_MANY_OPEN_FILES, EMFILE }, + { ERROR_ACCESS_DENIED, EACCES }, { ERROR_INVALID_HANDLE, EBADF }, + { ERROR_ARENA_TRASHED, ENOMEM }, { ERROR_NOT_ENOUGH_MEMORY, ENOMEM }, + { ERROR_INVALID_BLOCK, ENOMEM }, { ERROR_BAD_ENVIRONMENT, E2BIG }, + { ERROR_BAD_FORMAT, ENOEXEC }, { ERROR_INVALID_ACCESS, EINVAL }, + { ERROR_INVALID_DATA, EINVAL }, { ERROR_INVALID_DRIVE, ENOENT }, + { ERROR_CURRENT_DIRECTORY, EACCES }, { ERROR_NOT_SAME_DEVICE, EXDEV }, + { ERROR_NO_MORE_FILES, ENOENT }, { ERROR_LOCK_VIOLATION, EACCES }, + { ERROR_BAD_NETPATH, ENOENT }, { ERROR_NETWORK_ACCESS_DENIED, EACCES }, + { ERROR_BAD_NET_NAME, ENOENT }, { ERROR_FILE_EXISTS, EEXIST }, + { ERROR_CANNOT_MAKE, EACCES }, { ERROR_FAIL_I24, EACCES }, + { ERROR_INVALID_PARAMETER, EINVAL }, { ERROR_NO_PROC_SLOTS, EAGAIN }, + { ERROR_DRIVE_LOCKED, EACCES }, { ERROR_BROKEN_PIPE, EPIPE }, + { ERROR_DISK_FULL, ENOSPC }, { ERROR_INVALID_TARGET_HANDLE, EBADF }, + { ERROR_INVALID_HANDLE, EINVAL }, { ERROR_WAIT_NO_CHILDREN, ECHILD }, + { ERROR_CHILD_NOT_COMPLETE, ECHILD }, { ERROR_DIRECT_ACCESS_HANDLE, EBADF }, + { ERROR_NEGATIVE_SEEK, EINVAL }, { ERROR_SEEK_ON_DEVICE, EACCES }, + { ERROR_DIR_NOT_EMPTY, ENOTEMPTY }, { ERROR_NOT_LOCKED, EACCES }, + { ERROR_BAD_PATHNAME, ENOENT }, { ERROR_MAX_THRDS_REACHED, EAGAIN }, + { ERROR_LOCK_FAILED, EACCES }, { ERROR_ALREADY_EXISTS, EEXIST }, + { ERROR_FILENAME_EXCED_RANGE, ENOENT }, { ERROR_NESTING_NOT_ALLOWED, EAGAIN }, + { ERROR_NOT_ENOUGH_QUOTA, ENOMEM }, { 0, -1 } +}; + +_CRTIMP __int64 __cdecl _lseeki64(int fh,__int64 pos,int mthd); +__int64 __cdecl _ftelli64(FILE *str); +void mingw_dosmaperr (unsigned long oserrno); +int __cdecl _flush (FILE *str); + +int __cdecl _flush (FILE *str) +{ + FILE *stream; + int rc = 0; /* assume good return */ + __int64 nchar; + + stream = str; + if ((stream->_flag & (_IOREAD | _IOWRT)) == _IOWRT && bigbuf(stream) + && (nchar = (__int64) (stream->_ptr - stream->_base)) > 0ll) + { + if ( _write(_fileno(stream), stream->_base, nchar) == nchar) { + if (_IORW & stream->_flag) + stream->_flag &= ~_IOWRT; + } else { + stream->_flag |= _IOERR; + rc = EOF; + } + } + stream->_ptr = stream->_base; + stream->_cnt = 0ll; + return rc; +} + +int fseeko64 (FILE* stream, _off64_t offset, int whence) +{ + fpos_t pos; + if (whence == SEEK_CUR) + { + /* If stream is invalid, fgetpos sets errno. */ + if (fgetpos (stream, &pos)) + return (-1); + pos += (fpos_t) offset; + } + else if (whence == SEEK_END) + { + /* If writing, we need to flush before getting file length. */ + fflush (stream); + pos = (fpos_t) (_filelengthi64 (_fileno (stream)) + offset); + } + else if (whence == SEEK_SET) + pos = (fpos_t) offset; + else + { + errno = EINVAL; + return (-1); + } + return fsetpos (stream, &pos); +} + +int __cdecl _fseeki64(FILE *str,__int64 offset,int whence) +{ + FILE *stream; + /* Init stream pointer */ + stream = str; + errno=0; + if(!stream || ((whence != SEEK_SET) && (whence != SEEK_CUR) && (whence != SEEK_END))) + { + errno=EINVAL; + return -1; + } + /* Clear EOF flag */ + stream->_flag &= ~_IOEOF; + + if (whence == SEEK_CUR) { + offset += _ftelli64(stream); + whence = SEEK_SET; + } + /* Flush buffer as necessary */ + _flush(stream); + + /* If file opened for read/write, clear flags since we don't know + what the user is going to do next. If the file was opened for + read access only, decrease _bufsiz so that the next _filbuf + won't cost quite so much */ + + if (stream->_flag & _IORW) + stream->_flag &= ~(_IOWRT|_IOREAD); + else if ( (stream->_flag & _IOREAD) && (stream->_flag & _IOMYBUF) && + !(stream->_flag & _IOSETVBUF) ) + stream->_bufsiz = _SMALL_BUFSIZ; + + /* Seek to the desired locale and return. */ + + return (_lseeki64(_fileno(stream), offset, whence) == -1ll ? -1 : 0); +} + +__int64 __cdecl _ftelli64(FILE *str) +{ + FILE *stream; + size_t offset; + __int64 filepos; + register char *p; + char *max; + int fd; + size_t rdcnt = 0; + + errno=0; + stream = str; + fd = _fileno(stream); + if (stream->_cnt < 0ll) stream->_cnt = 0ll; + if ((filepos = _lseeki64(fd, 0ll, SEEK_CUR)) < 0L) + return -1ll; + + if (!bigbuf(stream)) /* _IONBF or no buffering designated */ + return (filepos - (__int64) stream->_cnt); + + offset = (size_t)(stream->_ptr - stream->_base); + + if (stream->_flag & (_IOWRT|_IOREAD)) + { + if (_osfile(fd) & FTEXT) + for (p = stream->_base; p < stream->_ptr; p++) + if (*p == '\n') /* adjust for '\r' */ + offset++; + } + else if (!(stream->_flag & _IORW)) { + errno=EINVAL; + return -1ll; + } + if (filepos == 0ll) + return ((__int64)offset); + + if (stream->_flag & _IOREAD) /* go to preceding sector */ + { + if (stream->_cnt == 0ll) /* filepos holds correct location */ + offset = 0ll; + else + { + rdcnt = ((size_t) stream->_cnt) + ((size_t) (size_t)(stream->_ptr - stream->_base)); + if (_osfile(fd) & FTEXT) { + if (_lseeki64(fd, 0ll, SEEK_END) == filepos) { + max = stream->_base + rdcnt; + for (p = stream->_base; p < max; p++) + if (*p == '\n') /* adjust for '\r' */ + rdcnt++; + if (stream->_flag & _IOCTRLZ) + ++rdcnt; + } else { + _lseeki64(fd, filepos, SEEK_SET); + if ( (rdcnt <= _SMALL_BUFSIZ) && (stream->_flag & _IOMYBUF) && + !(stream->_flag & _IOSETVBUF)) + rdcnt = _SMALL_BUFSIZ; + else + rdcnt = stream->_bufsiz; + if (_osfile(fd) & FCRLF) + ++rdcnt; + } + } /* end if FTEXT */ + } + filepos -= (__int64)rdcnt; + } /* end else stream->_cnt != 0 */ + return (filepos + (__int64)offset); +} + +void mingw_dosmaperr (unsigned long oserrno) +{ + size_t i; + + _doserrno = oserrno; /* set _doserrno */ + /* check the table for the OS error code */ + i = 0; + do { + if (oserrno == local_errtab[i].oscode) + { + errno = local_errtab[i].errnocode; + return; + } + } while (local_errtab[++i].errnocode != -1); + if (oserrno >= ERROR_WRITE_PROTECT && oserrno <= ERROR_SHARING_BUFFER_EXCEEDED) + errno = EACCES; + else if (oserrno >= ERROR_INVALID_STARTING_CODESEG && oserrno <= ERROR_INFLOOP_IN_RELOC_CHAIN) + errno = ENOEXEC; + else + errno = EINVAL; +} diff --git a/libc/mingw/stdio/fsetpos64.c b/libc/mingw/stdio/fsetpos64.c new file mode 100644 index 000000000..ab639f02f --- /dev/null +++ b/libc/mingw/stdio/fsetpos64.c @@ -0,0 +1,5 @@ +#include + +int __cdecl fsetpos64(FILE *_File,const fpos_t *_Pos){ /* fsetpos already 64bit */ + return fsetpos(_File,_Pos); +} diff --git a/libc/mingw/stdio/ftello.c b/libc/mingw/stdio/ftello.c new file mode 100644 index 000000000..1a63987fe --- /dev/null +++ b/libc/mingw/stdio/ftello.c @@ -0,0 +1,5 @@ +#include + +_off_t ftello(FILE * stream){ + return (_off_t) ftello64(stream); +} diff --git a/libc/mingw/stdio/ftello64.c b/libc/mingw/stdio/ftello64.c new file mode 100644 index 000000000..a0192fbe6 --- /dev/null +++ b/libc/mingw/stdio/ftello64.c @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +_off64_t +ftello64 (FILE * stream) +{ + fpos_t pos; + if (fgetpos(stream, &pos)) + return -1LL; + else + return ((off64_t) pos); +} diff --git a/libc/mingw/stdio/ftruncate64.c b/libc/mingw/stdio/ftruncate64.c new file mode 100644 index 000000000..ec597e206 --- /dev/null +++ b/libc/mingw/stdio/ftruncate64.c @@ -0,0 +1,371 @@ +#ifdef TEST_FTRUNCATE64 +#include +#include +#endif /* TEST_FTRUNCATE64 */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Mutually exclusive methods + We check disk space as truncating more than the allowed space results + in file getting mysteriously deleted + */ +#define _CHECK_SPACE_BY_VOLUME_METHOD_ 1 /* Needs to walk through all volumes */ +#define _CHECK_SPACE_BY_PSAPI_METHOD_ 0 /* Requires psapi.dll */ +#define _CHECK_SPACE_BY_VISTA_METHOD_ 0 /* Won't work on XP */ + +#if (_CHECK_SPACE_BY_PSAPI_METHOD_ == 1) /* Retrive actual volume path */ +static LPWSTR getdirpath(const LPWSTR __str){ + int len, walk = 0; + LPWSTR dirname; + while (__str[walk] != L'\0'){ + walk++; + if (__str[walk] == L'\\') len = walk + 1; + } + dirname = calloc(len + 1, sizeof(wchar_t)); + if (!dirname) return dirname; /* memory error */ + return wcsncpy(dirname,__str,len); +} + +static LPWSTR xp_normalize_fn(const LPWSTR fn) { + DWORD len, err, walker, isfound; + LPWSTR drives = NULL; + LPWSTR target = NULL; + LPWSTR ret = NULL; + wchar_t tmplt[3] = L" :"; /* Template */ + + /*Get list of drive letters */ + len = GetLogicalDriveStringsW(0,NULL); + drives = calloc(len,sizeof(wchar_t)); + if (!drives) return NULL; + len = GetLogicalDriveStringsW(len,drives); + + /*Allocatate memory */ + target = calloc(MAX_PATH + 1,sizeof(wchar_t)); + if (!target) { + free(drives); + return NULL; + } + + walker = 0; + while ((walker < len) && !(drives[walker] == L'\0' && drives[walker + 1] == L'\0')){ + /* search through alphabets */ + if(iswalpha(drives[walker])) { + *tmplt = drives[walker]; /* Put drive letter */ + err = QueryDosDeviceW(tmplt,target,MAX_PATH); + if(!err) { + free(drives); + free(target); + return NULL; + } + if( _wcsnicmp(target,fn,wcslen(target)) == 0) break; + wmemset(target,L'\0',MAX_PATH); + walker++; + } else walker++; + } + + if (!iswalpha(*tmplt)) { + free(drives); + free(target); + return NULL; /* Finish walking without finding correct drive */ + } + + ret = calloc(MAX_PATH + 1,sizeof(wchar_t)); + if (!ret) { + free(drives); + free(target); + return NULL; + } + _snwprintf(ret,MAX_PATH,L"%ws%ws",tmplt,fn+wcslen(target)); + + return ret; +} + +/* XP method of retrieving filename from handles, based on: + http://msdn.microsoft.com/en-us/library/aa366789%28VS.85%29.aspx + */ +static LPWSTR xp_getfilepath(const HANDLE f, const LARGE_INTEGER fsize){ + HANDLE hFileMap = NULL; + void* pMem = NULL; + LPWSTR temp, ret; + DWORD err; + + temp = calloc(MAX_PATH + 1, sizeof(wchar_t)); + if (!temp) goto errormap; + + /* CreateFileMappingW limitation: Cannot map 0 byte files, so extend it to 1 byte */ + if (!fsize.QuadPart) { + SetFilePointer(f, 1, NULL, FILE_BEGIN); + err = SetEndOfFile(f); + if(!temp) goto errormap; + } + + hFileMap = CreateFileMappingW(f,NULL,PAGE_READONLY,0,1,NULL); + if(!hFileMap) goto errormap; + pMem = MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 1); + if(!pMem) goto errormap; + err = GetMappedFileNameW(GetCurrentProcess(),pMem,temp,MAX_PATH); + if(!err) goto errormap; + + if (pMem) UnmapViewOfFile(pMem); + if (hFileMap) CloseHandle(hFileMap); + ret = xp_normalize_fn(temp); + free(temp); + return ret; + + errormap: + if (temp) free(temp); + if (pMem) UnmapViewOfFile(pMem); + if (hFileMap) CloseHandle(hFileMap); + _set_errno(EBADF); + return NULL; +} +#endif /* _CHECK_SPACE_BY_PSAPI_METHOD_ */ + +static int +checkfreespace (const HANDLE f, const ULONGLONG requiredspace) +{ + LPWSTR dirpath, volumeid, volumepath; + ULARGE_INTEGER freespace; + LARGE_INTEGER currentsize; + DWORD check, volumeserial; + BY_HANDLE_FILE_INFORMATION fileinfo; + HANDLE vol; + + /* Get current size */ + check = GetFileSizeEx (f, ¤tsize); + if (!check) + { + _set_errno(EBADF); + return -1; /* Error checking file size */ + } + + /* Short circuit disk space check if shrink operation */ + if ((ULONGLONG)currentsize.QuadPart >= requiredspace) + return 0; + + /* We check available space to user before attempting to truncate */ + +#if (_CHECK_SPACE_BY_VISTA_METHOD_ == 1) + /* Get path length */ + DWORD err; + LPWSTR filepath = NULL; + check = GetFinalPathNameByHandleW(f,filepath,0,FILE_NAME_NORMALIZED|VOLUME_NAME_GUID); + err = GetLastError(); + if (err == ERROR_PATH_NOT_FOUND || err == ERROR_INVALID_PARAMETER) { + _set_errno(EINVAL); + return -1; /* IO error */ + } + filepath = calloc(check + 1,sizeof(wchar_t)); + if (!filepath) { + _set_errno(EBADF); + return -1; /* Out of memory */ + } + check = GetFinalPathNameByHandleW(f,filepath,check,FILE_NAME_NORMALIZED|VOLUME_NAME_GUID); + /* FIXME: last error was set to error 87 (0x57) + "The parameter is incorrect." for some reason but works out */ + if (!check) { + _set_errno(EBADF); + return -1; /* Error resolving filename */ + } +#endif /* _CHECK_SPACE_BY_VISTA_METHOD_ */ + +#if (_CHECK_SPACE_BY_PSAPI_METHOD_ == 1) + LPWSTR filepath = NULL; + filepath = xp_getfilepath(f,currentsize); + + /* Get durectory path */ + dirpath = getdirpath(filepath); + free(filepath); + filepath = NULL; + if (!dirpath) { + _set_errno(EBADF); + return -1; /* Out of memory */ + } +#endif /* _CHECK_SPACE_BY_PSAPI_METHOD_ */ + +#if _CHECK_SPACE_BY_VOLUME_METHOD_ + if(!GetFileInformationByHandle(f,&fileinfo)) { + _set_errno(EINVAL); + return -1; /* Resolution failure */ + } + + volumeid = calloc(51,sizeof(wchar_t)); + volumepath = calloc(MAX_PATH+2,sizeof(wchar_t)); + if(!volumeid || !volumepath) { + _set_errno(EBADF); + return -1; /* Out of memory */ + } + + dirpath = NULL; + + vol = FindFirstVolumeW(volumeid,50); + /* wprintf(L"%d - %ws\n",wcslen(volumeid),volumeid); */ + do { + check = GetVolumeInformationW(volumeid,volumepath,MAX_PATH+1,&volumeserial,NULL,NULL,NULL,0); + /* wprintf(L"GetVolumeInformationW %d id %ws path %ws error %d\n",check,volumeid,volumepath,GetLastError()); */ + if(volumeserial == fileinfo.dwVolumeSerialNumber) { + dirpath = volumeid; + break; + } + } while (FindNextVolumeW(vol,volumeid,50)); + FindVolumeClose(vol); + + if(!dirpath) free(volumeid); /* we found the volume */ + free(volumepath); +#endif /* _CHECK_SPACE_BY_VOLUME_METHOD_ */ + + /* Get available free space */ + check = GetDiskFreeSpaceExW(dirpath,&freespace,NULL,NULL); + //wprintf(L"freespace %I64u\n",freespace); + free(dirpath); + if(!check) { + _set_errno(EFBIG); + return -1; /* Error getting free space */ + } + + /* Check space requirements */ + if ((requiredspace - currentsize.QuadPart) > freespace.QuadPart) + { + _set_errno(EFBIG); /* File too big for disk */ + return -1; + } /* We have enough space to truncate/expand */ + return 0; +} + +int ftruncate64(int __fd, _off64_t __length) { + HANDLE f; + LARGE_INTEGER quad; + DWORD check; + int ret = 0; + __int64 pos; + + /* Sanity check */ + if (__length < 0) { + goto errorout; + } + + /* Get Win32 Handle */ + if(__fd == -1) { + goto errorout; + } + + f = (HANDLE)_get_osfhandle(__fd); + if (f == INVALID_HANDLE_VALUE || (GetFileType(f) != FILE_TYPE_DISK)) { + _set_errno(EBADF); + return -1; + } + + + /* Save position */ + if((pos = _telli64(__fd)) == -1LL){ + goto errorout; + } + + /* Check available space */ + check = checkfreespace(f,__length); + if (check != 0) { + return -1; /* Error, errno already set */ + } + + quad.QuadPart = __length; + check = SetFilePointer(f, (LONG)quad.LowPart, &(quad.HighPart), FILE_BEGIN); + if (check == INVALID_SET_FILE_POINTER && quad.LowPart != INVALID_SET_FILE_POINTER) { + switch (GetLastError()) { + case ERROR_NEGATIVE_SEEK: + _set_errno(EFBIG); /* file too big? */ + return -1; + case INVALID_SET_FILE_POINTER: + _set_errno(EINVAL); /* shouldn't happen */ + return -1; + default: + _set_errno(EINVAL); /* shouldn't happen */ + return -1; + } + } + + check = SetEndOfFile(f); + if (!check) { + goto errorout; + } + + if(_lseeki64(__fd,pos,SEEK_SET) == -1LL){ + goto errorout; + } + + return ret; + + errorout: + _set_errno(EINVAL); + return -1; +} + +#if (TEST_FTRUNCATE64 == 1) +int main(){ + LARGE_INTEGER sz; + ULARGE_INTEGER freespace; + int f; + LPWSTR path, dir; + sz.QuadPart = 0LL; + f = _open("XXX.tmp", _O_BINARY|_O_CREAT|_O_RDWR, _S_IREAD | _S_IWRITE); + wprintf(L"%d\n",ftruncate64(f,12)); + wprintf(L"%d\n",ftruncate64(f,20)); + wprintf(L"%d\n",ftruncate64(f,15)); +/* path = xp_getfilepath((HANDLE)_get_osfhandle(f),sz); + dir = getdirpath(path); + GetDiskFreeSpaceExW(dir,&freespace,NULL,NULL); + wprintf(L"fs - %ws\n",path); + wprintf(L"dirfs - %ws\n",dir); + wprintf(L"free - %I64u\n",freespace.QuadPart); + free(dir); + free(path);*/ + _close(f); + return 0; +} +#endif /* TEST_FTRUNCATE64 */ + +#if (TEST_FTRUNCATE64 == 2) +int main() { +FILE *f; +int fd; +char buf[100]; +int cnt; +unlink("test.out"); +f = fopen("test.out","w+"); +fd = fileno(f); +write(fd,"abc",3); +fflush(f); +printf ("err: %d\n", ftruncate64(fd,10)); +cnt = read(fd,buf,100); +printf("cnt = %d\n",cnt); +return 0; +} +#endif /* TEST_FTRUNCATE64 */ + +#if (TEST_FTRUNCATE64 == 3) +int main() { +FILE *f; +int fd; +char buf[100]; +int cnt; +unlink("test.out"); +f = fopen("test.out","w+"); +fd = fileno(f); +write(fd,"abc",3); +fflush(f); +ftruncate64(fd,0); +write(fd,"def",3); +fclose(f); +f = fopen("test.out","r"); +cnt = fread(buf,1,100,f); +printf("cnt = %d\n",cnt); +return 0; +} +#endif /* TEST_FTRUNCATE64 */ + diff --git a/libc/mingw/stdio/lltoa.c b/libc/mingw/stdio/lltoa.c new file mode 100644 index 000000000..41736390c --- /dev/null +++ b/libc/mingw/stdio/lltoa.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +char* lltoa(long long _n, char * _c, int _i) + { return _i64toa (_n, _c, _i); } diff --git a/libc/mingw/stdio/lltow.c b/libc/mingw/stdio/lltow.c new file mode 100644 index 000000000..0812faf7e --- /dev/null +++ b/libc/mingw/stdio/lltow.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +wchar_t* lltow(long long _n, wchar_t * _w, int _i) + { return _i64tow (_n, _w, _i); } diff --git a/libc/mingw/stdio/lseek64.c b/libc/mingw/stdio/lseek64.c new file mode 100644 index 000000000..afda7cefb --- /dev/null +++ b/libc/mingw/stdio/lseek64.c @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +_off64_t lseek64(int fd,_off64_t offset, int whence) +{ + return _lseeki64(fd, (_off64_t) offset, whence); +} + diff --git a/libc/mingw/stdio/mingw_asprintf.c b/libc/mingw/stdio/mingw_asprintf.c new file mode 100644 index 000000000..e55e235af --- /dev/null +++ b/libc/mingw/stdio/mingw_asprintf.c @@ -0,0 +1,32 @@ +#define _GNU_SOURCE +#define __CRT__NO_INLINE + +#include +#include +#include + +int __mingw_asprintf(char ** __restrict__ ret, + const char * __restrict__ format, + ...) { + va_list ap; + int len; + va_start(ap,format); + /* Get Length */ + len = __mingw_vsnprintf(NULL,0,format,ap); + if (len < 0) goto _end; + /* +1 for \0 terminator. */ + *ret = malloc(len + 1); + /* Check malloc fail*/ + if (!*ret) { + len = -1; + goto _end; + } + /* Write String */ + __mingw_vsnprintf(*ret,len+1,format,ap); + /* Terminate explicitly */ + (*ret)[len] = '\0'; + _end: + va_end(ap); + return len; +} + diff --git a/libc/mingw/stdio/mingw_fprintf.c b/libc/mingw/stdio/mingw_fprintf.c new file mode 100644 index 000000000..438941f7e --- /dev/null +++ b/libc/mingw/stdio/mingw_fprintf.c @@ -0,0 +1,58 @@ +/* fprintf.c + * + * $Id: fprintf.c,v 1.1 2008/08/11 22:41:55 keithmarshall Exp $ + * + * Provides an implementation of the "fprintf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, whence it may replace the Microsoft + * function of the same name. + * + * Written by Keith Marshall + * + * This implementation of "fprintf" will normally be invoked by calling + * "__mingw_fprintf()" in preference to a direct reference to "fprintf()" + * itself; this leaves the MSVCRT implementation as the default, which + * will be deployed when user code invokes "fprint()". Users who then + * wish to use this implementation may either call "__mingw_fprintf()" + * directly, or may use conditional preprocessor defines, to redirect + * references to "fprintf()" to "__mingw_fprintf()". + * + * Compiling this module with "-D INSTALL_AS_DEFAULT" will change this + * recommended convention, such that references to "fprintf()" in user + * code will ALWAYS be redirected to "__mingw_fprintf()"; if this option + * is adopted, then users wishing to use the MSVCRT implementation of + * "fprintf()" will be forced to use a "back-door" mechanism to do so. + * Such a "back-door" mechanism is provided with MinGW, allowing the + * MSVCRT implementation to be called as "__msvcrt_fprintf()"; however, + * since users may not expect this behaviour, a standard libmingwex.a + * installation does not employ this option. + * + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __fprintf (FILE *, const APICHAR *, ...) __MINGW_NOTHROW; + +int __cdecl __fprintf(FILE *stream, const APICHAR *fmt, ...) +{ + register int retval; + va_list argv; va_start( argv, fmt ); + _lock_file( stream ); + retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv ); + _unlock_file( stream ); + va_end( argv ); + return retval; +} diff --git a/libc/mingw/stdio/mingw_fprintfw.c b/libc/mingw/stdio/mingw_fprintfw.c new file mode 100644 index 000000000..e5ea41ee4 --- /dev/null +++ b/libc/mingw/stdio/mingw_fprintfw.c @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 + +#include "mingw_fprintf.c" + diff --git a/libc/mingw/stdio/mingw_fscanf.c b/libc/mingw/stdio/mingw_fscanf.c new file mode 100644 index 000000000..0c5192a5c --- /dev/null +++ b/libc/mingw/stdio/mingw_fscanf.c @@ -0,0 +1,21 @@ +#include +#include +#include + +extern int __mingw_vfscanf (FILE *stream, const char *format, va_list argp); + +int __mingw_fscanf (FILE *stream, const char *format, ...); + +int +__mingw_fscanf (FILE *stream, const char *format, ...) +{ + va_list argp; + int r; + + va_start (argp, format); + r = __mingw_vfscanf (stream, format, argp); + va_end (argp); + + return r; +} + diff --git a/libc/mingw/stdio/mingw_fwscanf.c b/libc/mingw/stdio/mingw_fwscanf.c new file mode 100644 index 000000000..018125ecf --- /dev/null +++ b/libc/mingw/stdio/mingw_fwscanf.c @@ -0,0 +1,21 @@ +#include +#include +#include + +extern int __mingw_vfwscanf (FILE *stream, const wchar_t *format, va_list argp); + +int __mingw_fwscanf (FILE *stream, const wchar_t *format, ...); + +int +__mingw_fwscanf (FILE *stream, const wchar_t *format, ...) +{ + va_list argp; + int r; + + va_start (argp, format); + r = __mingw_vfwscanf (stream, format, argp); + va_end (argp); + + return r; +} + diff --git a/libc/mingw/stdio/mingw_pformat.c b/libc/mingw/stdio/mingw_pformat.c new file mode 100644 index 000000000..7e2493216 --- /dev/null +++ b/libc/mingw/stdio/mingw_pformat.c @@ -0,0 +1,3208 @@ +/* pformat.c + * + * $Id: pformat.c,v 1.9 2011/01/07 22:57:00 keithmarshall Exp $ + * + * Provides a core implementation of the formatting capabilities + * common to the entire `printf()' family of functions; it conforms + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. + * + * Written by Keith Marshall + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + * The elements of this implementation which deal with the formatting + * of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g' + * and `%G' format specifiers, but excluding the hexadecimal floating + * point `%a' and `%A' specifiers), make use of the `__gdtoa' function + * written by David M. Gay, and are modelled on his sample code, which + * has been deployed under its accompanying terms of use:-- + * + ****************************************************************** + * Copyright (C) 1997, 1999, 2001 Lucent Technologies + * All Rights Reserved + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that the above copyright notice appear in all + * copies and that both that the copyright notice and this + * permission notice and warranty disclaimer appear in supporting + * documentation, and that the name of Lucent or any of its entities + * not be used in advertising or publicity pertaining to + * distribution of the software without specific, written prior + * permission. + * + * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. + * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY + * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER + * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, + * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF + * THIS SOFTWARE. + ****************************************************************** + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef __ENABLE_DFP +#ifndef __STDC_WANT_DEC_FP__ +#define __STDC_WANT_DEC_FP__ 1 +#endif + +#include "../math/DFP/dfp_internal.h" +#endif /* __ENABLE_DFP */ + +#include + +/* FIXME: The following belongs in values.h, but current MinGW + * has nothing useful there! OTOH, values.h is not a standard + * header, and its use may be considered obsolete; perhaps it + * is better to just keep these definitions here. + */ + +#include +/* workaround gcc bug */ +#if defined(__GNUC__) && !defined(__clang__) +#define ATTRIB_GCC_STRUCT __attribute__((gcc_struct)) +#else +#define ATTRIB_GCC_STRUCT +#endif +typedef struct ATTRIB_GCC_STRUCT __tI128 { + int64_t digits[2]; +} __tI128; + +typedef struct ATTRIB_GCC_STRUCT __tI128_2 { + uint32_t digits32[4]; +} __tI128_2; + +typedef union ATTRIB_GCC_STRUCT __uI128 { + __tI128 t128; + __tI128_2 t128_2; +} __uI128; +#include + +#ifndef _VALUES_H +/* + * values.h + * + */ +#define _VALUES_H + +#include + +#define _TYPEBITS(type) (sizeof(type) * CHAR_BIT) + +#if defined(__ENABLE_PRINTF128) || defined(__ENABLE_DFP) +#define LLONGBITS _TYPEBITS(__tI128) +#else +#define LLONGBITS _TYPEBITS(long long) +#endif + +#endif /* !defined _VALUES_H -- end of file */ + +#include "mingw_pformat.h" + +/* Bit-map constants, defining the internal format control + * states, which propagate through the flags. + */ +#define PFORMAT_GROUPED 0x00001000 +#define PFORMAT_HASHED 0x00000800 +#define PFORMAT_LJUSTIFY 0x00000400 +#define PFORMAT_ZEROFILL 0x00000200 + +#define PFORMAT_JUSTIFY (PFORMAT_LJUSTIFY | PFORMAT_ZEROFILL) +#define PFORMAT_IGNORE -1 + +#define PFORMAT_SIGNED 0x000001C0 +#define PFORMAT_POSITIVE 0x00000100 +#define PFORMAT_NEGATIVE 0x00000080 +#define PFORMAT_ADDSPACE 0x00000040 + +#define PFORMAT_XCASE 0x00000020 + +#define PFORMAT_LDOUBLE 0x00000004 + +#ifdef __ENABLE_DFP +#define PFORMAT_DECIM32 0x00020000 +#define PFORMAT_DECIM64 0x00040000 +#define PFORMAT_DECIM128 0x00080000 +#endif + +/* `%o' format digit extraction mask, and shift count... + * (These are constant, and do not propagate through the flags). + */ +#define PFORMAT_OMASK 0x00000007 +#define PFORMAT_OSHIFT 0x00000003 + +/* `%x' and `%X' format digit extraction mask, and shift count... + * (These are constant, and do not propagate through the flags). + */ +#define PFORMAT_XMASK 0x0000000F +#define PFORMAT_XSHIFT 0x00000004 + +/* The radix point character, used in floating point formats, is + * localised on the basis of the active LC_NUMERIC locale category. + * It is stored locally, as a `wchar_t' entity, which is converted + * to a (possibly multibyte) character on output. Initialisation + * of the stored `wchar_t' entity, together with a record of its + * effective multibyte character length, is required each time + * `__pformat()' is entered, (static storage would not be thread + * safe), but this initialisation is deferred until it is actually + * needed; on entry, the effective character length is first set to + * the following value, (and the `wchar_t' entity is zeroed), to + * indicate that a call of `localeconv()' is needed, to complete + * the initialisation. + */ +#define PFORMAT_RPINIT -3 + +/* The floating point format handlers return the following value + * for the radix point position index, when the argument value is + * infinite, or not a number. + */ +#define PFORMAT_INFNAN -32768 + +typedef union +{ + /* A data type agnostic representation, + * for printf arguments of any integral data type... + */ + signed long __pformat_long_t; + signed long long __pformat_llong_t; + unsigned long __pformat_ulong_t; + unsigned long long __pformat_ullong_t; + unsigned short __pformat_ushort_t; + unsigned char __pformat_uchar_t; + signed short __pformat_short_t; + signed char __pformat_char_t; + void * __pformat_ptr_t; + __uI128 __pformat_u128_t; +} __pformat_intarg_t; + +typedef enum +{ + /* Format interpreter state indices... + * (used to identify the active phase of format string parsing). + */ + PFORMAT_INIT = 0, + PFORMAT_SET_WIDTH, + PFORMAT_GET_PRECISION, + PFORMAT_SET_PRECISION, + PFORMAT_END +} __pformat_state_t; + +typedef enum +{ + /* Argument length classification indices... + * (used for arguments representing integer data types). + */ + PFORMAT_LENGTH_INT = 0, + PFORMAT_LENGTH_SHORT, + PFORMAT_LENGTH_LONG, + PFORMAT_LENGTH_LLONG, + PFORMAT_LENGTH_LLONG128, + PFORMAT_LENGTH_CHAR +} __pformat_length_t; +/* + * And a macro to map any arbitrary data type to an appropriate + * matching index, selected from those above; the compiler should + * collapse this to a simple assignment. + */ + +#ifdef __GNUC__ +/* provides for some deadcode elimination via compile time eval */ +#define __pformat_arg_length(x) \ +__builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), __tI128), \ + PFORMAT_LENGTH_LLONG128, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), long long), \ + PFORMAT_LENGTH_LLONG, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), long), \ + PFORMAT_LENGTH_LONG, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), short), \ + PFORMAT_LENGTH_SHORT, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), char), \ + PFORMAT_LENGTH_CHAR, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), __uI128), \ + PFORMAT_LENGTH_LLONG128, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), unsigned long), \ + PFORMAT_LENGTH_LONG, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), unsigned long long), \ + PFORMAT_LENGTH_LLONG, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), unsigned short), \ + PFORMAT_LENGTH_SHORT, \ + __builtin_choose_expr ( \ + __builtin_types_compatible_p (typeof (x), unsigned char), \ + PFORMAT_LENGTH_CHAR, \ + PFORMAT_LENGTH_INT)))))))))) + +#else +#define __pformat_arg_length( type ) \ + sizeof( type ) == sizeof( __tI128 ) ? PFORMAT_LENGTH_LLONG128 : \ + sizeof( type ) == sizeof( long long ) ? PFORMAT_LENGTH_LLONG : \ + sizeof( type ) == sizeof( long ) ? PFORMAT_LENGTH_LONG : \ + sizeof( type ) == sizeof( short ) ? PFORMAT_LENGTH_SHORT : \ + sizeof( type ) == sizeof( char ) ? PFORMAT_LENGTH_CHAR : \ + /* should never need this default */ PFORMAT_LENGTH_INT +#endif + +typedef struct +{ + /* Formatting and output control data... + * An instance of this control block is created, (on the stack), + * for each call to `__pformat()', and is passed by reference to + * each of the output handlers, as required. + */ + void * dest; + int flags; + int width; + int precision; + int rplen; + wchar_t rpchr; + int thousands_chr_len; + wchar_t thousands_chr; + int count; + int quota; + int expmin; +} __pformat_t; + +#if defined(__ENABLE_PRINTF128) || defined(__ENABLE_DFP) +/* trim leading, leave at least n characters */ +static char * __bigint_trim_leading_zeroes(char *in, int n){ + char *src = in; + int len = strlen(in); + while( len > n && *++src == '0') len--; + + /* we want to null terminator too */ + memmove(in, src, strlen(src) + 1); + return in; +} + +/* LSB first */ +static +void __bigint_to_string(const uint32_t *digits, const uint32_t digitlen, char *buff, const uint32_t bufflen){ + int64_t digitsize = sizeof(*digits) * 8; + int64_t shiftpos = digitlen * digitsize - 1; + memset(buff, 0, bufflen); + + while(shiftpos >= 0) { + /* increment */ + for(uint32_t i = 0; i < bufflen - 1; i++){ + buff[i] += (buff[i] > 4) ? 3 : 0; + } + + /* shift left */ + for(uint32_t i = 0; i < bufflen - 1; i++) + buff[i] <<= 1; + + /* shift in */ + buff[bufflen - 2] |= digits[shiftpos / digitsize] & (0x1 << (shiftpos % digitsize)) ? 1 : 0; + + /* overflow check */ + for(uint32_t i = bufflen - 1; i > 0; i--){ + buff[i - 1] |= (buff[i] > 0xf); + buff[i] &= 0x0f; + } + shiftpos--; + } + + for(uint32_t i = 0; i < bufflen - 1; i++){ + buff[i] += '0'; + } + buff[bufflen - 1] = '\0'; +} + +#if defined(__ENABLE_PRINTF128) +/* LSB first, hex version */ +static +void __bigint_to_stringx(const uint32_t *digits, const uint32_t digitlen, char *buff, const uint32_t bufflen, int upper){ + int32_t stride = sizeof(*digits) * 2; + uint32_t lastpos = 0; + + for(uint32_t i = 0; i < digitlen * stride; i++){ + int32_t buffpos = bufflen - i - 2; + buff[buffpos] = (digits[ i / stride ] & (0xf << 4 * (i % stride))) >> ( 4 * (i % stride)); + buff[buffpos] += (buff[buffpos] > 9) ? ((upper) ? 0x7 : 0x27) : 0; + buff[buffpos] += '0'; + lastpos = buffpos; + if(buffpos == 0) break; /* sanity check */ + } + memset(buff, '0', lastpos); + buff[bufflen - 1] = '\0'; +} + +/* LSB first, octet version */ +static +void __bigint_to_stringo(const uint32_t *digits, const uint32_t digitlen, char *buff, const uint32_t bufflen){ + const uint32_t digitsize = sizeof(*digits) * 8; + const uint64_t bits = digitsize * digitlen; + uint32_t pos = bufflen - 2; + uint32_t reg = 0; + for(uint32_t i = 0; i <= bits; i++){ + reg |= (digits[ i / digitsize] & (0x1 << (i % digitsize))) ? 1 << (i % 3) : 0; + if( (i && ( i + 1) % 3 == 0) || (i + 1) == bits){ /* make sure all is committed after last bit */ + buff[pos] = '0' + reg; + reg = 0; + if(!pos) break; /* sanity check */ + pos--; + } + } + if(pos < bufflen - 1) + memset(buff,'0', pos + 1); + buff[bufflen - 1] = '\0'; +} +#endif /* defined(__ENABLE_PRINTF128) */ +#endif /* defined(__ENABLE_PRINTF128) || defined(__ENABLE_DFP) */ + +static +void __pformat_putc( int c, __pformat_t *stream ) +{ + /* Place a single character into the `__pformat()' output queue, + * provided any specified output quota has not been exceeded. + */ + if( (stream->flags & PFORMAT_NOLIMIT) || (stream->quota > stream->count) ) + { + /* Either there was no quota specified, + * or the active quota has not yet been reached. + */ + if( stream->flags & PFORMAT_TO_FILE ) + /* + * This is single character output to a FILE stream... + */ + __fputc(c, (FILE *)(stream->dest)); + + else + /* Whereas, this is to an internal memory buffer... + */ + ((APICHAR *)(stream->dest))[stream->count] = c; + } + ++stream->count; +} + +static +void __pformat_putchars( const char *s, int count, __pformat_t *stream ) +{ +#ifndef __BUILD_WIDEAPI + /* Handler for `%c' and (indirectly) `%s' conversion specifications. + * + * Transfer characters from the string buffer at `s', character by + * character, up to the number of characters specified by `count', or + * if `precision' has been explicitly set to a value less than `count', + * stopping after the number of characters specified for `precision', + * to the `__pformat()' output stream. + * + * Characters to be emitted are passed through `__pformat_putc()', to + * ensure that any specified output quota is honoured. + */ + if( (stream->precision >= 0) && (count > stream->precision) ) + /* + * Ensure that the maximum number of characters transferred doesn't + * exceed any explicitly set `precision' specification. + */ + count = stream->precision; + + /* Establish the width of any field padding required... + */ + if( stream->width > count ) + /* + * as the number of spaces equivalent to the number of characters + * by which those to be emitted is fewer than the field width... + */ + stream->width -= count; + + else + /* ignoring any width specification which is insufficient. + */ + stream->width = PFORMAT_IGNORE; + + if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) + /* + * When not doing flush left justification, (i.e. the `-' flag + * is not set), any residual unreserved field width must appear + * as blank padding, to the left of the output string. + */ + while( stream->width-- ) + __pformat_putc( '\x20', stream ); + + /* Emit the data... + */ + while( count-- ) + /* + * copying the requisite number of characters from the input. + */ + __pformat_putc( *s++, stream ); + + /* If we still haven't consumed the entire specified field width, + * we must be doing flush left justification; any residual width + * must be filled with blanks, to the right of the output value. + */ + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + +#else /* __BUILD_WIDEAPI */ + + int len; + + if( (stream->precision >= 0) && (count > stream->precision) ) + count = stream->precision; + + if( (stream->flags & PFORMAT_TO_FILE) && (stream->flags & PFORMAT_NOLIMIT) ) + { + int __cdecl __ms_fwprintf(FILE *, const wchar_t *, ...); + + if( stream->width > count ) + { + if( (stream->flags & PFORMAT_LJUSTIFY) == 0 ) + len = __ms_fwprintf( (FILE *)(stream->dest), L"%*.*S", stream->width, count, s ); + else + len = __ms_fwprintf( (FILE *)(stream->dest), L"%-*.*S", stream->width, count, s ); + } + else + { + len = __ms_fwprintf( (FILE *)(stream->dest), L"%.*S", count, s ); + } + if( len > 0 ) + stream->count += len; + stream->width = PFORMAT_IGNORE; + return; + } + + if( stream->width > count ) + stream->width -= count; + else + stream->width = PFORMAT_IGNORE; + + if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) + while( stream->width-- ) + __pformat_putc( '\x20', stream ); + + { + /* mbrtowc */ + size_t l; + wchar_t w[12], *p; + while( count > 0 ) + { + mbstate_t ps; + memset(&ps, 0, sizeof(ps) ); + --count; + p = &w[0]; + l = mbrtowc (p, s, strlen (s), &ps); + if (!l) + break; + if ((ssize_t)l < 0) + { + l = 1; + w[0] = (wchar_t) *s; + } + s += l; + __pformat_putc((int)w[0], stream); + } + } + + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + +#endif /* __BUILD_WIDEAPI */ +} + +static +void __pformat_puts( const char *s, __pformat_t *stream ) +{ + /* Handler for `%s' conversion specifications. + * + * Transfer a NUL terminated character string, character by character, + * stopping when the end of the string is encountered, or if `precision' + * has been explicitly set, when the specified number of characters has + * been emitted, if that is less than the length of the input string, + * to the `__pformat()' output stream. + * + * This is implemented as a trivial call to `__pformat_putchars()', + * passing the length of the input string as the character count, + * (after first verifying that the input pointer is not NULL). + */ + if( s == NULL ) s = "(null)"; + + if( stream->precision >= 0 ) + __pformat_putchars( s, strnlen( s, stream->precision ), stream ); + else + __pformat_putchars( s, strlen( s ), stream ); +} + +static +void __pformat_wputchars( const wchar_t *s, int count, __pformat_t *stream ) +{ +#ifndef __BUILD_WIDEAPI + /* Handler for `%C'(`%lc') and `%S'(`%ls') conversion specifications; + * (this is a wide character variant of `__pformat_putchars()'). + * + * Each multibyte character sequence to be emitted is passed, byte + * by byte, through `__pformat_putc()', to ensure that any specified + * output quota is honoured. + */ + char buf[16]; + mbstate_t state; + int len = wcrtomb(buf, L'\0', &state); + + if( (stream->precision >= 0) && (count > stream->precision) ) + /* + * Ensure that the maximum number of characters transferred doesn't + * exceed any explicitly set `precision' specification. + */ + count = stream->precision; + + /* Establish the width of any field padding required... + */ + if( stream->width > count ) + /* + * as the number of spaces equivalent to the number of characters + * by which those to be emitted is fewer than the field width... + */ + stream->width -= count; + + else + /* ignoring any width specification which is insufficient. + */ + stream->width = PFORMAT_IGNORE; + + if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) + /* + * When not doing flush left justification, (i.e. the `-' flag + * is not set), any residual unreserved field width must appear + * as blank padding, to the left of the output string. + */ + while( stream->width-- ) + __pformat_putc( '\x20', stream ); + + /* Emit the data, converting each character from the wide + * to the multibyte domain as we go... + */ + while( (count-- > 0) && ((len = wcrtomb( buf, *s++, &state )) > 0) ) + { + char *p = buf; + while( len-- > 0 ) + __pformat_putc( *p++, stream ); + } + + /* If we still haven't consumed the entire specified field width, + * we must be doing flush left justification; any residual width + * must be filled with blanks, to the right of the output value. + */ + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + +#else /* __BUILD_WIDEAPI */ + + int len; + + if( (stream->precision >= 0) && (count > stream->precision) ) + count = stream->precision; + + if( (stream->flags & PFORMAT_TO_FILE) && (stream->flags & PFORMAT_NOLIMIT) ) + { + int __cdecl __ms_fwprintf(FILE *, const wchar_t *, ...); + + if( stream->width > count ) + { + if( (stream->flags & PFORMAT_LJUSTIFY) == 0 ) + len = __ms_fwprintf( (FILE *)(stream->dest), L"%*.*s", stream->width, count, s ); + else + len = __ms_fwprintf( (FILE *)(stream->dest), L"%-*.*s", stream->width, count, s ); + } + else + { + len = __ms_fwprintf( (FILE *)(stream->dest), L"%.*s", count, s ); + } + if( len > 0 ) + stream->count += len; + stream->width = PFORMAT_IGNORE; + return; + } + + if( stream->width > count ) + stream->width -= count; + else + stream->width = PFORMAT_IGNORE; + + if( (stream->width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) + while( stream->width-- ) + __pformat_putc( '\x20', stream ); + + len = count; + while(len-- > 0 && *s != 0) + { + __pformat_putc(*s++, stream); + } + + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + +#endif /* __BUILD_WIDEAPI */ +} + +static +void __pformat_wcputs( const wchar_t *s, __pformat_t *stream ) +{ + /* Handler for `%S' (`%ls') conversion specifications. + * + * Transfer a NUL terminated wide character string, character by + * character, converting to its equivalent multibyte representation + * on output, and stopping when the end of the string is encountered, + * or if `precision' has been explicitly set, when the specified number + * of characters has been emitted, if that is less than the length of + * the input string, to the `__pformat()' output stream. + * + * This is implemented as a trivial call to `__pformat_wputchars()', + * passing the length of the input string as the character count, + * (after first verifying that the input pointer is not NULL). + */ + if( s == NULL ) s = L"(null)"; + + if( stream->precision >= 0 ) + __pformat_wputchars( s, wcsnlen( s, stream->precision ), stream ); + else + __pformat_wputchars( s, wcslen( s ), stream ); +} + +static +int __pformat_int_bufsiz( int bias, int size, __pformat_t *stream ) +{ + /* Helper to establish the size of the internal buffer, which + * is required to queue the ASCII decomposition of an integral + * data value, prior to transfer to the output stream. + */ + size = ((size - 1 + LLONGBITS) / size) + bias; + size += (stream->precision > 0) ? stream->precision : 0; + if ((stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0) + size += (size / 3); + return (size > stream->width) ? size : stream->width; +} + +static +void __pformat_int( __pformat_intarg_t value, __pformat_t *stream ) +{ + /* Handler for `%d', `%i' and `%u' conversion specifications. + * + * Transfer the ASCII representation of an integer value parameter, + * formatted as a decimal number, to the `__pformat()' output queue; + * output will be truncated, if any specified quota is exceeded. + */ + int32_t bufflen = __pformat_int_bufsiz(1, PFORMAT_OSHIFT, stream); +#ifdef __ENABLE_PRINTF128 + char *tmp_buff = NULL; +#endif + char *buf = NULL; + char *p; + int precision; + + buf = alloca(bufflen); + p = buf; + if( stream->flags & PFORMAT_NEGATIVE ) +#ifdef __ENABLE_PRINTF128 + { + /* The input value might be negative, (i.e. it is a signed value)... + */ + if( value.__pformat_u128_t.t128.digits[1] < 0) { + /* + * It IS negative, but we want to encode it as unsigned, + * displayed with a leading minus sign, so convert it... + */ + /* two's complement */ + value.__pformat_u128_t.t128.digits[0] = ~value.__pformat_u128_t.t128.digits[0]; + value.__pformat_u128_t.t128.digits[1] = ~value.__pformat_u128_t.t128.digits[1]; + value.__pformat_u128_t.t128.digits[0] += 1; + value.__pformat_u128_t.t128.digits[1] += (!value.__pformat_u128_t.t128.digits[0]) ? 1 : 0; + } else + /* It is unequivocally a POSITIVE value, so turn off the + * request to prefix it with a minus sign... + */ + stream->flags &= ~PFORMAT_NEGATIVE; + } + + tmp_buff = alloca(bufflen); + /* Encode the input value for display... + */ + __bigint_to_string(value.__pformat_u128_t.t128_2.digits32, + 4, tmp_buff, bufflen); + __bigint_trim_leading_zeroes(tmp_buff,1); + + memset(p,0,bufflen); + for(int32_t i = strlen(tmp_buff) - 1; i >= 0; i--){ + if ( i && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0 + && (i % 4) == 3) + { + *p++ = ','; + } + *p++ = tmp_buff[i]; + if( i > bufflen - 1) break; /* sanity chec */ + if( tmp_buff[i] == '\0' ) break; /* end */ + } +#else + { + /* The input value might be negative, (i.e. it is a signed value)... + */ + if( value.__pformat_llong_t < 0LL ) + /* + * It IS negative, but we want to encode it as unsigned, + * displayed with a leading minus sign, so convert it... + */ + value.__pformat_llong_t = -value.__pformat_llong_t; + + else + /* It is unequivocally a POSITIVE value, so turn off the + * request to prefix it with a minus sign... + */ + stream->flags &= ~PFORMAT_NEGATIVE; + } +while( value.__pformat_ullong_t ) + { + /* decomposing it into its constituent decimal digits, + * in order from least significant to most significant, using + * the local buffer as a LIFO queue in which to store them. + */ + if (p != buf && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0 + && ((p - buf) % 4) == 3) + { + *p++ = ','; + } + *p++ = '0' + (unsigned char)(value.__pformat_ullong_t % 10LL); + value.__pformat_ullong_t /= 10LL; + } +#endif + + if( (stream->precision > 0) + && ((precision = stream->precision - (p - buf)) > 0) ) + /* + * We have not yet queued sufficient digits to fill the field width + * specified for minimum `precision'; pad with zeros to achieve this. + */ + while( precision-- > 0 ) + *p++ = '0'; + + if( (p == buf) && (stream->precision != 0) ) + /* + * Input value was zero; make sure we print at least one digit, + * unless the precision is also explicitly zero. + */ + *p++ = '0'; + + if( (stream->width > 0) && ((stream->width -= p - buf) > 0) ) + { + /* We have now queued sufficient characters to display the input value, + * at the desired precision, but this will not fill the output field... + */ + if( stream->flags & PFORMAT_SIGNED ) + /* + * We will fill one additional space with a sign... + */ + stream->width--; + + if( (stream->precision < 0) + && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) ) + /* + * and the `0' flag is in effect, so we pad the remaining spaces, + * to the left of the displayed value, with zeros. + */ + while( stream->width-- > 0 ) + *p++ = '0'; + + else if( (stream->flags & PFORMAT_LJUSTIFY) == 0 ) + /* + * the `0' flag is not in effect, and neither is the `-' flag, + * so we pad to the left of the displayed value with spaces, so that + * the value appears right justified within the output field. + */ + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + } + + if( stream->flags & PFORMAT_NEGATIVE ) + /* + * A negative value needs a sign... + */ + *p++ = '-'; + + else if( stream->flags & PFORMAT_POSITIVE ) + /* + * A positive value may have an optionally displayed sign... + */ + *p++ = '+'; + + else if( stream->flags & PFORMAT_ADDSPACE ) + /* + * Space was reserved for displaying a sign, but none was emitted... + */ + *p++ = '\x20'; + + while( p > buf ) + /* + * Emit the accumulated constituent digits, + * in order from most significant to least significant... + */ + __pformat_putc( *--p, stream ); + + while( stream->width-- > 0 ) + /* + * The specified output field has not yet been completely filled; + * the `-' flag must be in effect, resulting in a displayed value which + * appears left justified within the output field; we must pad the field + * to the right of the displayed value, by emitting additional spaces, + * until we reach the rightmost field boundary. + */ + __pformat_putc( '\x20', stream ); +} + +static +void __pformat_xint( int fmt, __pformat_intarg_t value, __pformat_t *stream ) +{ + /* Handler for `%o', `%p', `%x' and `%X' conversions. + * + * These can be implemented using a simple `mask and shift' strategy; + * set up the mask and shift values appropriate to the conversion format, + * and allocate a suitably sized local buffer, in which to queue encoded + * digits of the formatted value, in preparation for output. + */ + int width; + int shift = (fmt == 'o') ? PFORMAT_OSHIFT : PFORMAT_XSHIFT; + int bufflen = __pformat_int_bufsiz(2, shift, stream); + char *buf = NULL; +#ifdef __ENABLE_PRINTF128 + char *tmp_buf = NULL; +#endif + char *p; + buf = alloca(bufflen); + p = buf; +#ifdef __ENABLE_PRINTF128 + tmp_buf = alloca(bufflen); + if(fmt == 'o'){ + __bigint_to_stringo(value.__pformat_u128_t.t128_2.digits32,4,tmp_buf,bufflen); + } else { + __bigint_to_stringx(value.__pformat_u128_t.t128_2.digits32,4,tmp_buf,bufflen, !(fmt & PFORMAT_XCASE)); + } + __bigint_trim_leading_zeroes(tmp_buf,0); + + memset(buf,0,bufflen); + for(int32_t i = strlen(tmp_buf); i >= 0; i--) + *p++ = tmp_buf[i]; +#else + int mask = (fmt == 'o') ? PFORMAT_OMASK : PFORMAT_XMASK; + while( value.__pformat_ullong_t ) + { + /* Encode the specified non-zero input value as a sequence of digits, + * in the appropriate `base' encoding and in reverse digit order, each + * encoded in its printable ASCII form, with no leading zeros, using + * the local buffer as a LIFO queue in which to store them. + */ + char *q; + if( (*(q = p++) = '0' + (value.__pformat_ullong_t & mask)) > '9' ) + *q = (*q + 'A' - '9' - 1) | (fmt & PFORMAT_XCASE); + value.__pformat_ullong_t >>= shift; + } +#endif + + if( p == buf ) + /* + * Nothing was queued; input value must be zero, which should never be + * emitted in the `alternative' PFORMAT_HASHED style. + */ + stream->flags &= ~PFORMAT_HASHED; + + if( ((width = stream->precision) > 0) && ((width -= p - buf) > 0) ) + /* + * We have not yet queued sufficient digits to fill the field width + * specified for minimum `precision'; pad with zeros to achieve this. + */ + while( width-- > 0 ) + *p++ = '0'; + + else if( (fmt == 'o') && (stream->flags & PFORMAT_HASHED) ) + /* + * The field width specified for minimum `precision' has already + * been filled, but the `alternative' PFORMAT_HASHED style for octal + * output requires at least one initial zero; that will not have + * been queued, so add it now. + */ + *p++ = '0'; + + if( (p == buf) && (stream->precision != 0) ) + /* + * Still nothing queued for output, but the `precision' has not been + * explicitly specified as zero, (which is necessary if no output for + * an input value of zero is desired); queue exactly one zero digit. + */ + *p++ = '0'; + + if( stream->width > (width = p - buf) ) + /* + * Specified field width exceeds the minimum required... + * Adjust so that we retain only the additional padding width. + */ + stream->width -= width; + + else + /* Ignore any width specification which is insufficient. + */ + stream->width = PFORMAT_IGNORE; + + if( ((width = stream->width) > 0) + && (fmt != 'o') && (stream->flags & PFORMAT_HASHED) ) + /* + * For `%#x' or `%#X' formats, (which have the `#' flag set), + * further reduce the padding width to accommodate the radix + * indicating prefix. + */ + width -= 2; + + if( (width > 0) && (stream->precision < 0) + && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) ) + /* + * When the `0' flag is set, and not overridden by the `-' flag, + * or by a specified precision, add sufficient leading zeros to + * consume the remaining field width. + */ + while( width-- > 0 ) + *p++ = '0'; + + if( (fmt != 'o') && (stream->flags & PFORMAT_HASHED) ) + { + /* For formats other than octal, the PFORMAT_HASHED output style + * requires the addition of a two character radix indicator, as a + * prefix to the actual encoded numeric value. + */ + *p++ = fmt; + *p++ = '0'; + } + + if( (width > 0) && ((stream->flags & PFORMAT_LJUSTIFY) == 0) ) + /* + * When not doing flush left justification, (i.e. the `-' flag + * is not set), any residual unreserved field width must appear + * as blank padding, to the left of the output value. + */ + while( width-- > 0 ) + __pformat_putc( '\x20', stream ); + + while( p > buf ) + /* + * Move the queued output from the local buffer to the ultimate + * destination, in LIFO order. + */ + __pformat_putc( *--p, stream ); + + /* If we still haven't consumed the entire specified field width, + * we must be doing flush left justification; any residual width + * must be filled with blanks, to the right of the output value. + */ + while( width-- > 0 ) + __pformat_putc( '\x20', stream ); +} + +typedef union +{ + /* A multifaceted representation of an IEEE extended precision, + * (80-bit), floating point number, facilitating access to its + * component parts. + */ + double __pformat_fpreg_double_t; + long double __pformat_fpreg_ldouble_t; + struct + { unsigned long long __pformat_fpreg_mantissa; + signed short __pformat_fpreg_exponent; + }; + unsigned short __pformat_fpreg_bitmap[5]; + unsigned long __pformat_fpreg_bits; +} __pformat_fpreg_t; + +#ifdef _WIN32 +/* TODO: make this unconditional in final release... + * (see note at head of associated `#else' block. + */ +#include "../gdtoa/gdtoa.h" + +static +char *__pformat_cvt( int mode, __pformat_fpreg_t x, int nd, int *dp, int *sign ) +{ + /* Helper function, derived from David M. Gay's `g_xfmt()', calling + * his `__gdtoa()' function in a manner to provide extended precision + * replacements for `ecvt()' and `fcvt()'. + */ + int k; unsigned int e = 0; char *ep; + static FPI fpi = { 64, 1-16383-64+1, 32766-16383-64+1, FPI_Round_near, 0, 14 /* Int_max */ }; + + if( sizeof( double ) == sizeof( long double ) ) + { + /* The caller has written into x.__pformat_fpreg_ldouble_t, which + * actually isn't laid out in the way the rest of the union expects it. + */ + int exp = (x.__pformat_fpreg_mantissa >> 52) & 0x7ff; + unsigned long long mant = x.__pformat_fpreg_mantissa & 0x000fffffffffffffULL; + int integer = exp ? 1 : 0; + int signbit = x.__pformat_fpreg_mantissa >> 63; + + k = __fpclassify( x.__pformat_fpreg_double_t ); + + if (exp == 0x7ff) + exp = 0x7fff; + else if (exp != 0) + exp = exp - 1023 + 16383; + x.__pformat_fpreg_mantissa = (mant << 11) | ((unsigned long long)integer << 63); + x.__pformat_fpreg_exponent = exp | (signbit << 15); + } + else + k = __fpclassifyl( x.__pformat_fpreg_ldouble_t ); + + + /* Classify the argument into an appropriate `__gdtoa()' category... + */ + if( k & FP_NAN ) + /* + * identifying infinities or not-a-number... + */ + k = (k & FP_NORMAL) ? STRTOG_Infinite : STRTOG_NaN; + + else if( k & FP_NORMAL ) + { + /* normal and near-zero `denormals'... + */ + if( k & FP_ZERO ) + { + /* with appropriate exponent adjustment for a `denormal'... + */ + k = STRTOG_Denormal; + e = 1 - 0x3FFF - 63; + } + else + { + /* or with `normal' exponent adjustment... + */ + k = STRTOG_Normal; + e = (x.__pformat_fpreg_exponent & 0x7FFF) - 0x3FFF - 63; + } + } + + else + /* or, if none of the above, it's a zero, (positive or negative). + */ + k = STRTOG_Zero; + + /* Check for negative values, always treating NaN as unsigned... + * (return value is zero for positive/unsigned; non-zero for negative). + */ + *sign = (k == STRTOG_NaN) ? 0 : x.__pformat_fpreg_exponent & 0x8000; + + /* Finally, get the raw digit string, and radix point position index. + */ + return __gdtoa( &fpi, e, &x.__pformat_fpreg_bits, &k, mode, nd, dp, &ep ); +} + +static +char *__pformat_ecvt( long double x, int precision, int *dp, int *sign ) +{ + /* A convenience wrapper for the above... + * it emulates `ecvt()', but takes a `long double' argument. + */ + __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x; + return __pformat_cvt( 2, z, precision, dp, sign ); +} + +static +char *__pformat_fcvt( long double x, int precision, int *dp, int *sign ) +{ + /* A convenience wrapper for the above... + * it emulates `fcvt()', but takes a `long double' argument. + */ + __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x; + return __pformat_cvt( 3, z, precision, dp, sign ); +} + +/* The following are required, to clean up the `__gdtoa()' memory pool, + * after processing the data returned by the above. + */ +#define __pformat_ecvt_release( value ) __freedtoa( value ) +#define __pformat_fcvt_release( value ) __freedtoa( value ) + +#else +/* + * TODO: remove this before final release; it is included here as a + * convenience for testing, without requiring a working `__gdtoa()'. + */ +static +char *__pformat_ecvt( long double x, int precision, int *dp, int *sign ) +{ + /* Define in terms of `ecvt()'... + */ + char *retval = ecvt( (double)(x), precision, dp, sign ); + if( isinf( x ) || isnan( x ) ) + { + /* emulating `__gdtoa()' reporting for infinities and NaN. + */ + *dp = PFORMAT_INFNAN; + if( *retval == '-' ) + { + /* Need to force the `sign' flag, (particularly for NaN). + */ + ++retval; *sign = 1; + } + } + return retval; +} + +static +char *__pformat_fcvt( long double x, int precision, int *dp, int *sign ) +{ + /* Define in terms of `fcvt()'... + */ + char *retval = fcvt( (double)(x), precision, dp, sign ); + if( isinf( x ) || isnan( x ) ) + { + /* emulating `__gdtoa()' reporting for infinities and NaN. + */ + *dp = PFORMAT_INFNAN; + if( *retval == '-' ) + { + /* Need to force the `sign' flag, (particularly for NaN). + */ + ++retval; *sign = 1; + } + } + return retval; +} + +/* No memory pool clean up needed, for these emulated cases... + */ +#define __pformat_ecvt_release( value ) /* nothing to be done */ +#define __pformat_fcvt_release( value ) /* nothing to be done */ + +/* TODO: end of conditional to be removed. */ +#endif + +static +void __pformat_emit_radix_point( __pformat_t *stream ) +{ + /* Helper to place a localised representation of the radix point + * character at the ultimate destination, when formatting fixed or + * floating point numbers. + */ + if( stream->rplen == PFORMAT_RPINIT ) + { + /* Radix point initialisation not yet completed; + * establish a multibyte to `wchar_t' converter... + */ + int len; wchar_t rpchr; mbstate_t state; + + /* Initialise the conversion state... + */ + memset( &state, 0, sizeof( state ) ); + + /* Fetch and convert the localised radix point representation... + */ + if( (len = mbrtowc( &rpchr, localeconv()->decimal_point, 16, &state )) > 0 ) + /* + * and store it, if valid. + */ + stream->rpchr = rpchr; + + /* In any case, store the reported effective multibyte length, + * (or the error flag), marking initialisation as `done'. + */ + stream->rplen = len; + } + + if( stream->rpchr != (wchar_t)(0) ) + { + /* We have a localised radix point mark; + * establish a converter to make it a multibyte character... + */ +#ifdef __BUILD_WIDEAPI + __pformat_putc (stream->rpchr, stream); +#else + int len; char buf[len = stream->rplen]; mbstate_t state; + + /* Initialise the conversion state... + */ + memset( &state, 0, sizeof( state ) ); + + /* Convert the `wchar_t' representation to multibyte... + */ + if( (len = wcrtomb( buf, stream->rpchr, &state )) > 0 ) + { + /* and copy to the output destination, when valid... + */ + char *p = buf; + while( len-- > 0 ) + __pformat_putc( *p++, stream ); + } + + else + /* otherwise fall back to plain ASCII '.'... + */ + __pformat_putc( '.', stream ); +#endif + } + else + /* No localisation: just use ASCII '.'... + */ + __pformat_putc( '.', stream ); +} + +static +void __pformat_emit_numeric_value( int c, __pformat_t *stream ) +{ + /* Convenience helper to transfer numeric data from an internal + * formatting buffer to the ultimate destination... + */ + if( c == '.' ) + /* + * converting this internal representation of the the radix + * point to the appropriately localised representation... + */ + __pformat_emit_radix_point( stream ); + else if (c == ',') + { + wchar_t wcs; + if ((wcs = stream->thousands_chr) != 0) + __pformat_wputchars (&wcs, 1, stream); + } + else + /* and passing all other characters through, unmodified. + */ + __pformat_putc( c, stream ); +} + +static +void __pformat_emit_inf_or_nan( int sign, char *value, __pformat_t *stream ) +{ + /* Helper to emit INF or NAN where a floating point value + * resolves to one of these special states. + */ + int i; + char buf[4]; + char *p = buf; + + /* We use the string formatting helper to display INF/NAN, + * but we don't want truncation if the precision set for the + * original floating point output request was insufficient; + * ignore it! + */ + stream->precision = PFORMAT_IGNORE; + + if( sign ) + /* + * Negative infinity: emit the sign... + */ + *p++ = '-'; + + else if( stream->flags & PFORMAT_POSITIVE ) + /* + * Not negative infinity, but '+' flag is in effect; + * thus, we emit a positive sign... + */ + *p++ = '+'; + + else if( stream->flags & PFORMAT_ADDSPACE ) + /* + * No sign required, but space was reserved for it... + */ + *p++ = '\x20'; + + /* Copy the appropriate status indicator, up to a maximum of + * three characters, transforming to the case corresponding to + * the format specification... + */ + for( i = 3; i > 0; --i ) + *p++ = (*value++ & ~PFORMAT_XCASE) | (stream->flags & PFORMAT_XCASE); + + /* and emit the result. + */ + __pformat_putchars( buf, p - buf, stream ); +} + +static +void __pformat_emit_float( int sign, char *value, int len, __pformat_t *stream ) +{ + /* Helper to emit a fixed point representation of numeric data, + * as encoded by a prior call to `ecvt()' or `fcvt()'; (this does + * NOT include the exponent, for floating point format). + */ + if( len > 0 ) + { + /* The magnitude of `x' is greater than or equal to 1.0... + * reserve space in the output field, for the required number of + * decimal digits to be placed before the decimal point... + */ + if( stream->width >= len) + /* + * adjusting as appropriate, when width is sufficient... + */ + stream->width -= len; + + else + /* or simply ignoring the width specification, if not. + */ + stream->width = PFORMAT_IGNORE; + } + + else if( stream->width > 0 ) + /* + * The magnitude of `x' is less than 1.0... + * reserve space for exactly one zero before the decimal point. + */ + stream->width--; + + /* Reserve additional space for the digits which will follow the + * decimal point... + */ + if( (stream->width >= 0) && (stream->width > stream->precision) ) + /* + * adjusting appropriately, when sufficient width remains... + * (note that we must check both of these conditions, because + * precision may be more negative than width, as a result of + * adjustment to provide extra padding when trailing zeros + * are to be discarded from "%g" format conversion with a + * specified field width, but if width itself is negative, + * then there is explicitly to be no padding anyway). + */ + stream->width -= stream->precision; + + else + /* or again, ignoring the width specification, if not. + */ + stream->width = PFORMAT_IGNORE; + + /* Reserve space in the output field, for display of the decimal point, + * unless the precision is explicity zero, with the `#' flag not set. + */ + if ((stream->width > 0) + && ((stream->precision > 0) || (stream->flags & PFORMAT_HASHED))) + stream->width--; + + if (len > 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0) + { + int cths = ((len + 2) / 3) - 1; + while (cths > 0 && stream->width > 0) + { + --cths; stream->width--; + } + } + + /* Reserve space in the output field, for display of the sign of the + * formatted value, if required; (i.e. if the value is negative, or if + * either the `space' or `+' formatting flags are set). + */ + if( (stream->width > 0) && (sign || (stream->flags & PFORMAT_SIGNED)) ) + stream->width--; + + /* Emit any padding space, as required to correctly right justify + * the output within the alloted field width. + */ + if( (stream->width > 0) && ((stream->flags & PFORMAT_JUSTIFY) == 0) ) + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + + /* Emit the sign indicator, as appropriate... + */ + if( sign ) + /* + * mandatory, for negative values... + */ + __pformat_putc( '-', stream ); + + else if( stream->flags & PFORMAT_POSITIVE ) + /* + * optional, for positive values... + */ + __pformat_putc( '+', stream ); + + else if( stream->flags & PFORMAT_ADDSPACE ) + /* + * or just fill reserved space, when the space flag is in effect. + */ + __pformat_putc( '\x20', stream ); + + /* If the `0' flag is in effect, and not overridden by the `-' flag, + * then zero padding, to fill out the field, goes here... + */ + if( (stream->width > 0) + && ((stream->flags & PFORMAT_JUSTIFY) == PFORMAT_ZEROFILL) ) + while( stream->width-- > 0 ) + __pformat_putc( '0', stream ); + + /* Emit the digits of the encoded numeric value... + */ + if( len > 0 ) + { + /* + * ...beginning with those which precede the radix point, + * and appending any necessary significant trailing zeros. + */ + do { + __pformat_putc( *value ? *value++ : '0', stream); + --len; + if (len != 0 && (stream->flags & PFORMAT_GROUPED) != 0 && stream->thousands_chr != 0 + && (len % 3) == 0) + __pformat_wputchars (&stream->thousands_chr, 1, stream); + } + while (len > 0); + } + else + /* The magnitude of the encoded value is less than 1.0, so no + * digits precede the radix point; we emit a mandatory initial + * zero, followed immediately by the radix point. + */ + __pformat_putc( '0', stream ); + + /* Unless the encoded value is integral, AND the radix point + * is not expressly demanded by the `#' flag, we must insert + * the appropriately localised radix point mark here... + */ + if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) ) + __pformat_emit_radix_point( stream ); + + /* When the radix point offset, `len', is negative, this implies + * that additional zeros must appear, following the radix point, + * and preceding the first significant digit... + */ + if( len < 0 ) + { + /* To accommodate these, we adjust the precision, (reducing it + * by adding a negative value), and then we emit as many zeros + * as are required. + */ + stream->precision += len; + do __pformat_putc( '0', stream ); + while( ++len < 0 ); + } + + /* Now we emit any remaining significant digits, or trailing zeros, + * until the required precision has been achieved. + */ + while( stream->precision-- > 0 ) + __pformat_putc( *value ? *value++ : '0', stream ); +} + +static +void __pformat_emit_efloat( int sign, char *value, int e, __pformat_t *stream ) +{ + /* Helper to emit a floating point representation of numeric data, + * as encoded by a prior call to `ecvt()' or `fcvt()'; (this DOES + * include the following exponent). + */ + int exp_width = 1; + __pformat_intarg_t exponent; exponent.__pformat_llong_t = e -= 1; + + /* Determine how many digit positions are required for the exponent. + */ + while( (e /= 10) != 0 ) + exp_width++; + + /* Ensure that this is at least as many as the standard requirement. + * The C99 standard requires the expenent to contain at least two + * digits, unless specified explicitly otherwise. + */ + if (stream->expmin == -1) + stream->expmin = 2; + if( exp_width < stream->expmin ) + exp_width = stream->expmin; + + /* Adjust the residual field width allocation, to allow for the + * number of exponent digits to be emitted, together with a sign + * and exponent separator... + */ + if( stream->width > (exp_width += 2) ) + stream->width -= exp_width; + + else + /* ignoring the field width specification, if insufficient. + */ + stream->width = PFORMAT_IGNORE; + + /* Emit the significand, as a fixed point value with one digit + * preceding the radix point. + */ + __pformat_emit_float( sign, value, 1, stream ); + + /* Reset precision, to ensure the mandatory minimum number of + * exponent digits will be emitted, and set the flags to ensure + * the sign is displayed. + */ + stream->precision = stream->expmin; + stream->flags |= PFORMAT_SIGNED; + + /* Emit the exponent separator. + */ + __pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream ); + + /* Readjust the field width setting, such that it again allows + * for the digits of the exponent, (which had been discounted when + * computing any left side padding requirement), so that they are + * correctly included in the computation of any right side padding + * requirement, (but here we exclude the exponent separator, which + * has been emitted, and so counted already). + */ + stream->width += exp_width - 1; + + /* And finally, emit the exponent itself, as a signed integer, + * with any padding required to achieve flush left justification, + * (which will be added automatically, by `__pformat_int()'). + */ + __pformat_int( exponent, stream ); +} + +static +void __pformat_float( long double x, __pformat_t *stream ) +{ + /* Handler for `%f' and `%F' format specifiers. + * + * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()' + * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve + * output in fixed point format. + */ + int sign, intlen; char *value; + + /* Establish the precision for the displayed value, defaulting to six + * digits following the decimal point, if not explicitly specified. + */ + if( stream->precision < 0 ) + stream->precision = 6; + + /* Encode the input value as ASCII, for display... + */ + value = __pformat_fcvt( x, stream->precision, &intlen, &sign ); + + if( intlen == PFORMAT_INFNAN ) + /* + * handle cases of `infinity' or `not-a-number'... + */ + __pformat_emit_inf_or_nan( sign, value, stream ); + + else + { /* or otherwise, emit the formatted result. + */ + __pformat_emit_float( sign, value, intlen, stream ); + + /* and, if there is any residual field width as yet unfilled, + * then we must be doing flush left justification, so pad out to + * the right hand field boundary. + */ + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + } + + /* Clean up `__pformat_fcvt()' memory allocation for `value'... + */ + __pformat_fcvt_release( value ); +} + +#ifdef __ENABLE_DFP + +typedef struct decimal128_decode { + int64_t significand[2]; + int32_t exponent; + int sig_neg; + int exp_neg; +} decimal128_decode; + +static uint32_t dec128_decode(decimal128_decode *result, const _Decimal128 deci){ + int64_t significand2; + int64_t significand1; + int32_t exp_part; + int8_t sig_sign; + ud128 in; + in.d = deci; + + if(in.t0.bits == 0x3){ /*case 11 */ + /* should not enter here */ + sig_sign = in.t2.sign; + exp_part = in.t2.exponent; + significand1 = in.t2.mantissaL; + significand2 = (in.t2.mantissaH | (0x1ULL << 49)); + } else { + sig_sign = in.t1.sign; + exp_part = in.t1.exponent; + significand1 = in.t1.mantissaL; + significand2 = in.t1.mantissaH; + } + exp_part -= 6176; /* exp bias */ + + result->significand[0] = significand1; + result->significand[1] = significand2; /* higher */ + result->exponent = exp_part; + result->exp_neg = (exp_part < 0 )? 1 : 0; + result->sig_neg = sig_sign; + + return 0; +} + +static +void __pformat_efloat_decimal(_Decimal128 x, __pformat_t *stream ){ + decimal128_decode in; + char str_exp[8]; + char str_sig[40]; + int floatclass = __fpclassifyd128(x); + + /* precision control */ + int32_t prec = ( (stream->precision < 0) || (stream->precision > 38) ) ? + 6 : stream->precision; + int32_t max_prec; + int32_t exp_strlen; + + dec128_decode(&in,x); + + if((floatclass & FP_INFINITE) == FP_INFINITE){ + stream->precision = 3; + if(stream->flags & PFORMAT_SIGNED) + __pformat_putc( in.sig_neg ? '-' : '+', stream ); + __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "inf" : "INF", stream); + return; + } else if(floatclass & FP_NAN){ + stream->precision = 3; + if(stream->flags & PFORMAT_SIGNED) + __pformat_putc( in.sig_neg ? '-' : '+', stream ); + __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "nan" : "NAN", stream); + return; + } + + /* Stringify significand */ + __bigint_to_string( + (uint32_t[4]){in.significand[0] & 0x0ffffffff, in.significand[0] >> 32, in.significand[1] & 0x0ffffffff, in.significand[1] >> 32 }, + 4, str_sig, sizeof(str_sig)); + __bigint_trim_leading_zeroes(str_sig,1); + max_prec = strlen(str_sig+1); + + /* Try to canonize exponent */ + in.exponent += max_prec; + in.exp_neg = (in.exponent < 0 ) ? 1 : 0; + + /* stringify exponent */ + __bigint_to_string( + (uint32_t[1]) { in.exp_neg ? -in.exponent : in.exponent}, + 1, str_exp, sizeof(str_exp)); + exp_strlen = strlen(__bigint_trim_leading_zeroes(str_exp,3)); + + /* account for dot, +-e */ + for(int32_t spacers = 0; spacers < stream->width - max_prec - exp_strlen - 4; spacers++) + __pformat_putc( ' ', stream ); + + /* optional sign */ + if (in.sig_neg || (stream->flags & PFORMAT_SIGNED)) { + __pformat_putc( in.sig_neg ? '-' : '+', stream ); + } else if( stream->width - max_prec - exp_strlen - 4 > 0 ) { + __pformat_putc( ' ', stream ); + } + stream->width = 0; + /* s.sss form */ + __pformat_putc(str_sig[0], stream); + if(prec) { + /* str_sig[prec+1] = '\0';*/ + __pformat_emit_radix_point(stream); + __pformat_putchars(str_sig+1, prec, stream); + + /* Pad with 0s */ + for(int i = max_prec; i < prec; i++) + __pformat_putc('0', stream); + } + + stream->precision = exp_strlen; /* force puts to emit */ + + __pformat_putc( ('E' | (stream->flags & PFORMAT_XCASE)), stream ); + __pformat_putc( in.exp_neg ? '-' : '+', stream ); + + for(int32_t trailing = 0; trailing < 3 - exp_strlen; trailing++) + __pformat_putc('0', stream); + __pformat_putchars(str_exp, exp_strlen,stream); +} + +static +void __pformat_float_decimal(_Decimal128 x, __pformat_t *stream ){ + decimal128_decode in; + char str_exp[8]; + char str_sig[40]; + int floatclass = __fpclassifyd128(x); + + /* precision control */ + int prec = ( (stream->precision < 0) || (stream->precision > 38) ) ? + 6 : stream->precision; + int max_prec; + + dec128_decode(&in,x); + + if((floatclass & FP_INFINITE) == FP_INFINITE){ + stream->precision = 3; + if(stream->flags & PFORMAT_SIGNED) + __pformat_putc( in.sig_neg ? '-' : '+', stream ); + __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "inf" : "INF", stream); + return; + } else if(floatclass & FP_NAN){ + stream->precision = 3; + if(stream->flags & PFORMAT_SIGNED) + __pformat_putc( in.sig_neg ? '-' : '+', stream ); + __pformat_puts( (stream->flags & PFORMAT_XCASE) ? "nan" : "NAN", stream); + return; + } + + /* Stringify significand */ + __bigint_to_string( + (uint32_t[4]){in.significand[0] & 0x0ffffffff, in.significand[0] >> 32, in.significand[1] & 0x0ffffffff, in.significand[1] >> 32 }, + 4, str_sig, sizeof(str_sig)); + __bigint_trim_leading_zeroes(str_sig,0); + max_prec = strlen(str_sig); + + /* stringify exponent */ + __bigint_to_string( + (uint32_t[1]) { in.exp_neg ? -in.exponent : in.exponent}, + 1, str_exp, sizeof(str_exp)); + __bigint_trim_leading_zeroes(str_exp,0); + + int32_t decimal_place = max_prec + in.exponent; + int32_t sig_written = 0; + + /*account for . +- */ + for(int32_t spacers = 0; spacers < stream->width - decimal_place - prec - 2; spacers++) + __pformat_putc( ' ', stream ); + + if (in.sig_neg || (stream->flags & PFORMAT_SIGNED)) { + __pformat_putc( in.sig_neg ? '-' : '+', stream ); + } else if(stream->width - decimal_place - prec - 1 > 0){ + __pformat_putc( ' ', stream ); + } + + if(decimal_place <= 0){ /* easy mode */ + __pformat_putc( '0', stream ); + points: + __pformat_emit_radix_point(stream); + for(int32_t written = 0; written < prec; written++){ + if(decimal_place < 0){ /* leading 0s */ + decimal_place++; + __pformat_putc( '0', stream ); + /* significand */ + } else if ( sig_written < max_prec ){ + __pformat_putc( str_sig[sig_written], stream ); + sig_written++; + } else { /* trailing 0s */ + __pformat_putc( '0', stream ); + } + } + } else { /* hard mode */ + for(; sig_written < decimal_place; sig_written++){ + __pformat_putc( str_sig[sig_written], stream ); + if(sig_written == max_prec - 1) break; + } + decimal_place -= sig_written; + for(; decimal_place > 0; decimal_place--) + __pformat_putc( '0', stream ); + goto points; + } + + return; +} + +static +void __pformat_gfloat_decimal(_Decimal128 x, __pformat_t *stream ){ + int prec = ( (stream->precision < 0)) ? + 6 : stream->precision; + decimal128_decode in; + dec128_decode(&in,x); + if(in.exponent > prec) __pformat_efloat_decimal(x,stream); + else __pformat_float_decimal(x,stream); +} + +#endif /* __ENABLE_DFP */ + +static +void __pformat_efloat( long double x, __pformat_t *stream ) +{ + /* Handler for `%e' and `%E' format specifiers. + * + * This wraps calls to `__pformat_cvt()', `__pformat_emit_efloat()' + * and `__pformat_emit_inf_or_nan()', as appropriate, to achieve + * output in floating point format. + */ + int sign, intlen; char *value; + + /* Establish the precision for the displayed value, defaulting to six + * digits following the decimal point, if not explicitly specified. + */ + if( stream->precision < 0 ) + stream->precision = 6; + + /* Encode the input value as ASCII, for display... + */ + value = __pformat_ecvt( x, stream->precision + 1, &intlen, &sign ); + + if( intlen == PFORMAT_INFNAN ) + /* + * handle cases of `infinity' or `not-a-number'... + */ + __pformat_emit_inf_or_nan( sign, value, stream ); + + else + /* or otherwise, emit the formatted result. + */ + __pformat_emit_efloat( sign, value, intlen, stream ); + + /* Clean up `__pformat_ecvt()' memory allocation for `value'... + */ + __pformat_ecvt_release( value ); +} + +static +void __pformat_gfloat( long double x, __pformat_t *stream ) +{ + /* Handler for `%g' and `%G' format specifiers. + * + * This wraps calls to `__pformat_cvt()', `__pformat_emit_float()', + * `__pformat_emit_efloat()' and `__pformat_emit_inf_or_nan()', as + * appropriate, to achieve output in the more suitable of either + * fixed or floating point format. + */ + int sign, intlen; char *value; + + /* Establish the precision for the displayed value, defaulting to + * six significant digits, if not explicitly specified... + */ + if( stream->precision < 0 ) + stream->precision = 6; + + /* or to a minimum of one digit, otherwise... + */ + else if( stream->precision == 0 ) + stream->precision = 1; + + /* Encode the input value as ASCII, for display. + */ + value = __pformat_ecvt( x, stream->precision, &intlen, &sign ); + + if( intlen == PFORMAT_INFNAN ) + /* + * Handle cases of `infinity' or `not-a-number'. + */ + __pformat_emit_inf_or_nan( sign, value, stream ); + + else if( (-4 < intlen) && (intlen <= stream->precision) ) + { + /* Value lies in the acceptable range for fixed point output, + * (i.e. the exponent is no less than minus four, and the number + * of significant digits which precede the radix point is fewer + * than the least number which would overflow the field width, + * specified or implied by the established precision). + */ + if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED ) + /* + * The `#' flag is in effect... + * Adjust precision to retain the specified number of significant + * digits, with the proper number preceding the radix point, and + * the balance following it... + */ + stream->precision -= intlen; + + else + /* The `#' flag is not in effect... + * Here we adjust the precision to accommodate all digits which + * precede the radix point, but we truncate any balance following + * it, to suppress output of non-significant trailing zeros... + */ + if( ((stream->precision = strlen( value ) - intlen) < 0) + /* + * This may require a compensating adjustment to the field + * width, to accommodate significant trailing zeros, which + * precede the radix point... + */ + && (stream->width > 0) ) + stream->width += stream->precision; + + /* Now, we format the result as any other fixed point value. + */ + __pformat_emit_float( sign, value, intlen, stream ); + + /* If there is any residual field width as yet unfilled, then + * we must be doing flush left justification, so pad out to the + * right hand field boundary. + */ + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + } + + else + { /* Value lies outside the acceptable range for fixed point; + * one significant digit will precede the radix point, so we + * decrement the precision to retain only the appropriate number + * of additional digits following it, when we emit the result + * in floating point format. + */ + if( (stream->flags & PFORMAT_HASHED) == PFORMAT_HASHED ) + /* + * The `#' flag is in effect... + * Adjust precision to emit the specified number of significant + * digits, with one preceding the radix point, and the balance + * following it, retaining any non-significant trailing zeros + * which are required to exactly match the requested precision... + */ + stream->precision--; + + else + /* The `#' flag is not in effect... + * Adjust precision to emit only significant digits, with one + * preceding the radix point, and any others following it, but + * suppressing non-significant trailing zeros... + */ + stream->precision = strlen( value ) - 1; + + /* Now, we format the result as any other floating point value. + */ + __pformat_emit_efloat( sign, value, intlen, stream ); + } + + /* Clean up `__pformat_ecvt()' memory allocation for `value'. + */ + __pformat_ecvt_release( value ); +} + +static +void __pformat_emit_xfloat( __pformat_fpreg_t value, __pformat_t *stream ) +{ + /* Helper for emitting floating point data, originating as + * either `double' or `long double' type, as a hexadecimal + * representation of the argument value. + */ + char buf[18 + 6], *p = buf; + __pformat_intarg_t exponent; short exp_width = 2; + + /* The mantissa field of the argument value representation can + * accommodate at most 16 hexadecimal digits, of which one will + * be placed before the radix point, leaving at most 15 digits + * to satisfy any requested precision; thus... + */ + if( (stream->precision >= 0) && (stream->precision < 15) ) + { + /* When the user specifies a precision within this range, + * we want to adjust the mantissa, to retain just the number + * of digits required, rounding up when the high bit of the + * leftmost discarded digit is set; (mask of 0x08 accounts + * for exactly one digit discarded, shifting 4 bits per + * digit, with up to 14 additional digits, to consume the + * full availability of 15 precision digits). + * + * However, before we perform the rounding operation, we + * normalise the mantissa, shifting it to the left by as many + * bit positions may be necessary, until its highest order bit + * is set, thus preserving the maximum number of bits in the + * rounded result as possible. + */ + while( value.__pformat_fpreg_mantissa < (LLONG_MAX + 1ULL) ) + value.__pformat_fpreg_mantissa <<= 1; + + /* We then shift the mantissa one bit position back to the + * right, to guard against possible overflow when the rounding + * adjustment is added. + */ + value.__pformat_fpreg_mantissa >>= 1; + + /* We now add the rounding adjustment, noting that to keep the + * 0x08 mask aligned with the shifted mantissa, we also need to + * shift it right by one bit initially, changing its starting + * value to 0x04... + */ + value.__pformat_fpreg_mantissa += 0x04LL << (4 * (14 - stream->precision)); + if( (value.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0ULL ) + /* + * When the rounding adjustment would not have overflowed, + * then we shift back to the left again, to fill the vacated + * bit we reserved to accommodate the carry. + */ + value.__pformat_fpreg_mantissa <<= 1; + + else + /* Otherwise the rounding adjustment would have overflowed, + * so the carry has already filled the vacated bit; the effect + * of this is equivalent to an increment of the exponent. + */ + value.__pformat_fpreg_exponent++; + + /* We now complete the rounding to the required precision, by + * shifting the unwanted digits out, from the right hand end of + * the mantissa. + */ + value.__pformat_fpreg_mantissa >>= 4 * (15 - stream->precision); + } + + /* Encode the significant digits of the mantissa in hexadecimal + * ASCII notation, ready for transfer to the output stream... + */ + while( value.__pformat_fpreg_mantissa ) + { + /* taking the rightmost digit in each pass... + */ + unsigned c = value.__pformat_fpreg_mantissa & 0xF; + if( c == value.__pformat_fpreg_mantissa) + { + /* inserting the radix point, when we reach the last, + * (i.e. the most significant digit), unless we found no + * less significant digits, with no mandatory radix point + * inclusion, and no additional required precision... + */ + if( (p > buf) + || (stream->flags & PFORMAT_HASHED) || (stream->precision > 0) ) + { + /* + * Internally, we represent the radix point as an ASCII '.'; + * we will replace it with any locale specific alternative, + * at the time of transfer to the ultimate destination. + */ + *p++ = '.'; + } + + /* If the most significant hexadecimal digit of the encoded + * output value is greater than one, then the indicated value + * will appear too large, by an additional binary exponent + * corresponding to the number of higher order bit positions + * which it occupies... + */ + while( value.__pformat_fpreg_mantissa > 1 ) + { + /* so reduce the exponent value to compensate... + */ + value.__pformat_fpreg_exponent--; + value.__pformat_fpreg_mantissa >>= 1; + } + } + + else if( stream->precision > 0 ) + /* + * we have not yet fulfilled the desired precision, + * and we have not yet found the most significant digit, + * so account for the current digit, within the field + * width required to meet the specified precision. + */ + stream->precision--; + + if( (c > 0) || (p > buf) || (stream->precision >= 0) ) + { + /* + * Ignoring insignificant trailing zeros, (unless required to + * satisfy specified precision), store the current encoded digit + * into the pending output buffer, in LIFO order, and using the + * appropriate case for digits in the `A'..`F' range. + */ + *p++ = c > 9 ? (c - 10 + 'A') | (stream->flags & PFORMAT_XCASE) : c + '0'; + } + /* Shift out the current digit, (4-bit logical shift right), + * to align the next more significant digit to be extracted, + * and encoded in the next pass. + */ + value.__pformat_fpreg_mantissa >>= 4; + } + + if( p == buf ) + { + /* Nothing has been queued for output... + * We need at least one zero, and possibly a radix point. + */ + if( (stream->precision > 0) || (stream->flags & PFORMAT_HASHED) ) + *p++ = '.'; + + *p++ = '0'; + } + + if( stream->width > 0 ) + { + /* Adjust the user specified field width, to account for the + * number of digits minimally required, to display the encoded + * value, at the requested precision. + * + * FIXME: this uses the minimum number of digits possible for + * representation of the binary exponent, in strict conformance + * with C99 and POSIX specifications. Although there appears to + * be no Microsoft precedent for doing otherwise, we may wish to + * relate this to the `_get_output_format()' result, to maintain + * consistency with `%e', `%f' and `%g' styles. + */ + int min_width = p - buf; + int exponent2 = value.__pformat_fpreg_exponent; + + /* If we have not yet queued sufficient digits to fulfil the + * requested precision, then we must adjust the minimum width + * specification, to accommodate the additional digits which + * are required to do so. + */ + if( stream->precision > 0 ) + min_width += stream->precision; + + /* Adjust the minimum width requirement, to accomodate the + * sign, radix indicator and at least one exponent digit... + */ + min_width += stream->flags & PFORMAT_SIGNED ? 6 : 5; + while( (exponent2 = exponent2 / 10) != 0 ) + { + /* and increase as required, if additional exponent digits + * are needed, also saving the exponent field width adjustment, + * for later use when that is emitted. + */ + min_width++; + exp_width++; + } + + if( stream->width > min_width ) + { + /* When specified field width exceeds the minimum required, + * adjust to retain only the excess... + */ + stream->width -= min_width; + + /* and then emit any required left side padding spaces. + */ + if( (stream->flags & PFORMAT_JUSTIFY) == 0 ) + while( stream->width-- > 0 ) + __pformat_putc( '\x20', stream ); + } + + else + /* Specified field width is insufficient; just ignore it! + */ + stream->width = PFORMAT_IGNORE; + } + + /* Emit the sign of the encoded value, as required... + */ + if( stream->flags & PFORMAT_NEGATIVE ) + /* + * this is mandatory, to indicate a negative value... + */ + __pformat_putc( '-', stream ); + + else if( stream->flags & PFORMAT_POSITIVE ) + /* + * but this is optional, for a positive value... + */ + __pformat_putc( '+', stream ); + + else if( stream->flags & PFORMAT_ADDSPACE ) + /* + * with this optional alternative. + */ + __pformat_putc( '\x20', stream ); + + /* Prefix a `0x' or `0X' radix indicator to the encoded value, + * with case appropriate to the format specification. + */ + __pformat_putc( '0', stream ); + __pformat_putc( 'X' | (stream->flags & PFORMAT_XCASE), stream ); + + /* If the `0' flag is in effect... + * Zero padding, to fill out the field, goes here... + */ + if( (stream->width > 0) && (stream->flags & PFORMAT_ZEROFILL) ) + while( stream->width-- > 0 ) + __pformat_putc( '0', stream ); + + /* Next, we emit the encoded value, without its exponent... + */ + while( p > buf ) + __pformat_emit_numeric_value( *--p, stream ); + + /* followed by any additional zeros needed to satisfy the + * precision specification... + */ + while( stream->precision-- > 0 ) + __pformat_putc( '0', stream ); + + /* then the exponent prefix, (C99 and POSIX specify `p'), + * in the case appropriate to the format specification... + */ + __pformat_putc( 'P' | (stream->flags & PFORMAT_XCASE), stream ); + + /* and finally, the decimal representation of the binary exponent, + * as a signed value with mandatory sign displayed, in a field width + * adjusted to accommodate it, LEFT justified, with any additional + * right side padding remaining from the original field width. + */ + stream->width += exp_width; + stream->flags |= PFORMAT_SIGNED; + /* sign extend */ + exponent.__pformat_u128_t.t128.digits[1] = (value.__pformat_fpreg_exponent < 0) ? -1 : 0; + exponent.__pformat_u128_t.t128.digits[0] = value.__pformat_fpreg_exponent; + __pformat_int( exponent, stream ); +} + +static +void __pformat_xldouble( long double x, __pformat_t *stream ) +{ + /* Handler for `%La' and `%LA' format specifiers, (with argument + * value specified as `long double' type). + */ + unsigned sign_bit = 0; + __pformat_fpreg_t z; z.__pformat_fpreg_ldouble_t = x; + + /* First check for NaN; it is emitted unsigned... + */ + if( isnan( x ) ) + __pformat_emit_inf_or_nan( sign_bit, "NaN", stream ); + + else + { /* Capture the sign bit up-front, so we can show it correctly + * even when the argument value is zero or infinite. + */ + if( (sign_bit = (z.__pformat_fpreg_exponent & 0x8000)) != 0 ) + stream->flags |= PFORMAT_NEGATIVE; + + /* Check for infinity, (positive or negative)... + */ + if( isinf( x ) ) + /* + * displaying the appropriately signed indicator, + * when appropriate. + */ + __pformat_emit_inf_or_nan( sign_bit, "Inf", stream ); + + else + { /* The argument value is a representable number... + * extract the effective value of the biased exponent... + */ + z.__pformat_fpreg_exponent &= 0x7FFF; + if( z.__pformat_fpreg_exponent == 0 ) + { + /* A biased exponent value of zero means either a + * true zero value, if the mantissa field also has + * a zero value, otherwise... + */ + if( z.__pformat_fpreg_mantissa != 0 ) + { + /* ...this mantissa represents a subnormal value; + * adjust the exponent, while shifting the mantissa + * to the left, until its leading bit is 1. + */ + z.__pformat_fpreg_exponent = 1-0x3FFF; + while( (z.__pformat_fpreg_mantissa & (LLONG_MAX + 1ULL)) == 0 ) + { + z.__pformat_fpreg_mantissa <<= 1; + --z.__pformat_fpreg_exponent; + } + } + } + else + /* This argument represents a non-zero normal number; + * eliminate the bias from the exponent... + */ + z.__pformat_fpreg_exponent -= 0x3FFF; + + /* Finally, hand the adjusted representation off to the + * generalised hexadecimal floating point format handler... + */ + __pformat_emit_xfloat( z, stream ); + } + } +} + +int +__pformat (int flags, void *dest, int max, const APICHAR *fmt, va_list argv) +{ + int c; + int saved_errno = errno; + + __pformat_t stream = + { + /* Create and initialise a format control block + * for this output request. + */ + dest, /* output goes to here */ + flags &= PFORMAT_TO_FILE | PFORMAT_NOLIMIT, /* only these valid initially */ + PFORMAT_IGNORE, /* no field width yet */ + PFORMAT_IGNORE, /* nor any precision spec */ + PFORMAT_RPINIT, /* radix point uninitialised */ + (wchar_t)(0), /* leave it unspecified */ + 0, + (wchar_t)(0), /* leave it unspecified */ + 0, /* zero output char count */ + max, /* establish output limit */ + -1 /* exponent chars preferred; + -1 means to be determined. */ + }; + +#ifdef __BUILD_WIDEAPI + const APICHAR *literal_string_start = NULL; +#endif + + format_scan: while( (c = *fmt++) != 0 ) + { + /* Format string parsing loop... + * The entry point is labelled, so that we can return to the start state + * from within the inner `conversion specification' interpretation loop, + * as soon as a conversion specification has been resolved. + */ + if( c == '%' ) + { + /* Initiate parsing of a `conversion specification'... + */ + __pformat_intarg_t argval; + __pformat_state_t state = PFORMAT_INIT; + __pformat_length_t length = PFORMAT_LENGTH_INT; + + /* Save the current format scan position, so that we can backtrack + * in the event of encountering an invalid format specification... + */ + const APICHAR *backtrack = fmt; + + /* Restart capture for dynamic field width and precision specs... + */ + int *width_spec = &stream.width; + + #ifdef __BUILD_WIDEAPI + if (literal_string_start) + { + stream.width = stream.precision = PFORMAT_IGNORE; + __pformat_wputchars( literal_string_start, fmt - literal_string_start - 1, &stream ); + literal_string_start = NULL; + } + #endif + + /* Reset initial state for flags, width and precision specs... + */ + stream.flags = flags; + stream.width = stream.precision = PFORMAT_IGNORE; + + while( *fmt ) + { + switch( c = *fmt++ ) + { + /* Data type specifiers... + * All are terminal, so exit the conversion spec parsing loop + * with a `goto format_scan', thus resuming at the outer level + * in the regular format string parser. + */ + case '%': + /* + * Not strictly a data type specifier... + * it simply converts as a literal `%' character. + * + * FIXME: should we require this to IMMEDIATELY follow the + * initial `%' of the "conversion spec"? (glibc `printf()' + * on GNU/Linux does NOT appear to require this, but POSIX + * and SUSv3 do seem to demand it). + */ + #ifndef __BUILD_WIDEAPI + __pformat_putc( c, &stream ); + #else + stream.width = stream.precision = PFORMAT_IGNORE; + __pformat_wputchars( L"%", 1, &stream ); + #endif + goto format_scan; + + case 'C': + /* + * Equivalent to `%lc'; set `length' accordingly, + * and simply fall through. + */ + length = PFORMAT_LENGTH_LONG; + + case 'c': + /* + * Single, (or single multibyte), character output... + * + * We handle these by copying the argument into our local + * `argval' buffer, and then we pass the address of that to + * either `__pformat_putchars()' or `__pformat_wputchars()', + * as appropriate, effectively formatting it as a string of + * the appropriate type, with a length of one. + * + * A side effect of this method of handling character data + * is that, if the user sets a precision of zero, then no + * character is actually emitted; we don't want that, so we + * forcibly override any user specified precision. + */ + stream.precision = PFORMAT_IGNORE; + + /* Now we invoke the appropriate format handler... + */ + if( (length == PFORMAT_LENGTH_LONG) + || (length == PFORMAT_LENGTH_LLONG) ) + { + /* considering any `long' type modifier as a reference to + * `wchar_t' data, (which is promoted to an `int' argument)... + */ + wchar_t iargval = (wchar_t)(va_arg( argv, int )); + __pformat_wputchars( &iargval, 1, &stream ); + } + else + { /* while anything else is simply taken as `char', (which + * is also promoted to an `int' argument)... + */ + argval.__pformat_uchar_t = (unsigned char)(va_arg( argv, int )); + __pformat_putchars( (char *)(&argval), 1, &stream ); + } + goto format_scan; + + case 'S': + /* + * Equivalent to `%ls'; set `length' accordingly, + * and simply fall through. + */ + length = PFORMAT_LENGTH_LONG; + + case 's': + if( (length == PFORMAT_LENGTH_LONG) + || (length == PFORMAT_LENGTH_LLONG)) + { + /* considering any `long' type modifier as a reference to + * a `wchar_t' string... + */ + __pformat_wcputs( va_arg( argv, wchar_t * ), &stream ); + } + else + /* This is normal string output; + * we simply invoke the appropriate handler... + */ + __pformat_puts( va_arg( argv, char * ), &stream ); + goto format_scan; + case 'm': /* strerror (errno) */ + __pformat_puts (strerror (saved_errno), &stream); + goto format_scan; + + case 'o': + case 'u': + case 'x': + case 'X': + /* + * Unsigned integer values; octal, decimal or hexadecimal format... + */ +#if __ENABLE_PRINTF128 + argval.__pformat_u128_t.t128.digits[1] = 0LL; /* no sign extend needed */ + if( length == PFORMAT_LENGTH_LLONG128 ) + argval.__pformat_u128_t.t128 = va_arg( argv, __tI128 ); + else +#endif + if( length == PFORMAT_LENGTH_LLONG ) { + /* + * with an `unsigned long long' argument, which we + * process `as is'... + */ + argval.__pformat_ullong_t = va_arg( argv, unsigned long long ); + + } else if( length == PFORMAT_LENGTH_LONG ) { + /* + * or with an `unsigned long', which we promote to + * `unsigned long long'... + */ + argval.__pformat_ullong_t = va_arg( argv, unsigned long ); + + } else + { /* or for any other size, which will have been promoted + * to `unsigned int', we select only the appropriately sized + * least significant segment, and again promote to the same + * size as `unsigned long long'... + */ + argval.__pformat_ullong_t = va_arg( argv, unsigned int ); + if( length == PFORMAT_LENGTH_SHORT ) + /* + * from `unsigned short'... + */ + argval.__pformat_ullong_t = argval.__pformat_ushort_t; + + else if( length == PFORMAT_LENGTH_CHAR ) + /* + * or even from `unsigned char'... + */ + argval.__pformat_ullong_t = argval.__pformat_uchar_t; + } + + /* so we can pass any size of argument to either of two + * common format handlers... + */ + if( c == 'u' ) + /* + * depending on whether output is to be encoded in + * decimal format... + */ + __pformat_int( argval, &stream ); + + else + /* or in octal or hexadecimal format... + */ + __pformat_xint( c, argval, &stream ); + + goto format_scan; + + case 'd': + case 'i': + /* + * Signed integer values; decimal format... + * This is similar to `u', but must process `argval' as signed, + * and be prepared to handle negative numbers. + */ + stream.flags |= PFORMAT_NEGATIVE; +#if __ENABLE_PRINTF128 + if( length == PFORMAT_LENGTH_LLONG128 ) { + argval.__pformat_u128_t.t128 = va_arg( argv, __tI128 ); + goto skip_sign; /* skip sign extend */ + } else +#endif + if( length == PFORMAT_LENGTH_LLONG ){ + /* + * The argument is a `long long' type... + */ + argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, long long ); + } else if( length == PFORMAT_LENGTH_LONG ) { + /* + * or here, a `long' type... + */ + argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, long ); + } else + { /* otherwise, it's an `int' type... + */ + argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, int ); + if( length == PFORMAT_LENGTH_SHORT ) + /* + * but it was promoted from a `short' type... + */ + argval.__pformat_u128_t.t128.digits[0] = argval.__pformat_short_t; + else if( length == PFORMAT_LENGTH_CHAR ) + /* + * or even from a `char' type... + */ + argval.__pformat_u128_t.t128.digits[0] = argval.__pformat_char_t; + } + + /* In any case, all share a common handler... + */ + argval.__pformat_u128_t.t128.digits[1] = (argval.__pformat_llong_t < 0) ? -1LL : 0LL; +#if __ENABLE_PRINTF128 + skip_sign: +#endif + __pformat_int( argval, &stream ); + goto format_scan; + + case 'p': + /* + * Pointer argument; format as hexadecimal, subject to... + */ + if( (state == PFORMAT_INIT) && (stream.flags == flags) ) + { + /* Here, the user didn't specify any particular + * formatting attributes. We must choose a default + * which will be compatible with Microsoft's (broken) + * scanf() implementation, (i.e. matching the default + * used by MSVCRT's printf(), which appears to resemble + * "%0.8X" for 32-bit pointers); in particular, we MUST + * NOT adopt a GNU-like format resembling "%#x", because + * Microsoft's scanf() will choke on the "0x" prefix. + */ + stream.flags |= PFORMAT_ZEROFILL; + stream.precision = 2 * sizeof( uintptr_t ); + } + argval.__pformat_u128_t.t128.digits[0] = va_arg( argv, uintptr_t ); + argval.__pformat_u128_t.t128.digits[1] = 0; + __pformat_xint( 'x', argval, &stream ); + goto format_scan; + + case 'e': + /* + * Floating point format, with lower case exponent indicator + * and lower case `inf' or `nan' representation when required; + * select lower case mode, and simply fall through... + */ + stream.flags |= PFORMAT_XCASE; + + case 'E': + /* + * Floating point format, with upper case exponent indicator + * and upper case `INF' or `NAN' representation when required, + * (or lower case for all of these, on fall through from above); + * select lower case mode, and simply fall through... + */ +#ifdef __ENABLE_DFP + if( stream.flags & PFORMAT_DECIM32 ) + /* Is a 32bit decimal float */ + __pformat_efloat_decimal((_Decimal128)va_arg( argv, _Decimal32 ), &stream ); + else if( stream.flags & PFORMAT_DECIM64 ) + /* + * Is a 64bit decimal float + */ + __pformat_efloat_decimal((_Decimal128)va_arg( argv, _Decimal64 ), &stream ); + else if( stream.flags & PFORMAT_DECIM128 ) + /* + * Is a 128bit decimal float + */ + __pformat_efloat_decimal(va_arg( argv, _Decimal128 ), &stream ); + else +#endif /* __ENABLE_DFP */ + if( stream.flags & PFORMAT_LDOUBLE ) + /* + * for a `long double' argument... + */ + __pformat_efloat( va_arg( argv, long double ), &stream ); + + else + /* or just a `double', which we promote to `long double', + * so the two may share a common format handler. + */ + __pformat_efloat( (long double)(va_arg( argv, double )), &stream ); + + goto format_scan; + + case 'f': + /* + * Fixed point format, using lower case for `inf' and + * `nan', when appropriate; select lower case mode, and + * simply fall through... + */ + stream.flags |= PFORMAT_XCASE; + + case 'F': + /* + * Fixed case format using upper case, or lower case on + * fall through from above, for `INF' and `NAN'... + */ +#ifdef __ENABLE_DFP + if( stream.flags & PFORMAT_DECIM32 ) + /* Is a 32bit decimal float */ + __pformat_float_decimal((_Decimal128)va_arg( argv, _Decimal32 ), &stream ); + else if( stream.flags & PFORMAT_DECIM64 ) + /* + * Is a 64bit decimal float + */ + __pformat_float_decimal((_Decimal128)va_arg( argv, _Decimal64 ), &stream ); + else if( stream.flags & PFORMAT_DECIM128 ) + /* + * Is a 128bit decimal float + */ + __pformat_float_decimal(va_arg( argv, _Decimal128 ), &stream ); + else +#endif /* __ENABLE_DFP */ + if( stream.flags & PFORMAT_LDOUBLE ) + /* + * for a `long double' argument... + */ + __pformat_float( va_arg( argv, long double ), &stream ); + + else + /* or just a `double', which we promote to `long double', + * so the two may share a common format handler. + */ + __pformat_float( (long double)(va_arg( argv, double )), &stream ); + + goto format_scan; + + case 'g': + /* + * Generalised floating point format, with lower case + * exponent indicator when required; select lower case + * mode, and simply fall through... + */ + stream.flags |= PFORMAT_XCASE; + + case 'G': + /* + * Generalised floating point format, with upper case, + * or on fall through from above, with lower case exponent + * indicator when required... + */ +#ifdef __ENABLE_DFP + if( stream.flags & PFORMAT_DECIM32 ) + /* Is a 32bit decimal float */ + __pformat_gfloat_decimal((_Decimal128)va_arg( argv, _Decimal32 ), &stream ); + else if( stream.flags & PFORMAT_DECIM64 ) + /* + * Is a 64bit decimal float + */ + __pformat_gfloat_decimal((_Decimal128)va_arg( argv, _Decimal64 ), &stream ); + else if( stream.flags & PFORMAT_DECIM128 ) + /* + * Is a 128bit decimal float + */ + __pformat_gfloat_decimal(va_arg( argv, _Decimal128 ), &stream ); + else +#endif /* __ENABLE_DFP */ + if( stream.flags & PFORMAT_LDOUBLE ) + /* + * for a `long double' argument... + */ + __pformat_gfloat( va_arg( argv, long double ), &stream ); + + else + /* or just a `double', which we promote to `long double', + * so the two may share a common format handler. + */ + __pformat_gfloat( (long double)(va_arg( argv, double )), &stream ); + + goto format_scan; + + case 'a': + /* + * Hexadecimal floating point format, with lower case radix + * and exponent indicators; select the lower case mode, and + * fall through... + */ + stream.flags |= PFORMAT_XCASE; + + case 'A': + /* + * Hexadecimal floating point format; handles radix and + * exponent indicators in either upper or lower case... + */ + if( stream.flags & PFORMAT_LDOUBLE ) + /* + * with a `long double' argument... + */ + __pformat_xldouble( va_arg( argv, long double ), &stream ); + + else + /* or just a `double'. + */ + __pformat_xldouble( (long double)(va_arg( argv, double )), &stream ); + + goto format_scan; + + case 'n': + /* + * Save current output character count... + */ + if( length == PFORMAT_LENGTH_CHAR ) + /* + * to a signed `char' destination... + */ + *va_arg( argv, char * ) = stream.count; + + else if( length == PFORMAT_LENGTH_SHORT ) + /* + * or to a signed `short'... + */ + *va_arg( argv, short * ) = stream.count; + + else if( length == PFORMAT_LENGTH_LONG ) + /* + * or to a signed `long'... + */ + *va_arg( argv, long * ) = stream.count; + + else if( length == PFORMAT_LENGTH_LLONG ) + /* + * or to a signed `long long'... + */ + *va_arg( argv, long long * ) = stream.count; + + else + /* + * or, by default, to a signed `int'. + */ + *va_arg( argv, int * ) = stream.count; + + goto format_scan; + + /* Argument length modifiers... + * These are non-terminal; each sets the format parser + * into the PFORMAT_END state, and ends with a `break'. + */ + case 'h': + /* + * Interpret the argument as explicitly of a `short' + * or `char' data type, truncated from the standard + * length defined for integer promotion. + */ + if( *fmt == 'h' ) + { + /* Modifier is `hh'; data type is `char' sized... + * Skip the second `h', and set length accordingly. + */ + ++fmt; + length = PFORMAT_LENGTH_CHAR; + } + + else + /* Modifier is `h'; data type is `short' sized... + */ + length = PFORMAT_LENGTH_SHORT; + + state = PFORMAT_END; + break; + + case 'j': + /* + * Interpret the argument as being of the same size as + * a `intmax_t' entity... + */ + length = __pformat_arg_length( intmax_t ); + state = PFORMAT_END; + break; + +# ifdef _WIN32 + + case 'I': + /* + * The MSVCRT implementation of the printf() family of + * functions explicitly uses... + */ +#ifdef __ENABLE_PRINTF128 + if( (fmt[0] == '1') && (fmt[1] == '2') && (fmt[2] == '8')){ + length = PFORMAT_LENGTH_LLONG128; + fmt += 3; + } else +#endif + if( (fmt[0] == '6') && (fmt[1] == '4') ) + { + /* I64' instead of `ll', + * when referring to `long long' integer types... + */ + length = PFORMAT_LENGTH_LLONG; + fmt += 2; + } else + if( (fmt[0] == '3') && (fmt[1] == '2') ) + { + /* and `I32' instead of `l', + * when referring to `long' integer types... + */ + length = PFORMAT_LENGTH_LONG; + fmt += 2; + } + + else + /* or unqualified `I' instead of `t' or `z', + * when referring to `ptrdiff_t' or `size_t' entities; + * (we will choose to map it to `ptrdiff_t'). + */ + length = __pformat_arg_length( ptrdiff_t ); + + state = PFORMAT_END; + break; + +# endif + +#ifdef __ENABLE_DFP + case 'H': + stream.flags |= PFORMAT_DECIM32; + state = PFORMAT_END; + break; + + case 'D': + /* + * Interpret the argument as explicitly of a + * `_Decimal64' or `_Decimal128' data type. + */ + if( *fmt == 'D' ) + { + /* Modifier is `DD'; data type is `_Decimal128' sized... + * Skip the second `D', and set length accordingly. + */ + ++fmt; + stream.flags |= PFORMAT_DECIM128; + } + + else + /* Modifier is `D'; data type is `_Decimal64' sized... + */ + stream.flags |= PFORMAT_DECIM64; + + state = PFORMAT_END; + break; +#endif /* __ENABLE_DFP */ + case 'l': + /* + * Interpret the argument as explicitly of a + * `long' or `long long' data type. + */ + if( *fmt == 'l' ) + { + /* Modifier is `ll'; data type is `long long' sized... + * Skip the second `l', and set length accordingly. + */ + ++fmt; + length = PFORMAT_LENGTH_LLONG; + } + + else + /* Modifier is `l'; data type is `long' sized... + */ + length = PFORMAT_LENGTH_LONG; + + state = PFORMAT_END; + break; + + case 'L': + /* + * Identify the appropriate argument as a `long double', + * when associated with `%a', `%A', `%e', `%E', `%f', `%F', + * `%g' or `%G' format specifications. + */ + stream.flags |= PFORMAT_LDOUBLE; + state = PFORMAT_END; + break; + + case 't': + /* + * Interpret the argument as being of the same size as + * a `ptrdiff_t' entity... + */ + length = __pformat_arg_length( ptrdiff_t ); + state = PFORMAT_END; + break; + + case 'z': + /* + * Interpret the argument as being of the same size as + * a `size_t' entity... + */ + length = __pformat_arg_length( size_t ); + state = PFORMAT_END; + break; + + /* Precision indicator... + * May appear once only; it must precede any modifier + * for argument length, or any data type specifier. + */ + case '.': + if( state < PFORMAT_GET_PRECISION ) + { + /* We haven't seen a precision specification yet, + * so initialise it to zero, (in case no digits follow), + * and accept any following digits as the precision. + */ + stream.precision = 0; + width_spec = &stream.precision; + state = PFORMAT_GET_PRECISION; + } + + else + /* We've already seen a precision specification, + * so this is just junk; proceed to end game. + */ + state = PFORMAT_END; + + /* Either way, we must not fall through here. + */ + break; + + /* Variable field width, or precision specification, + * derived from the argument list... + */ + case '*': + /* + * When this appears... + */ + if( width_spec + && ((state == PFORMAT_INIT) || (state == PFORMAT_GET_PRECISION)) ) + { + /* in proper context; assign to field width + * or precision, as appropriate. + */ + if( (*width_spec = va_arg( argv, int )) < 0 ) + { + /* Assigned value was negative... + */ + if( state == PFORMAT_INIT ) + { + /* For field width, this is equivalent to + * a positive value with the `-' flag... + */ + stream.flags |= PFORMAT_LJUSTIFY; + stream.width = -stream.width; + } + + else + /* while as a precision specification, + * it should simply be ignored. + */ + stream.precision = PFORMAT_IGNORE; + } + } + + else + /* out of context; give up on width and precision + * specifications for this conversion. + */ + state = PFORMAT_END; + + /* Mark as processed... + * we must not see `*' again, in this context. + */ + width_spec = NULL; + break; + + /* Formatting flags... + * Must appear while in the PFORMAT_INIT state, + * and are non-terminal, so again, end with `break'. + */ + case '#': + /* + * Select alternate PFORMAT_HASHED output style. + */ + if( state == PFORMAT_INIT ) + stream.flags |= PFORMAT_HASHED; + break; + + case '+': + /* + * Print a leading sign with numeric output, + * for both positive and negative values. + */ + if( state == PFORMAT_INIT ) + stream.flags |= PFORMAT_POSITIVE; + break; + + case '-': + /* + * Select left justification of displayed output + * data, within the output field width, instead of + * the default flush right justification. + */ + if( state == PFORMAT_INIT ) + stream.flags |= PFORMAT_LJUSTIFY; + break; + + case '\'': + /* + * This is an XSI extension to the POSIX standard, + * which we do not support, at present. + */ + if (state == PFORMAT_INIT) + { + stream.flags |= PFORMAT_GROUPED; /* $$$$ */ + int len; wchar_t rpchr; mbstate_t cstate; + memset (&cstate, 0, sizeof(state)); + if ((len = mbrtowc( &rpchr, localeconv()->thousands_sep, 16, &cstate)) > 0) + stream.thousands_chr = rpchr; + stream.thousands_chr_len = len; + } + break; + + case '\x20': + /* + * Reserve a single space, within the output field, + * for display of the sign of signed data; this will + * be occupied by the minus sign, if the data value + * is negative, or by a plus sign if the data value + * is positive AND the `+' flag is also present, or + * by a space otherwise. (Technically, this flag + * is redundant, if the `+' flag is present). + */ + if( state == PFORMAT_INIT ) + stream.flags |= PFORMAT_ADDSPACE; + break; + + case '0': + /* + * May represent a flag, to activate the `pad with zeros' + * option, or it may simply be a digit in a width or in a + * precision specification... + */ + if( state == PFORMAT_INIT ) + { + /* This is the flag usage... + */ + stream.flags |= PFORMAT_ZEROFILL; + break; + } + + default: + /* + * If we didn't match anything above, then we will check + * for digits, which we may accumulate to generate field + * width or precision specifications... + */ + if( (state < PFORMAT_END) && ('9' >= c) && (c >= '0') ) + { + if( state == PFORMAT_INIT ) + /* + * Initial digits explicitly relate to field width... + */ + state = PFORMAT_SET_WIDTH; + + else if( state == PFORMAT_GET_PRECISION ) + /* + * while those following a precision indicator + * explicitly relate to precision. + */ + state = PFORMAT_SET_PRECISION; + + if( width_spec ) + { + /* We are accepting a width or precision specification... + */ + if( *width_spec < 0 ) + /* + * and accumulation hasn't started yet; we simply + * initialise the accumulator with the current digit + * value, converting from ASCII to decimal. + */ + *width_spec = c - '0'; + + else + /* Accumulation has already started; we perform a + * `leftwise decimal digit shift' on the accumulator, + * (i.e. multiply it by ten), then add the decimal + * equivalent value of the current digit. + */ + *width_spec = *width_spec * 10 + c - '0'; + } + } + + else + { + /* We found a digit out of context, or some other character + * with no designated meaning; reject this format specification, + * backtrack, and emit it as literal text... + */ + fmt = backtrack; + #ifndef __BUILD_WIDEAPI + __pformat_putc( '%', &stream ); + #else + stream.width = stream.precision = PFORMAT_IGNORE; + __pformat_wputchars( L"%", 1, &stream ); + #endif + goto format_scan; + } + } + } + } + + else + /* We just parsed a character which is not included within any format + * specification; we simply emit it as a literal. + */ + #ifndef __BUILD_WIDEAPI + __pformat_putc( c, &stream ); + #else + if (literal_string_start == NULL) + literal_string_start = fmt - 1; + #endif + } + + /* When we have fully dispatched the format string, the return value is the + * total number of bytes we transferred to the output destination. + */ +#ifdef __BUILD_WIDEAPI + if (literal_string_start) + { + stream.width = stream.precision = PFORMAT_IGNORE; + __pformat_wputchars( literal_string_start, fmt - literal_string_start - 1, &stream ); + } +#endif + + return stream.count; +} + +/* $RCSfile: pformat.c,v $Revision: 1.9 $: end of file */ + diff --git a/libc/mingw/stdio/mingw_pformat.h b/libc/mingw/stdio/mingw_pformat.h new file mode 100644 index 000000000..477780432 --- /dev/null +++ b/libc/mingw/stdio/mingw_pformat.h @@ -0,0 +1,99 @@ +#ifndef PFORMAT_H +/* + * pformat.h + * + * $Id: pformat.h,v 1.1 2008/07/28 23:24:20 keithmarshall Exp $ + * + * A private header, defining the `pformat' API; it is to be included + * in each compilation unit implementing any of the `printf' family of + * functions, but serves no useful purpose elsewhere. + * + * Written by Keith Marshall + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + */ +#define PFORMAT_H + +/* The following macros reproduce definitions from _mingw.h, + * so that compilation will not choke, if using any compiler + * other than the MinGW implementation of GCC. + */ +#ifndef __cdecl +# ifdef __GNUC__ +# define __cdecl __attribute__((__cdecl__)) +# else +# define __cdecl +# endif +#endif + +#ifndef __MINGW_GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +# define __MINGW_GNUC_PREREQ( major, minor )\ + (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) +# else +# define __MINGW_GNUC_PREREQ( major, minor ) +# endif +#endif + +#ifndef __MINGW_NOTHROW +# if __MINGW_GNUC_PREREQ( 3, 3 ) +# define __MINGW_NOTHROW __attribute__((__nothrow__)) +# else +# define __MINGW_NOTHROW +# endif +#endif + +#ifdef __BUILD_WIDEAPI +#define APICHAR wchar_t +#else +#define APICHAR char +#endif + +/* The following are the declarations specific to the `pformat' API... + */ +#define PFORMAT_TO_FILE 0x2000 +#define PFORMAT_NOLIMIT 0x4000 + +#if defined(__MINGW32__) || defined(__MINGW64__) + /* + * Map MinGW specific function names, for use in place of the generic + * implementation defined equivalent function names. + */ +#ifdef __BUILD_WIDEAPI +# define __pformat __mingw_wpformat +#define __fputc(X,STR) fputwc((wchar_t) (X), (STR)) + +# define __printf __mingw_wprintf +# define __fprintf __mingw_fwprintf +# define __sprintf __mingw_swprintf +# define __snprintf __mingw_snwprintf + +# define __vprintf __mingw_vwprintf +# define __vfprintf __mingw_vfwprintf +# define __vsprintf __mingw_vswprintf +# define __vsnprintf __mingw_vsnwprintf +#else +# define __pformat __mingw_pformat +#define __fputc(X,STR) fputc((X), (STR)) + +# define __printf __mingw_printf +# define __fprintf __mingw_fprintf +# define __sprintf __mingw_sprintf +# define __snprintf __mingw_snprintf + +# define __vprintf __mingw_vprintf +# define __vfprintf __mingw_vfprintf +# define __vsprintf __mingw_vsprintf +# define __vsnprintf __mingw_vsnprintf +#endif /* __BUILD_WIDEAPI */ +#endif + +int __cdecl __pformat(int, void *, int, const APICHAR *, va_list) __MINGW_NOTHROW; +#endif /* !defined PFORMAT_H */ diff --git a/libc/mingw/stdio/mingw_pformatw.c b/libc/mingw/stdio/mingw_pformatw.c new file mode 100644 index 000000000..2c7cd1ead --- /dev/null +++ b/libc/mingw/stdio/mingw_pformatw.c @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 + +#include "mingw_pformat.c" + diff --git a/libc/mingw/stdio/mingw_printf.c b/libc/mingw/stdio/mingw_printf.c new file mode 100644 index 000000000..fbd2e7d90 --- /dev/null +++ b/libc/mingw/stdio/mingw_printf.c @@ -0,0 +1,59 @@ +/* printf.c + * + * $Id: printf.c,v 1.1 2008/08/11 22:41:55 keithmarshall Exp $ + * + * Provides an implementation of the "printf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, whence it may replace the Microsoft + * function of the same name. + * + * Written by Keith Marshall + * + * This implementation of "printf" will normally be invoked by calling + * "__mingw_printf()" in preference to a direct reference to "printf()" + * itself; this leaves the MSVCRT implementation as the default, which + * will be deployed when user code invokes "print()". Users who then + * wish to use this implementation may either call "__mingw_printf()" + * directly, or may use conditional preprocessor defines, to redirect + * references to "printf()" to "__mingw_printf()". + * + * Compiling this module with "-D INSTALL_AS_DEFAULT" will change this + * recommended convention, such that references to "printf()" in user + * code will ALWAYS be redirected to "__mingw_printf()"; if this option + * is adopted, then users wishing to use the MSVCRT implementation of + * "printf()" will be forced to use a "back-door" mechanism to do so. + * Such a "back-door" mechanism is provided with MinGW, allowing the + * MSVCRT implementation to be called as "__msvcrt_printf()"; however, + * since users may not expect this behaviour, a standard libmingwex.a + * installation does not employ this option. + * + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __printf(const APICHAR *, ...) __MINGW_NOTHROW; + +int __cdecl __printf(const APICHAR *fmt, ...) +{ + register int retval; + va_list argv; va_start( argv, fmt ); + _lock_file( stdout ); + retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv ); + _unlock_file( stdout ); + va_end( argv ); + return retval; +} + diff --git a/libc/mingw/stdio/mingw_printfw.c b/libc/mingw/stdio/mingw_printfw.c new file mode 100644 index 000000000..db65c93e8 --- /dev/null +++ b/libc/mingw/stdio/mingw_printfw.c @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 + +#include "mingw_printf.c" + diff --git a/libc/mingw/stdio/mingw_scanf.c b/libc/mingw/stdio/mingw_scanf.c new file mode 100644 index 000000000..ebec7d48b --- /dev/null +++ b/libc/mingw/stdio/mingw_scanf.c @@ -0,0 +1,28 @@ +#include +#include +#include + +extern int __mingw_vfscanf (FILE *stream, const char *format, va_list argp); + +int __mingw_scanf (const char *format, ...); +int __mingw_vscanf (const char *format, va_list argp); + +int +__mingw_scanf (const char *format, ...) +{ + va_list argp; + int r; + + va_start (argp, format); + r = __mingw_vfscanf (stdin, format, argp); + va_end (argp); + + return r; +} + +int +__mingw_vscanf (const char *format, va_list argp) +{ + return __mingw_vfscanf (stdin, format, argp); +} + diff --git a/libc/mingw/stdio/mingw_snprintf.c b/libc/mingw/stdio/mingw_snprintf.c new file mode 100644 index 000000000..0c0d76220 --- /dev/null +++ b/libc/mingw/stdio/mingw_snprintf.c @@ -0,0 +1,40 @@ +/* snprintf.c + * + * $Id: snprintf.c,v 1.3 2008/07/28 23:24:20 keithmarshall Exp $ + * + * Provides an implementation of the "snprintf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, replacing the redirection through + * libmoldnames.a, to the MSVCRT standard "_snprintf" function; (the + * standard MSVCRT function remains available, and may be invoked + * directly, using this fully qualified form of its name). + * + * Written by Keith Marshall + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ + +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __snprintf (APICHAR *, size_t, const APICHAR *fmt, ...) __MINGW_NOTHROW; +int __cdecl __vsnprintf (APICHAR *, size_t, const APICHAR *fmt, va_list) __MINGW_NOTHROW; + +int __cdecl __snprintf(APICHAR *buf, size_t length, const APICHAR *fmt, ...) +{ + va_list argv; va_start( argv, fmt ); + register int retval = __vsnprintf( buf, length, fmt, argv ); + va_end( argv ); + return retval; +} diff --git a/libc/mingw/stdio/mingw_snprintfw.c b/libc/mingw/stdio/mingw_snprintfw.c new file mode 100644 index 000000000..b31cda2ae --- /dev/null +++ b/libc/mingw/stdio/mingw_snprintfw.c @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 + +#include "mingw_snprintf.c" + diff --git a/libc/mingw/stdio/mingw_sprintf.c b/libc/mingw/stdio/mingw_sprintf.c new file mode 100644 index 000000000..4b46eb532 --- /dev/null +++ b/libc/mingw/stdio/mingw_sprintf.c @@ -0,0 +1,56 @@ +/* sprintf.c + * + * $Id: sprintf.c,v 1.1 2008/08/11 22:41:55 keithmarshall Exp $ + * + * Provides an implementation of the "sprintf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, whence it may replace the Microsoft + * function of the same name. + * + * Written by Keith Marshall + * + * This implementation of "sprintf" will normally be invoked by calling + * "__mingw_sprintf()" in preference to a direct reference to "sprintf()" + * itself; this leaves the MSVCRT implementation as the default, which + * will be deployed when user code invokes "sprint()". Users who then + * wish to use this implementation may either call "__mingw_sprintf()" + * directly, or may use conditional preprocessor defines, to redirect + * references to "sprintf()" to "__mingw_sprintf()". + * + * Compiling this module with "-D INSTALL_AS_DEFAULT" will change this + * recommended convention, such that references to "sprintf()" in user + * code will ALWAYS be redirected to "__mingw_sprintf()"; if this option + * is adopted, then users wishing to use the MSVCRT implementation of + * "sprintf()" will be forced to use a "back-door" mechanism to do so. + * Such a "back-door" mechanism is provided with MinGW, allowing the + * MSVCRT implementation to be called as "__msvcrt_sprintf()"; however, + * since users may not expect this behaviour, a standard libmingwex.a + * installation does not employ this option. + * + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __sprintf (APICHAR *, const APICHAR *, ...) __MINGW_NOTHROW; + +int __cdecl __sprintf(APICHAR *buf, const APICHAR *fmt, ...) +{ + register int retval; + va_list argv; va_start( argv, fmt ); + buf[retval = __pformat( PFORMAT_NOLIMIT, buf, 0, fmt, argv )] = '\0'; + va_end( argv ); + return retval; +} diff --git a/libc/mingw/stdio/mingw_sprintfw.c b/libc/mingw/stdio/mingw_sprintfw.c new file mode 100644 index 000000000..0baf1e4f3 --- /dev/null +++ b/libc/mingw/stdio/mingw_sprintfw.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 +#define _CRT_NON_CONFORMING_SWPRINTFS 1 + +#include "mingw_sprintf.c" + diff --git a/libc/mingw/stdio/mingw_sscanf.c b/libc/mingw/stdio/mingw_sscanf.c new file mode 100644 index 000000000..e1a8e8bfe --- /dev/null +++ b/libc/mingw/stdio/mingw_sscanf.c @@ -0,0 +1,20 @@ +#include +#include + +extern int __mingw_vsscanf (const char *buf, const char *format, va_list argp); + +int __mingw_sscanf (const char *buf, const char *format, ...); + +int +__mingw_sscanf (const char *buf, const char *format, ...) +{ + va_list argp; + int r; + + va_start (argp, format); + r = __mingw_vsscanf (buf, format, argp); + va_end (argp); + + return r; +} + diff --git a/libc/mingw/stdio/mingw_swscanf.c b/libc/mingw/stdio/mingw_swscanf.c new file mode 100644 index 000000000..47f9f34f1 --- /dev/null +++ b/libc/mingw/stdio/mingw_swscanf.c @@ -0,0 +1,20 @@ +#include +#include + +extern int __mingw_vswscanf (const wchar_t *buf, const wchar_t *format, va_list argp); + +int __mingw_swscanf (const wchar_t *buf, const wchar_t *format, ...); + +int +__mingw_swscanf (const wchar_t *buf, const wchar_t *format, ...) +{ + va_list argp; + int r; + + va_start (argp, format); + r = __mingw_vswscanf (buf, format, argp); + va_end (argp); + + return r; +} + diff --git a/libc/mingw/stdio/mingw_vasprintf.c b/libc/mingw/stdio/mingw_vasprintf.c new file mode 100644 index 000000000..8e3344a27 --- /dev/null +++ b/libc/mingw/stdio/mingw_vasprintf.c @@ -0,0 +1,25 @@ +#define _GNU_SOURCE +#define __CRT__NO_INLINE + +#include +#include +#include + +int __mingw_vasprintf(char ** __restrict__ ret, + const char * __restrict__ format, + va_list ap) { + int len; + /* Get Length */ + len = __mingw_vsnprintf(NULL,0,format,ap); + if (len < 0) return -1; + /* +1 for \0 terminator. */ + *ret = malloc(len + 1); + /* Check malloc fail*/ + if (!*ret) return -1; + /* Write String */ + __mingw_vsnprintf(*ret,len+1,format,ap); + /* Terminate explicitly */ + (*ret)[len] = '\0'; + return len; +} + diff --git a/libc/mingw/stdio/mingw_vfprintf.c b/libc/mingw/stdio/mingw_vfprintf.c new file mode 100644 index 000000000..01ad01b57 --- /dev/null +++ b/libc/mingw/stdio/mingw_vfprintf.c @@ -0,0 +1,58 @@ +/* vfprintf.c + * + * $Id: vfprintf.c,v 1.1 2008/08/11 22:41:55 keithmarshall Exp $ + * + * Provides an implementation of the "vfprintf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, whence it may replace the Microsoft + * function of the same name. + * + * Written by Keith Marshall + * + * This implementation of "vfprintf" will normally be invoked by calling + * "__mingw_vfprintf()" in preference to a direct reference to "vfprintf()" + * itself; this leaves the MSVCRT implementation as the default, which + * will be deployed when user code invokes "vfprint()". Users who then + * wish to use this implementation may either call "__mingw_vfprintf()" + * directly, or may use conditional preprocessor defines, to redirect + * references to "vfprintf()" to "__mingw_vfprintf()". + * + * Compiling this module with "-D INSTALL_AS_DEFAULT" will change this + * recommended convention, such that references to "vfprintf()" in user + * code will ALWAYS be redirected to "__mingw_vfprintf()"; if this option + * is adopted, then users wishing to use the MSVCRT implementation of + * "vfprintf()" will be forced to use a "back-door" mechanism to do so. + * Such a "back-door" mechanism is provided with MinGW, allowing the + * MSVCRT implementation to be called as "__msvcrt_vfprintf()"; however, + * since users may not expect this behaviour, a standard libmingwex.a + * installation does not employ this option. + * + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __vfprintf (FILE *, const APICHAR *, va_list) __MINGW_NOTHROW; + +int __cdecl __vfprintf(FILE *stream, const APICHAR *fmt, va_list argv) +{ + register int retval; + + _lock_file( stream ); + retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stream, 0, fmt, argv ); + _unlock_file( stream ); + + return retval; +} diff --git a/libc/mingw/stdio/mingw_vfprintfw.c b/libc/mingw/stdio/mingw_vfprintfw.c new file mode 100644 index 000000000..0b8638765 --- /dev/null +++ b/libc/mingw/stdio/mingw_vfprintfw.c @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 + +#include "mingw_vfprintf.c" + diff --git a/libc/mingw/stdio/mingw_vfscanf.c b/libc/mingw/stdio/mingw_vfscanf.c new file mode 100644 index 000000000..4bd9e91cf --- /dev/null +++ b/libc/mingw/stdio/mingw_vfscanf.c @@ -0,0 +1,1630 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2011 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Helper flags for conversion. */ +#define IS_C 0x0001 +#define IS_S 0x0002 +#define IS_L 0x0004 +#define IS_LL 0x0008 +#define IS_SIGNED_NUM 0x0010 +#define IS_POINTER 0x0020 +#define IS_HEX_FLOAT 0x0040 +#define IS_SUPPRESSED 0x0080 +#define USE_GROUP 0x0100 +#define USE_GNU_ALLOC 0x0200 +#define USE_POSIX_ALLOC 0x0400 + +#define IS_ALLOC_USED (USE_GNU_ALLOC | USE_POSIX_ALLOC) + +/* internal stream structure with back-buffer. */ +typedef struct _IFP +{ + __extension__ union { + void *fp; + const char *str; + }; + int bch[1024]; + int is_string : 1; + int back_top; + int seen_eof : 1; +} _IFP; + +static void * +get_va_nth (va_list argp, unsigned int n) +{ + va_list ap; + if (!n) abort (); + va_copy (ap, argp); + while (--n > 0) + (void) va_arg(ap, void *); + return va_arg (ap, void *); +} + +static void +optimize_alloc (char **p, char *end, size_t alloc_sz) +{ + size_t need_sz; + char *h; + + if (!p || !*p) + return; + + need_sz = end - *p; + if (need_sz == alloc_sz) + return; + + if ((h = (char *) realloc (*p, need_sz)) != NULL) + *p = h; +} + +static void +back_ch (int c, _IFP *s, size_t *rin, int not_eof) +{ + if (!not_eof && c == EOF) + return; + if (s->is_string == 0) + { + FILE *fp = s->fp; + ungetc (c, fp); + rin[0] -= 1; + return; + } + rin[0] -= 1; + s->bch[s->back_top] = c; + s->back_top += 1; +} + +static int +in_ch (_IFP *s, size_t *rin) +{ + int r; + if (s->back_top) + { + s->back_top -= 1; + r = s->bch[s->back_top]; + rin[0] += 1; + } + else if (s->seen_eof) + { + return EOF; + } + else if (s->is_string) + { + const char *ps = s->str; + r = ((int) *ps) & 0xff; + ps++; + if (r != 0) + { + rin[0] += 1; + s->str = ps; + return r; + } + s->seen_eof = 1; + return EOF; + } + else + { + FILE *fp = (FILE *) s->fp; + r = getc (fp); + if (r != EOF) + rin[0] += 1; + else s->seen_eof = 1; + } + return r; +} + +static int +match_string (_IFP *s, size_t *rin, int *c, const char *str) +{ + int ch = *c; + + if (*str == 0) + return 1; + + if (*str != (char) tolower (ch)) + return 0; + ++str; + while (*str != 0) + { + if ((ch = in_ch (s, rin)) == EOF) + { + c[0] = ch; + return 0; + } + + if (*str != (char) tolower (ch)) + { + c[0] = ch; + return 0; + } + ++str; + } + c[0] = ch; + return 1; +} + +struct gcollect +{ + size_t count; + struct gcollect *next; + char **ptrs[32]; +}; + +static void +release_ptrs (struct gcollect **pt, char **wbuf) +{ + struct gcollect *pf; + size_t cnt; + + if (wbuf) + { + free (*wbuf); + *wbuf = NULL; + } + if (!pt || (pf = *pt) == NULL) + return; + while (pf != NULL) + { + struct gcollect *pf_sv = pf; + for (cnt = 0; cnt < pf->count; ++cnt) + { + free (*pf->ptrs[cnt]); + *pf->ptrs[cnt] = NULL; + } + pf = pf->next; + free (pf_sv); + } + *pt = NULL; +} + +static int +cleanup_return (int rval, struct gcollect **pfree, char **strp, char **wbuf) +{ + if (rval == EOF) + release_ptrs (pfree, wbuf); + else + { + if (pfree) + { + struct gcollect *pf = *pfree, *pf_sv; + while (pf != NULL) + { + pf_sv = pf; + pf = pf->next; + free (pf_sv); + } + *pfree = NULL; + } + if (strp != NULL) + { + free (*strp); + *strp = NULL; + } + if (wbuf) + { + free (*wbuf); + *wbuf = NULL; + } + } + return rval; +} + +static struct gcollect * +resize_gcollect (struct gcollect *pf) +{ + struct gcollect *np; + if (pf && pf->count < 32) + return pf; + np = malloc (sizeof (struct gcollect)); + np->count = 0; + np->next = pf; + return np; +} + +static char * +resize_wbuf (size_t wpsz, size_t *wbuf_max_sz, char *old) +{ + char *wbuf; + size_t nsz; + if (*wbuf_max_sz != wpsz) + return old; + nsz = (256 > (2 * wbuf_max_sz[0]) ? 256 : (2 * wbuf_max_sz[0])); + if (!old) + wbuf = (char *) malloc (nsz); + else + wbuf = (char *) realloc (old, nsz); + if (!wbuf) + { + if (old) + free (old); + } + else + *wbuf_max_sz = nsz; + return wbuf; +} + +static int +__mingw_sformat (_IFP *s, const char *format, va_list argp) +{ + const char *f = format; + struct gcollect *gcollect = NULL; + size_t read_in = 0, wbuf_max_sz = 0, cnt; + ssize_t str_sz = 0; + char *str = NULL, **pstr = NULL, *wbuf = NULL; + wchar_t *wstr = NULL; + int rval = 0, c = 0, ignore_ws = 0; + va_list arg; + unsigned char fc; + unsigned int npos; + int width, flags, base = 0, errno_sv; + size_t wbuf_cur_sz, read_in_sv, new_sz, n; + char seen_dot, seen_exp, is_neg, not_in; + char *tmp_wbuf_ptr, buf[MB_LEN_MAX]; + const char *lc_decimal_point, *lc_thousands_sep; + mbstate_t state, cstate; + union { + unsigned long long ull; + unsigned long ul; + long long ll; + long l; + } cv_val; + + arg = argp; + + if (!s || s->fp == NULL || !format) + { + errno = EINVAL; + return EOF; + } + + memset (&state, 0, sizeof (state)); + + lc_decimal_point = localeconv()->decimal_point; + lc_thousands_sep = localeconv()->thousands_sep; + if (lc_thousands_sep != NULL && *lc_thousands_sep == 0) + lc_thousands_sep = NULL; + + while (*f != 0) + { + if (!isascii ((unsigned char) *f)) + { + int len; + + if ((len = mbrlen (f, strlen (f), &state)) > 0) + { + do + { + if ((c = in_ch (s, &read_in)) == EOF || c != (unsigned char) *f++) + { + back_ch (c, s, &read_in, 1); + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + } + } + while (--len > 0); + + continue; + } + } + + fc = *f++; + if (fc != '%') + { + if (isspace (fc)) + ignore_ws = 1; + else + { + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + if (ignore_ws) + { + ignore_ws = 0; + if (isspace (c)) + { + do + { + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + } + while (isspace (c)); + } + } + + if (c != fc) + { + back_ch (c, s, &read_in, 0); + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + continue; + } + + width = flags = 0; + npos = 0; + wbuf_cur_sz = 0; + + if (isdigit ((unsigned char) *f)) + { + const char *svf = f; + npos = (unsigned char) *f++ - '0'; + while (isdigit ((unsigned char) *f)) + npos = npos * 10 + ((unsigned char) *f++ - '0'); + if (*f != '$') + { + npos = 0; + f = svf; + } + else + f++; + } + + do + { + if (*f == '*') + flags |= IS_SUPPRESSED; + else if (*f == '\'') + { + if (lc_thousands_sep) + flags |= USE_GROUP; + } + else if (*f == 'I') + { + /* we don't support locale's digits (i18N), but ignore it for now silently. */ + ; +#ifdef _WIN32 + if (f[1] == '6' && f[2] == '4') + { + flags |= IS_LL | IS_L; + f += 2; + } + else if (f[1] == '3' && f[2] == '2') + { + flags |= IS_L; + f += 2; + } + else + { +#ifdef _WIN64 + flags |= IS_LL | IS_L; +#else + flags |= IS_L; +#endif + } +#endif + } + else + break; + ++f; + } + while (1); + + while (isdigit ((unsigned char) *f)) + width = width * 10 + ((unsigned char) *f++ - '0'); + + if (!width) + width = -1; + + switch (*f) + { + case 'h': + ++f; + flags |= (*f == 'h' ? IS_C : IS_S); + if (*f == 'h') + ++f; + break; + case 'l': + ++f; + flags |= (*f == 'l' ? IS_LL : 0) | IS_L; + if (*f == 'l') + ++f; + break; + case 'q': case 'L': + ++f; + flags |= IS_LL | IS_L; + break; + case 'a': + if (f[1] != 's' && f[1] != 'S' && f[1] != '[') + break; + ++f; + flags |= USE_GNU_ALLOC; + break; + case 'm': + flags |= USE_POSIX_ALLOC; + ++f; + if (*f == 'l') + { + flags |= IS_L; + f++; + } + break; + case 'z': +#ifdef _WIN64 + flags |= IS_LL | IS_L; +#else + flags |= IS_L; +#endif + ++f; + break; + case 'j': + if (sizeof (uintmax_t) > sizeof (unsigned long)) + flags |= IS_LL; + else if (sizeof (uintmax_t) > sizeof (unsigned int)) + flags |= IS_L; + ++f; + break; + case 't': +#ifdef _WIN64 + flags |= IS_LL; +#else + flags |= IS_L; +#endif + ++f; + break; + case 0: + return cleanup_return (rval, &gcollect, pstr, &wbuf); + default: + break; + } + + if (*f == 0) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + fc = *f++; + if (ignore_ws || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) + { + errno_sv = errno; + errno = 0; + do + { + if ((c == EOF || (c = in_ch (s, &read_in)) == EOF) + && errno == EINTR) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + } + while (isspace (c)); + + ignore_ws = 0; + errno = errno_sv; + back_ch (c, s, &read_in, 0); + } + + switch (fc) + { + case 'c': + if ((flags & IS_L) != 0) + fc = 'C'; + break; + case 's': + if ((flags & IS_L) != 0) + fc = 'S'; + break; + } + + switch (fc) + { + case '%': + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + if (c != fc) + { + back_ch (c, s, &read_in, 1); + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + break; + + case 'n': + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_LL) != 0) + *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = read_in; + else if ((flags & IS_L) != 0) + *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = read_in; + else if ((flags & IS_S) != 0) + *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = read_in; + else if ((flags & IS_C) != 0) + *(npos != 0 ? (char *) get_va_nth (argp, npos) : va_arg (arg, char *)) = read_in; + else + *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = read_in; + } + break; + + case 'c': + if (width == -1) + width = 1; + + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + str_sz = (width > 1024 ? 1024 : width); + if ((str = *pstr = (char *) malloc (str_sz)) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + str = (char *) get_va_nth (argp, npos); + else + str = va_arg (arg, char *); + if (!str) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + { + do + { + if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz)) + { + new_sz = str_sz + (str_sz >= width ? width - 1 : str_sz); + while ((str = (char *) realloc (*pstr, new_sz)) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!str) + { + release_ptrs (&gcollect, &wbuf); + return EOF; + } + *pstr = str; + str += str_sz; + str_sz = new_sz; + } + *str++ = c; + } + while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); + } + else + while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); + + if ((flags & IS_SUPPRESSED) == 0) + { + optimize_alloc (pstr, str, str_sz); + pstr = NULL; + ++rval; + } + + break; + + case 'C': + if (width == -1) + width = 1; + + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + str_sz = (width > 1024 ? 1024 : width); + *pstr = (char *) malloc (str_sz * sizeof (wchar_t)); + if ((wstr = (wchar_t *) *pstr) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + wstr = (wchar_t *) get_va_nth (argp, npos); + else + wstr = va_arg (arg, wchar_t *); + if (!wstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + memset (&cstate, 0, sizeof (cstate)); + + do + { + buf[0] = c; + + if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0 + && wstr == ((wchar_t *) *pstr + str_sz)) + { + new_sz = str_sz + (str_sz > width ? width - 1 : str_sz); + + while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!wstr) + { + release_ptrs (&gcollect, &wbuf); + return EOF; + } + *pstr = (char *) wstr; + wstr += str_sz; + str_sz = new_sz; + } + + while (1) + { + n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate); + + if (n == (size_t) -2) + { + if ((c = in_ch (s, &read_in)) == EOF) + { + errno = EILSEQ; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + buf[0] = c; + continue; + } + + if (n != 1) + { + errno = EILSEQ; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + break; + } + + ++wstr; + } + while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); + + if ((flags & IS_SUPPRESSED) == 0) + { + optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); + pstr = NULL; + ++rval; + } + break; + + case 's': + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + str_sz = 100; + if ((str = *pstr = (char *) malloc (100)) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + str = (char *) get_va_nth (argp, npos); + else + str = va_arg (arg, char *); + if (!str) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + do + { + if (isspace (c)) + { + back_ch (c, s, &read_in, 1); + break; + } + + if ((flags & IS_SUPPRESSED) == 0) + { + *str++ = c; + if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz)) + { + new_sz = str_sz * 2; + + while ((str = (char *) realloc (*pstr, new_sz)) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!str) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + (*pstr)[str_sz - 1] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = str; + str += str_sz; + str_sz = new_sz; + } + } + } + while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != EOF); + + if ((flags & IS_SUPPRESSED) == 0) + { + *str++ = 0; + optimize_alloc (pstr, str, str_sz); + pstr = NULL; + ++rval; + } + break; + + case 'S': + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + str_sz = 100; + *pstr = (char *) malloc (100 * sizeof (wchar_t)); + if ((wstr = (wchar_t *) *pstr) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + wstr = (wchar_t *) get_va_nth (argp, npos); + else + wstr = va_arg (arg, wchar_t *); + if (!wstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + memset (&cstate, 0, sizeof (cstate)); + + do + { + if (isspace (c)) + { + back_ch (c, s, &read_in, 1); + break; + } + + buf[0] = c; + + while (1) + { + n = mbrtowc ((flags & IS_SUPPRESSED) == 0 ? wstr : NULL, buf, 1, &cstate); + + if (n == (size_t) -2) + { + if ((c = in_ch (s, &read_in)) == EOF) + { + errno = EILSEQ; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + buf[0] = c; + continue; + } + + if (n != 1) + { + errno = EILSEQ; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + ++wstr; + break; + } + + if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0 + && wstr == ((wchar_t *) *pstr + str_sz)) + { + new_sz = str_sz * 2; + while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!wstr) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + ((wchar_t *) (*pstr))[str_sz - 1] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = (char *) wstr; + wstr += str_sz; + str_sz = new_sz; + } + } + while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != EOF); + + if ((flags & IS_SUPPRESSED) == 0) + { + *wstr++ = 0; + optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); + pstr = NULL; + ++rval; + } + break; + + case 'd': case 'i': + case 'o': case 'p': + case 'u': + case 'x': case 'X': + switch (fc) + { + case 'd': + flags |= IS_SIGNED_NUM; + base = 10; + break; + case 'i': + flags |= IS_SIGNED_NUM; + base = 0; + break; + case 'o': + base = 8; + break; + case 'p': + base = 16; + flags &= ~(IS_S | IS_LL | IS_L); + #ifdef _WIN64 + flags |= IS_LL; + #endif + flags |= IS_L | IS_POINTER; + break; + case 'u': + base = 10; + break; + case 'x': case 'X': + base = 16; + break; + } + + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + if (c == '+' || c == '-') + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + if (width > 0) + --width; + c = in_ch (s, &read_in); + } + if (width != 0 && c == '0') + { + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + c = in_ch (s, &read_in); + + if (width != 0 && tolower (c) == 'x') + { + if (!base) + base = 16; + if (base == 16) + { + if (width > 0) + --width; + c = in_ch (s, &read_in); + } + } + else if (!base) + base = 8; + } + + if (!base) + base = 10; + + while (c != EOF && width != 0) + { + if (base == 16) + { + if (!isxdigit (c)) + break; + } + else if (!isdigit (c) || (int) (c - '0') >= base) + { + const char *p = lc_thousands_sep; + int remain; + + if (base != 10 || (flags & USE_GROUP) == 0) + break; + remain = width > 0 ? width : INT_MAX; + while ((unsigned char) *p == c && remain >= 0) + { + /* As our conversion routines aren't supporting thousands + separators, we are filtering them here. */ + + ++p; + if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF) + break; + --remain; + } + + if (*p != 0) + { + if (p > lc_thousands_sep) + { + back_ch (c, s, &read_in, 0); + while (--p > lc_thousands_sep) + back_ch ((unsigned char) *p, s, &read_in, 1); + c = (unsigned char) *p; + } + break; + } + + if (width > 0) + width = remain; + --wbuf_cur_sz; + } + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + if (width > 0) + --width; + + c = in_ch (s, &read_in); + } + + if (!wbuf_cur_sz || (wbuf_cur_sz == 1 && (wbuf[0] == '+' || wbuf[0] == '-'))) + { + if (!wbuf_cur_sz && (flags & IS_POINTER) != 0 + && match_string (s, &read_in, &c, "(nil)")) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = '0'; + } + else + { + back_ch (c, s, &read_in, 0); + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + else + back_ch (c, s, &read_in, 0); + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = 0; + + if ((flags & IS_LL)) + { + if (flags & IS_SIGNED_NUM) + cv_val.ll = strtoll (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); + else + cv_val.ull = strtoull (wbuf, &tmp_wbuf_ptr, base); + } + else + { + if (flags & IS_SIGNED_NUM) + cv_val.l = strtol (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); + else + cv_val.ul = strtoul (wbuf, &tmp_wbuf_ptr, base); + } + if (wbuf == tmp_wbuf_ptr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_SIGNED_NUM) != 0) + { + if ((flags & IS_LL) != 0) + *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = cv_val.ll; + else if ((flags & IS_L) != 0) + *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = cv_val.l; + else if ((flags & IS_S) != 0) + *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = (short) cv_val.l; + else if ((flags & IS_C) != 0) + *(npos != 0 ? (signed char *) get_va_nth (argp, npos) : va_arg (arg, signed char *)) = (signed char) cv_val.ul; + else + *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = (int) cv_val.l; + } + else + { + if ((flags & IS_LL) != 0) + *(npos != 0 ? (unsigned long long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long long *)) = cv_val.ull; + else if ((flags & IS_L) != 0) + *(npos != 0 ? (unsigned long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long *)) = cv_val.ul; + else if ((flags & IS_S) != 0) + *(npos != 0 ? (unsigned short *) get_va_nth (argp, npos) : va_arg (arg, unsigned short *)) + = (unsigned short) cv_val.ul; + else if ((flags & IS_C) != 0) + *(npos != 0 ? (unsigned char *) get_va_nth (argp, npos) : va_arg (arg, unsigned char *)) = (unsigned char) cv_val.ul; + else + *(npos != 0 ? (unsigned int *) get_va_nth (argp, npos) : va_arg (arg, unsigned int *)) = (unsigned int) cv_val.ul; + } + ++rval; + } + break; + + case 'e': case 'E': + case 'f': case 'F': + case 'g': case 'G': + case 'a': case 'A': + if (width > 0) + --width; + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + seen_dot = seen_exp = 0; + is_neg = (c == '-' ? 1 : 0); + + if (c == '-' || c == '+') + { + if (width == 0 || (c = in_ch (s, &read_in)) == EOF) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + if (width > 0) + --width; + } + + if (tolower (c) == 'n') + { + const char *match_txt = "nan"; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + ++match_txt; + do + { + if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0]) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + ++match_txt; + } + while (*match_txt != 0); + } + else if (tolower (c) == 'i') + { + const char *match_txt = "inf"; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + ++match_txt; + do + { + if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0]) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + ++match_txt; + } + while (*match_txt != 0); + + if (width != 0 && (c = in_ch (s, &read_in)) != EOF && tolower (c) == 'i') + { + match_txt = "inity"; + + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + ++match_txt; + + do + { + if (width == 0 || (c = in_ch (s, &read_in)) == EOF || tolower (c) != match_txt[0]) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + ++match_txt; + } + while (*match_txt != 0); + } + else if (width != 0 && c != EOF) + back_ch (c, s, &read_in, 0); + } + else + { + not_in = 'e'; + if (width != 0 && c == '0') + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + c = in_ch (s, &read_in); + if (width > 0) + --width; + if (width != 0 && tolower (c) == 'x') + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + flags |= IS_HEX_FLOAT; + not_in = 'p'; + + flags &= ~USE_GROUP; + c = in_ch (s, &read_in); + if (width > 0) + --width; + } + } + + while (1) + { + if (isdigit (c) || (!seen_exp && (flags & IS_HEX_FLOAT) != 0 && isxdigit (c)) + || (seen_exp && wbuf[wbuf_cur_sz - 1] == not_in && (c == '-' || c == '+'))) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + } + else if (wbuf_cur_sz > 0 && !seen_exp && (char) tolower (c) == not_in) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = not_in; + seen_exp = seen_dot = 1; + } + else + { + const char *p = lc_decimal_point; + int remain = width > 0 ? width : INT_MAX; + + if (! seen_dot) + { + while ((unsigned char) *p == c && remain >= 0) + { + ++p; + if (*p == 0 || !remain || (c = in_ch (s, &read_in)) == EOF) + break; + --remain; + } + } + + if (*p == 0) + { + for (p = lc_decimal_point; *p != 0; ++p) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = (unsigned char) *p; + } + if (width > 0) + width = remain; + seen_dot = 1; + } + else + { + const char *pp = lc_thousands_sep; + + if (!seen_dot && (flags & USE_GROUP) != 0) + { + while ((pp - lc_thousands_sep) < (p - lc_decimal_point) + && *pp == lc_decimal_point[(pp - lc_thousands_sep)]) + ++pp; + if ((pp - lc_thousands_sep) == (p - lc_decimal_point)) + { + while ((unsigned char) *pp == c && remain >= 0) + { + ++pp; + if (*pp == 0 || !remain || (c = in_ch (s, &read_in)) == EOF) + break; + --remain; + } + } + } + + if (pp != NULL && *pp == 0) + { + /* As our conversion routines aren't supporting thousands + separators, we are filtering them here. */ + if (width > 0) + width = remain; + } + else + { + back_ch (c, s, &read_in, 0); + break; + } + } + } + + if (width == 0 || (c = in_ch (s, &read_in)) == EOF) + break; + + if (width > 0) + --width; + } + + if (!wbuf_cur_sz || ((flags & IS_HEX_FLOAT) != 0 && wbuf_cur_sz == 2)) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = 0; + + if ((flags & IS_LL) != 0) + { + long double ld; + ld = __mingw_strtold (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); + if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) + *(npos != 0 ? (long double *) get_va_nth (argp, npos) : va_arg (arg, long double *)) = is_neg ? -ld : ld; + } + else if ((flags & IS_L) != 0) + { + double d; + d = (double) __mingw_strtold (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); + if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) + *(npos != 0 ? (double *) get_va_nth (argp, npos) : va_arg (arg, double *)) = is_neg ? -d : d; + } + else + { + float d = __mingw_strtof (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); + if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) + *(npos != 0 ? (float *) get_va_nth (argp, npos) : va_arg (arg, float *)) = is_neg ? -d : d; + } + + if (wbuf == tmp_wbuf_ptr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + ++rval; + break; + + case '[': + if ((flags & IS_L) != 0) + { + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + str_sz = 100; + *pstr = (char *) malloc (100 * sizeof (wchar_t)); + + if ((wstr = (wchar_t *) *pstr) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + wstr = (wchar_t *) get_va_nth (argp, npos); + else + wstr = va_arg (arg, wchar_t *); + if (!wstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + } + else if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + str_sz = 100; + if ((str = *pstr = (char *) malloc (100)) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? EOF : rval), &gcollect, pstr, &wbuf); + + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + str = (char *) get_va_nth (argp, npos); + else + str = va_arg (arg, char *); + if (!str) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + not_in = (*f == '^' ? 1 : 0); + if (*f == '^') + f++; + + if (width < 0) + width = INT_MAX; + + if (wbuf_max_sz < 256) + { + wbuf_max_sz = 256; + if (wbuf) + free (wbuf); + wbuf = (char *) malloc (wbuf_max_sz); + } + memset (wbuf, 0, 256); + + fc = *f; + if (fc == ']' || fc == '-') + { + wbuf[fc] = 1; + ++f; + } + + while ((fc = *f++) != 0 && fc != ']') + { + if (fc == '-' && *f != 0 && *f != ']' && (unsigned char) f[-2] <= (unsigned char) *f) + { + for (fc = (unsigned char) f[-2]; fc < (unsigned char) *f; ++fc) + wbuf[fc] = 1; + } + else + wbuf[fc] = 1; + } + + if (!fc) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_L) != 0) + { + read_in_sv = read_in; + cnt = 0; + + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + memset (&cstate, 0, sizeof (cstate)); + + do + { + if (wbuf[c] == not_in) + { + back_ch (c, s, &read_in, 1); + break; + } + + if ((flags & IS_SUPPRESSED) == 0) + { + buf[0] = c; + n = mbrtowc (wstr, buf, 1, &cstate); + + if (n == (size_t) -2) + { + ++cnt; + continue; + } + cnt = 0; + + ++wstr; + if ((flags & IS_ALLOC_USED) != 0 && wstr == ((wchar_t *) *pstr + str_sz)) + { + new_sz = str_sz * 2; + while ((wstr = (wchar_t *) realloc (*pstr, new_sz * sizeof (wchar_t))) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!wstr) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + ((wchar_t *) (*pstr))[str_sz - 1] = 0; + pstr = NULL; + ++rval; + } + else + rval = EOF; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + *pstr = (char *) wstr; + wstr += str_sz; + str_sz = new_sz; + } + } + + if (--width <= 0) + break; + } + while ((c = in_ch (s, &read_in)) != EOF); + + if (cnt != 0) + { + errno = EILSEQ; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + if (read_in_sv == read_in) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + + if ((flags & IS_SUPPRESSED) == 0) + { + *wstr++ = 0; + optimize_alloc (pstr, (char *) wstr, str_sz * sizeof (wchar_t)); + pstr = NULL; + ++rval; + } + } + else + { + read_in_sv = read_in; + + if ((c = in_ch (s, &read_in)) == EOF) + return cleanup_return ((!rval ? EOF : rval), &gcollect, pstr, &wbuf); + + do + { + if (wbuf[c] == not_in) + { + back_ch (c, s, &read_in, 1); + break; + } + + if ((flags & IS_SUPPRESSED) == 0) + { + *str++ = c; + if ((flags & IS_ALLOC_USED) != 0 && str == (*pstr + str_sz)) + { + new_sz = str_sz * 2; + + while ((str = (char *) realloc (*pstr, new_sz)) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!str) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + (*pstr)[str_sz - 1] = 0; + pstr = NULL; + ++rval; + } + else + rval = EOF; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + *pstr = str; + str += str_sz; + str_sz = new_sz; + } + } + } + while (--width > 0 && (c = in_ch (s, &read_in)) != EOF); + + if (read_in_sv == read_in) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + { + *str++ = 0; + optimize_alloc (pstr, str, str_sz); + pstr = NULL; + ++rval; + } + } + break; + + default: + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if (ignore_ws) + { + while (isspace ((c = in_ch (s, &read_in)))); + back_ch (c, s, &read_in, 0); + } + + return cleanup_return (rval, &gcollect, pstr, &wbuf); +} + +int +__mingw_vfscanf (FILE *s, const char *format, va_list argp) +{ + _IFP ifp; + memset (&ifp, 0, sizeof (_IFP)); + ifp.fp = s; + return __mingw_sformat (&ifp, format, argp); +} + +int +__mingw_vsscanf (const char *s, const char *format, va_list argp) +{ + _IFP ifp; + memset (&ifp, 0, sizeof (_IFP)); + ifp.str = s; + ifp.is_string = 1; + return __mingw_sformat (&ifp, format, argp); +} + diff --git a/libc/mingw/stdio/mingw_vprintf.c b/libc/mingw/stdio/mingw_vprintf.c new file mode 100644 index 000000000..4098d49d1 --- /dev/null +++ b/libc/mingw/stdio/mingw_vprintf.c @@ -0,0 +1,58 @@ +/* vprintf.c + * + * $Id: vprintf.c,v 1.1 2008/08/11 22:41:55 keithmarshall Exp $ + * + * Provides an implementation of the "vprintf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, whence it may replace the Microsoft + * function of the same name. + * + * Written by Keith Marshall + * + * This implementation of "vprintf" will normally be invoked by calling + * "__mingw_vprintf()" in preference to a direct reference to "vprintf()" + * itself; this leaves the MSVCRT implementation as the default, which + * will be deployed when user code invokes "vprint()". Users who then + * wish to use this implementation may either call "__mingw_vprintf()" + * directly, or may use conditional preprocessor defines, to redirect + * references to "vprintf()" to "__mingw_vprintf()". + * + * Compiling this module with "-D INSTALL_AS_DEFAULT" will change this + * recommended convention, such that references to "vprintf()" in user + * code will ALWAYS be redirected to "__mingw_vprintf()"; if this option + * is adopted, then users wishing to use the MSVCRT implementation of + * "vprintf()" will be forced to use a "back-door" mechanism to do so. + * Such a "back-door" mechanism is provided with MinGW, allowing the + * MSVCRT implementation to be called as "__msvcrt_vprintf()"; however, + * since users may not expect this behaviour, a standard libmingwex.a + * installation does not employ this option. + * + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __vprintf (const APICHAR *, va_list) __MINGW_NOTHROW; + +int __cdecl __vprintf(const APICHAR *fmt, va_list argv) +{ + register int retval; + + _lock_file( stdout ); + retval = __pformat( PFORMAT_TO_FILE | PFORMAT_NOLIMIT, stdout, 0, fmt, argv ); + _unlock_file( stdout ); + + return retval; +} diff --git a/libc/mingw/stdio/mingw_vprintfw.c b/libc/mingw/stdio/mingw_vprintfw.c new file mode 100644 index 000000000..2c81073e6 --- /dev/null +++ b/libc/mingw/stdio/mingw_vprintfw.c @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 + +#include "mingw_vprintf.c" + diff --git a/libc/mingw/stdio/mingw_vsnprintf.c b/libc/mingw/stdio/mingw_vsnprintf.c new file mode 100644 index 000000000..b477300f9 --- /dev/null +++ b/libc/mingw/stdio/mingw_vsnprintf.c @@ -0,0 +1,52 @@ +/* vsnprintf.c + * + * $Id: vsnprintf.c,v 1.3 2008/07/28 23:24:20 keithmarshall Exp $ + * + * Provides an implementation of the "vsnprintf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, replacing the redirection through + * libmoldnames.a, to the MSVCRT standard "_vsnprintf" function; (the + * standard MSVCRT function remains available, and may be invoked + * directly, using this fully qualified form of its name). + * + * Written by Keith Marshall + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ + +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __vsnprintf (APICHAR *, size_t, const APICHAR *fmt, va_list) __MINGW_NOTHROW; +int __cdecl __vsnprintf(APICHAR *buf, size_t length, const APICHAR *fmt, va_list argv ) +{ + register int retval; + + if( length == (size_t)(0) ) + /* + * No buffer; simply compute and return the size required, + * without actually emitting any data. + */ + return __pformat( 0, buf, 0, fmt, argv); + + /* If we get to here, then we have a buffer... + * Emit data up to the limit of buffer length less one, + * then add the requisite NUL terminator. + */ + retval = __pformat( 0, buf, --length, fmt, argv ); + buf[retval < (int) length ? retval : (int)length] = '\0'; + + return retval; +} + diff --git a/libc/mingw/stdio/mingw_vsnprintfw.c b/libc/mingw/stdio/mingw_vsnprintfw.c new file mode 100644 index 000000000..fb3dfa5e4 --- /dev/null +++ b/libc/mingw/stdio/mingw_vsnprintfw.c @@ -0,0 +1,9 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 + +#include "mingw_vsnprintf.c" + diff --git a/libc/mingw/stdio/mingw_vsprintf.c b/libc/mingw/stdio/mingw_vsprintf.c new file mode 100644 index 000000000..af9793d38 --- /dev/null +++ b/libc/mingw/stdio/mingw_vsprintf.c @@ -0,0 +1,54 @@ +/* vsprintf.c + * + * $Id: vsprintf.c,v 1.1 2008/08/11 22:41:55 keithmarshall Exp $ + * + * Provides an implementation of the "vsprintf" function, conforming + * generally to C99 and SUSv3/POSIX specifications, with extensions + * to support Microsoft's non-standard format specifications. This + * is included in libmingwex.a, whence it may replace the Microsoft + * function of the same name. + * + * Written by Keith Marshall + * + * This implementation of "vsprintf" will normally be invoked by calling + * "__mingw_vsprintf()" in preference to a direct reference to "vsprintf()" + * itself; this leaves the MSVCRT implementation as the default, which + * will be deployed when user code invokes "vsprint()". Users who then + * wish to use this implementation may either call "__mingw_vsprintf()" + * directly, or may use conditional preprocessor defines, to redirect + * references to "vsprintf()" to "__mingw_vsprintf()". + * + * Compiling this module with "-D INSTALL_AS_DEFAULT" will change this + * recommended convention, such that references to "vsprintf()" in user + * code will ALWAYS be redirected to "__mingw_vsprintf()"; if this option + * is adopted, then users wishing to use the MSVCRT implementation of + * "vsprintf()" will be forced to use a "back-door" mechanism to do so. + * Such a "back-door" mechanism is provided with MinGW, allowing the + * MSVCRT implementation to be called as "__msvcrt_vsprintf()"; however, + * since users may not expect this behaviour, a standard libmingwex.a + * installation does not employ this option. + * + * + * This is free software. You may redistribute and/or modify it as you + * see fit, without restriction of copyright. + * + * This software is provided "as is", in the hope that it may be useful, + * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of + * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no + * time will the author accept any form of liability for any damages, + * however caused, resulting from the use of this software. + * + */ +#include +#include + +#include "mingw_pformat.h" + +int __cdecl __vsprintf (APICHAR *, const APICHAR *, va_list) __MINGW_NOTHROW; + +int __cdecl __vsprintf(APICHAR *buf, const APICHAR *fmt, va_list argv) +{ + register int retval; + buf[retval = __pformat( PFORMAT_NOLIMIT, buf, 0, fmt, argv )] = '\0'; + return retval; +} diff --git a/libc/mingw/stdio/mingw_vsprintfw.c b/libc/mingw/stdio/mingw_vsprintfw.c new file mode 100644 index 000000000..fd8808bf4 --- /dev/null +++ b/libc/mingw/stdio/mingw_vsprintfw.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __BUILD_WIDEAPI 1 +#define _CRT_NON_CONFORMING_SWPRINTFS 1 + +#include "mingw_vsprintf.c" + diff --git a/libc/mingw/stdio/mingw_wscanf.c b/libc/mingw/stdio/mingw_wscanf.c new file mode 100644 index 000000000..6202a79b5 --- /dev/null +++ b/libc/mingw/stdio/mingw_wscanf.c @@ -0,0 +1,28 @@ +#include +#include +#include + +extern int __mingw_vfwscanf (FILE *stream, const wchar_t *format, va_list argp); + +int __mingw_wscanf (const wchar_t *format, ...); +int __mingw_vwscanf (const wchar_t *format, va_list argp); + +int +__mingw_wscanf (const wchar_t *format, ...) +{ + va_list argp; + int r; + + va_start (argp, format); + r = __mingw_vfwscanf (stdin, format, argp); + va_end (argp); + + return r; +} + +int +__mingw_vwscanf (const wchar_t *format, va_list argp) +{ + return __mingw_vfwscanf (stdin, format, argp); +} + diff --git a/libc/mingw/stdio/mingw_wvfscanf.c b/libc/mingw/stdio/mingw_wvfscanf.c new file mode 100644 index 000000000..045aba791 --- /dev/null +++ b/libc/mingw/stdio/mingw_wvfscanf.c @@ -0,0 +1,1623 @@ +/* + This Software is provided under the Zope Public License (ZPL) Version 2.1. + + Copyright (c) 2011 by the mingw-w64 project + + See the AUTHORS file for the list of contributors to the mingw-w64 project. + + This license has been certified as open source. It has also been designated + as GPL compatible by the Free Software Foundation (FSF). + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions in source code must retain the accompanying copyright + notice, this list of conditions, and the following disclaimer. + 2. Redistributions in binary form must reproduce the accompanying + copyright notice, this list of conditions, and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + 3. Names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission + from the copyright holders. + 4. The right to distribute this software or to use it for any purpose does + not give you the right to use Servicemarks (sm) or Trademarks (tm) of + the copyright holders. Use of them is covered by separate agreement + with the copyright holders. + 5. If any files are modified, you must cause the modified files to carry + prominent notices stating that you changed the files and the date of + any change. + + Disclaimer + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESSED + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef CP_UTF8 +#define CP_UTF8 65001 +#endif + +#ifndef MB_ERR_INVALID_CHARS +#define MB_ERR_INVALID_CHARS 0x00000008 +#endif + +/* Helper flags for conversion. */ +#define IS_C 0x0001 +#define IS_S 0x0002 +#define IS_L 0x0004 +#define IS_LL 0x0008 +#define IS_SIGNED_NUM 0x0010 +#define IS_POINTER 0x0020 +#define IS_HEX_FLOAT 0x0040 +#define IS_SUPPRESSED 0x0080 +#define USE_GROUP 0x0100 +#define USE_GNU_ALLOC 0x0200 +#define USE_POSIX_ALLOC 0x0400 + +#define IS_ALLOC_USED (USE_GNU_ALLOC | USE_POSIX_ALLOC) + +/* internal stream structure with back-buffer. */ +typedef struct _IFP +{ + __extension__ union { + void *fp; + const wchar_t *str; + }; + int bch[1024]; + int is_string : 1; + int back_top; + int seen_eof : 1; +} _IFP; + +static void * +get_va_nth (va_list argp, unsigned int n) +{ + va_list ap; + if (!n) + abort (); + va_copy (ap, argp); + while (--n > 0) + (void) va_arg(ap, void *); + return va_arg (ap, void *); +} + +static void +optimize_alloc (int do_realloc, char **p, size_t sz, size_t need_sz, size_t typ_sz) +{ + char *h; + + if (!do_realloc || sz == need_sz || !p || *p == NULL) + return; + if ((h = (char *) realloc (*p, need_sz * typ_sz)) != NULL) + *p = h; +} + +static void +back_ch (int c, _IFP *s, size_t *rin, int not_eof) +{ + if (!not_eof && c == WEOF) + return; + if (s->is_string == 0) + { + FILE *fp = s->fp; + ungetwc (c, fp); + rin[0] -= 1; + return; + } + rin[0] -= 1; + s->bch[s->back_top] = c; + s->back_top += 1; +} + +static int +in_ch (_IFP *s, size_t *rin) +{ + int r; + if (s->back_top) + { + s->back_top -= 1; + r = s->bch[s->back_top]; + rin[0] += 1; + } + else if (s->seen_eof) + { + return WEOF; + } + else if (s->is_string) + { + const wchar_t *ps = s->str; + r = ((int) *ps) & 0xffff; + ps++; + if (r != 0) + { + rin[0] += 1; + s->str = ps; + return r; + } + s->seen_eof = 1; + return WEOF; + } + else + { + FILE *fp = (FILE *) s->fp; + r = getwc (fp); + if (r != WEOF) + rin[0] += 1; + else s->seen_eof = 1; + } + return r; +} + +static int +match_string (_IFP *s, size_t *rin, wint_t *c, const wchar_t *str) +{ + int ch = *c; + + if (*str == 0) + return 1; + + if (*str != (wchar_t) towlower (ch)) + return 0; + ++str; + while (*str != 0) + { + if ((ch = in_ch (s, rin)) == WEOF) + { + c[0] = ch; + return 0; + } + + if (*str != (wchar_t) towlower (ch)) + { + c[0] = ch; + return 0; + } + ++str; + } + c[0] = ch; + return 1; +} + +struct gcollect +{ + size_t count; + struct gcollect *next; + char **ptrs[32]; +}; + +static void +release_ptrs (struct gcollect **pt, wchar_t **wbuf) +{ + struct gcollect *pf; + size_t cnt; + + if (wbuf) + { + free (*wbuf); + *wbuf = NULL; + } + if (!pt || (pf = *pt) == NULL) + return; + while (pf != NULL) + { + struct gcollect *pf_sv = pf; + for (cnt = 0; cnt < pf->count; ++cnt) + { + free (*pf->ptrs[cnt]); + *pf->ptrs[cnt] = NULL; + } + pf = pf->next; + free (pf_sv); + } + *pt = NULL; +} + +static int +cleanup_return (int rval, struct gcollect **pfree, char **strp, wchar_t **wbuf) +{ + if (rval == WEOF) + release_ptrs (pfree, wbuf); + else + { + if (pfree) + { + struct gcollect *pf = *pfree, *pf_sv; + while (pf != NULL) + { + pf_sv = pf; + pf = pf->next; + free (pf_sv); + } + *pfree = NULL; + } + if (strp != NULL) + { + free (*strp); + *strp = NULL; + } + if (wbuf) + { + free (*wbuf); + *wbuf = NULL; + } + } + return rval; +} + +static struct gcollect * +resize_gcollect (struct gcollect *pf) +{ + struct gcollect *np; + if (pf && pf->count < 32) + return pf; + np = malloc (sizeof (struct gcollect)); + np->count = 0; + np->next = pf; + return np; +} + +static wchar_t * +resize_wbuf (size_t wpsz, size_t *wbuf_max_sz, wchar_t *old) +{ + wchar_t *wbuf; + size_t nsz; + if (*wbuf_max_sz != wpsz) + return old; + nsz = (256 > (2 * wbuf_max_sz[0]) ? 256 : (2 * wbuf_max_sz[0])); + if (!old) + wbuf = (wchar_t *) malloc (nsz * sizeof (wchar_t)); + else + wbuf = (wchar_t *) realloc (old, nsz * sizeof (wchar_t)); + if (!wbuf) + { + if (old) + free (old); + } + else + *wbuf_max_sz = nsz; + return wbuf; +} + +static int +__mingw_swformat (_IFP *s, const wchar_t *format, va_list argp) +{ + const wchar_t *f = format; + struct gcollect *gcollect = NULL; + size_t read_in = 0, wbuf_max_sz = 0; + ssize_t str_sz = 0; + char *str = NULL, **pstr = NULL;; + wchar_t *wstr = NULL, *wbuf = NULL; + wint_t c = 0, rval = 0; + int ignore_ws = 0; + va_list arg; + size_t wbuf_cur_sz, str_len, read_in_sv, new_sz, n; + unsigned int fc, npos; + int width, flags, base = 0, errno_sv, clen; + char seen_dot, seen_exp, is_neg, *nstr, buf[MB_LEN_MAX]; + wchar_t wc, not_in, *tmp_wbuf_ptr, *temp_wbuf_end, *wbuf_iter; + wint_t lc_decimal_point, lc_thousands_sep; + mbstate_t state; + union { + unsigned long long ull; + unsigned long ul; + long long ll; + long l; + } cv_val; + + arg = argp; + + if (!s || s->fp == NULL || !format) + { + errno = EINVAL; + return WEOF; + } + + memset (&state, 0, sizeof(state)); + clen = mbrtowc( &wc, localeconv()->decimal_point, 16, &state); + lc_decimal_point = (clen > 0 ? wc : '.'); + memset( &state, 0, sizeof( state ) ); + clen = mbrtowc( &wc, localeconv()->thousands_sep, 16, &state); + lc_thousands_sep = (clen > 0 ? wc : 0); + + while (*f != 0) + { + fc = *f++; + if (fc != '%') + { + if (iswspace (fc)) + ignore_ws = 1; + else + { + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + if (ignore_ws) + { + ignore_ws = 0; + if (iswspace (c)) + { + do + { + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + } + while (iswspace (c)); + } + } + + if (c != fc) + { + back_ch (c, s, &read_in, 0); + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + continue; + } + + width = flags = 0; + npos = 0; + wbuf_cur_sz = 0; + + if (iswdigit ((unsigned int) *f)) + { + const wchar_t *svf = f; + npos = (unsigned int) *f++ - '0'; + while (iswdigit ((unsigned int) *f)) + npos = npos * 10 + ((unsigned int) *f++ - '0'); + if (*f != '$') + { + npos = 0; + f = svf; + } + else + f++; + } + + do + { + if (*f == '*') + flags |= IS_SUPPRESSED; + else if (*f == '\'') + { + if (lc_thousands_sep) + flags |= USE_GROUP; + } + else if (*f == 'I') + { + /* we don't support locale's digits (i18N), but ignore it for now silently. */ + ; +#ifdef _WIN32 + if (f[1] == '6' && f[2] == '4') + { + flags |= IS_LL | IS_L; + f += 2; + } + else if (f[1] == '3' && f[2] == '2') + { + flags |= IS_L; + f += 2; + } + else + { +#ifdef _WIN64 + flags |= IS_LL | IS_L; +#else + flags |= IS_L; +#endif + } +#endif + } + else + break; + ++f; + } + while (1); + + while (iswdigit ((unsigned char) *f)) + width = width * 10 + ((unsigned char) *f++ - '0'); + + if (!width) + width = -1; + + switch (*f) + { + case 'h': + ++f; + flags |= (*f == 'h' ? IS_C : IS_S); + if (*f == 'h') + ++f; + break; + case 'l': + ++f; + flags |= (*f == 'l' ? IS_LL : 0) | IS_L; + if (*f == 'l') + ++f; + break; + case 'q': case 'L': + ++f; + flags |= IS_LL | IS_L; + break; + case 'a': + if (f[1] != 's' && f[1] != 'S' && f[1] != '[') + break; + ++f; + flags |= USE_GNU_ALLOC; + break; + case 'm': + flags |= USE_POSIX_ALLOC; + ++f; + if (*f == 'l') + { + flags |= IS_L; + ++f; + } + break; + case 'z': +#ifdef _WIN64 + flags |= IS_LL | IS_L; +#else + flags |= IS_L; +#endif + ++f; + break; + case 'j': + if (sizeof (uintmax_t) > sizeof (unsigned long)) + flags |= IS_LL; + else if (sizeof (uintmax_t) > sizeof (unsigned int)) + flags |= IS_L; + ++f; + break; + case 't': +#ifdef _WIN64 + flags |= IS_LL; +#else + flags |= IS_L; +#endif + ++f; + break; + case 0: + return cleanup_return (rval, &gcollect, pstr, &wbuf); + default: + break; + } + + if (*f == 0) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + fc = *f++; + if (ignore_ws || (fc != '[' && fc != 'c' && fc != 'C' && fc != 'n')) + { + errno_sv = errno; + errno = 0; + do + { + if ((c == WEOF || (c = in_ch (s, &read_in)) == WEOF) && errno == EINTR) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + } + while (iswspace (c)); + + ignore_ws = 0; + errno = errno_sv; + back_ch (c, s, &read_in, 0); + } + + switch (fc) + { + case 'c': + if ((flags & IS_L) != 0) + fc = 'C'; + break; + case 's': + if ((flags & IS_L) != 0) + fc = 'S'; + break; + } + + switch (fc) + { + case '%': + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + if (c != fc) + { + back_ch (c, s, &read_in, 1); + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + break; + + case 'n': + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_LL) != 0) + *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = read_in; + else if ((flags & IS_L) != 0) + *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = read_in; + else if ((flags & IS_S) != 0) + *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = read_in; + else if ((flags & IS_C) != 0) + *(npos != 0 ? (char *) get_va_nth (argp, npos) : va_arg (arg, char *)) = read_in; + else + *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = read_in; + } + break; + + case 'c': + if (width == -1) + width = 1; + + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + str_sz = 100; + if ((str = *pstr = (char *) malloc (100)) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + str = (char *) get_va_nth (argp, npos); + else + str = va_arg (arg, char *); + if (!str) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + memset (&state, 0, sizeof (state)); + + do + { + if ((flags & IS_SUPPRESSED) == 0 && (flags & USE_POSIX_ALLOC) != 0 + && (str + MB_CUR_MAX) >= (*pstr + str_sz)) + { + new_sz = str_sz * 2; + str_len = (str - *pstr); + while ((nstr = (char *) realloc (*pstr, new_sz)) == NULL + && new_sz > (str_len + MB_CUR_MAX)) + new_sz = str_len + MB_CUR_MAX; + if (!nstr) + { + release_ptrs (&gcollect, &wbuf); + return WEOF; + } + *pstr = nstr; + str = nstr + str_len; + str_sz = new_sz; + } + + n = wcrtomb ((flags & IS_SUPPRESSED) == 0 ? str : NULL, c, &state); + if (n == (size_t) -1LL) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + str += n; + } + while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); + + if ((flags & IS_SUPPRESSED) == 0) + { + optimize_alloc ((flags & IS_ALLOC_USED) != 0, pstr, str_sz, (str - *pstr), sizeof (char)); + pstr = NULL; + ++rval; + } + + break; + + case 'C': + if (width == -1) + width = 1; + + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + str_sz = (width > 1024 ? 1024 : width); + *pstr = (char *) malloc (str_sz * sizeof (wchar_t)); + if ((wstr = (wchar_t *) *pstr) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + + if ((wstr = (wchar_t *) *pstr) != NULL) + { + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + } + else + { + if (npos != 0) + wstr = (wchar_t *) get_va_nth (argp, npos); + else + wstr = va_arg (arg, wchar_t *); + if (!wstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + { + do + { + if ((flags & IS_ALLOC_USED) != 0 + && wstr == ((wchar_t *) *pstr + str_sz)) + { + new_sz = str_sz + (str_sz > width ? width - 1 : str_sz); + while ((wstr = (wchar_t *) realloc (*pstr, + new_sz * sizeof (wchar_t))) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!wstr) + { + release_ptrs (&gcollect, &wbuf); + return WEOF; + } + *pstr = (char *) wstr; + wstr += str_sz; + str_sz = new_sz; + } + *wstr++ = c; + } + while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); + } + else + { + while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); + } + + if ((flags & IS_SUPPRESSED) == 0) + { + optimize_alloc ((flags & IS_ALLOC_USED) != 0, pstr, str_sz, (wstr - (wchar_t *) *pstr), sizeof (wchar_t)); + pstr = NULL; + ++rval; + } + break; + + case 's': + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + str_sz = 100; + if ((str = *pstr = (char *) malloc (100)) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + str = (char *) get_va_nth (argp, npos); + else + str = va_arg (arg, char *); + if (!str) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + memset (&state, 0, sizeof (state)); + + do + { + if (iswspace (c)) + { + back_ch (c, s, &read_in, 1); + break; + } + + { + if ((flags & IS_SUPPRESSED) == 0 && (flags & IS_ALLOC_USED) != 0 + && (str + MB_CUR_MAX) >= (*pstr + str_sz)) + { + new_sz = str_sz * 2; + str_len = (str - *pstr); + + while ((nstr = (char *) realloc (*pstr, new_sz)) == NULL + && new_sz > (str_len + MB_CUR_MAX)) + new_sz = str_len + MB_CUR_MAX; + if (!nstr) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + (*pstr)[str_len] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = nstr; + str = nstr + str_len; + str_sz = new_sz; + } + + n = wcrtomb ((flags & IS_SUPPRESSED) == 0 ? str : NULL, c, + &state); + if (n == (size_t) -1LL) + { + errno = EILSEQ; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + str += n; + } + } + while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != WEOF); + + if ((flags & IS_SUPPRESSED) == 0) + { + n = wcrtomb (buf, 0, &state); + if (n > 0 && (flags & IS_ALLOC_USED) != 0 + && (str + n) >= (*pstr + str_sz)) + { + str_len = (str - *pstr); + + if ((nstr = (char *) realloc (*pstr, str_len + n + 1)) == NULL) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + (*pstr)[str_len] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = nstr; + str = nstr + str_len; + str_sz = str_len + n + 1; + } + + if (n) + { + memcpy (str, buf, n); + str += n; + } + *str++ = 0; + + optimize_alloc ((flags & IS_ALLOC_USED) != 0, pstr, str_sz, (str - *pstr), sizeof (char)); + pstr = NULL; + ++rval; + } + break; + + case 'S': + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + str_sz = 100; + *pstr = (char *) malloc (100 * sizeof (wchar_t)); + if ((wstr = (wchar_t *) *pstr) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + wstr = (wchar_t *) get_va_nth (argp, npos); + else + wstr = va_arg (arg, wchar_t *); + if (!wstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + do + { + if (iswspace (c)) + { + back_ch (c, s, &read_in, 1); + break; + } + + if ((flags & IS_SUPPRESSED) == 0) + { + *wstr++ = c; + if ((flags & IS_ALLOC_USED) != 0 && wstr == ((wchar_t *) *pstr + str_sz)) + { + new_sz = str_sz * 2; + + while ((wstr = (wchar_t *) realloc (*pstr, + new_sz * sizeof (wchar_t))) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!wstr) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + ((wchar_t *) (*pstr))[str_sz - 1] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = (char *) wstr; + wstr += str_sz; + str_sz = new_sz; + } + } + } + while ((width <= 0 || --width > 0) && (c = in_ch (s, &read_in)) != WEOF); + + if ((flags & IS_SUPPRESSED) == 0) + { + *wstr++ = 0; + + optimize_alloc ((flags & IS_ALLOC_USED) != 0, pstr, str_sz, (wstr - (wchar_t *) *pstr), sizeof (wchar_t)); + pstr = NULL; + ++rval; + } + break; + + case 'd': case 'i': + case 'o': case 'p': + case 'u': + case 'x': case 'X': + switch (fc) + { + case 'd': + flags |= IS_SIGNED_NUM; + base = 10; + break; + case 'i': + flags |= IS_SIGNED_NUM; + base = 0; + break; + case 'o': + base = 8; + break; + case 'p': + base = 16; + flags &= ~(IS_S | IS_LL | IS_L); + #ifdef _WIN64 + flags |= IS_LL; + #endif + flags |= IS_L | IS_POINTER; + break; + case 'u': + base = 10; + break; + case 'x': case 'X': + base = 16; + break; + } + + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + if (c == '+' || c == '-') + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + if (width > 0) + --width; + c = in_ch (s, &read_in); + } + + if (width != 0 && c == '0') + { + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + c = in_ch (s, &read_in); + + if (width != 0 && towlower (c) == 'x') + { + if (!base) + base = 16; + if (base == 16) + { + if (width > 0) + --width; + c = in_ch (s, &read_in); + } + } + else if (!base) + base = 8; + } + + if (!base) + base = 10; + + while (c != WEOF && width != 0) + { + if (base == 16) + { + if (!iswxdigit (c)) + break; + } + else if (!iswdigit (c) || (int) (c - '0') >= base) + { + if (base != 10 || (flags & USE_GROUP) == 0 || c != lc_thousands_sep) + break; + } + if (c != lc_thousands_sep) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + } + + if (width > 0) + --width; + + c = in_ch (s, &read_in); + } + + if (!wbuf_cur_sz || (wbuf_cur_sz == 1 && (wbuf[0] == '+' || wbuf[0] == '-'))) + { + if (!wbuf_cur_sz && (flags & IS_POINTER) != 0 + && match_string (s, &read_in, &c, L"(nil)")) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = '0'; + } + else + { + back_ch (c, s, &read_in, 0); + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + else + back_ch (c, s, &read_in, 0); + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = 0; + + if ((flags & IS_LL) != 0) + { + if ((flags & IS_SIGNED_NUM) != 0) + cv_val.ll = wcstoll (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); + else + cv_val.ull = wcstoull (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); + } + else + { + if ((flags & IS_SIGNED_NUM) != 0) + cv_val.l = wcstol (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); + else + cv_val.ul = wcstoul (wbuf, &tmp_wbuf_ptr, base/*, flags & USE_GROUP*/); + } + if (wbuf == tmp_wbuf_ptr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_SIGNED_NUM) != 0) + { + if ((flags & IS_LL) != 0) + *(npos != 0 ? (long long *) get_va_nth (argp, npos) : va_arg (arg, long long *)) = cv_val.ll; + else if ((flags & IS_L) != 0) + *(npos != 0 ? (long *) get_va_nth (argp, npos) : va_arg (arg, long *)) = cv_val.l; + else if ((flags & IS_S) != 0) + *(npos != 0 ? (short *) get_va_nth (argp, npos) : va_arg (arg, short *)) = (short) cv_val.l; + else if ((flags & IS_C) != 0) + *(npos != 0 ? (signed char *) get_va_nth (argp, npos) : va_arg (arg, signed char *)) = (signed char) cv_val.ul; + else + *(npos != 0 ? (int *) get_va_nth (argp, npos) : va_arg (arg, int *)) = (int) cv_val.l; + } + else + { + if ((flags & IS_LL) != 0) + *(npos != 0 ? (unsigned long long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long long *)) = cv_val.ull; + else if ((flags & IS_L) != 0) + *(npos != 0 ? (unsigned long *) get_va_nth (argp, npos) : va_arg (arg, unsigned long *)) = cv_val.ul; + else if ((flags & IS_S) != 0) + *(npos != 0 ? (unsigned short *) get_va_nth (argp, npos) : va_arg (arg, unsigned short *)) + = (unsigned short) cv_val.ul; + else if ((flags & IS_C) != 0) + *(npos != 0 ? (unsigned char *) get_va_nth (argp, npos) : va_arg (arg, unsigned char *)) = (unsigned char) cv_val.ul; + else + *(npos != 0 ? (unsigned int *) get_va_nth (argp, npos) : va_arg (arg, unsigned int *)) = (unsigned int) cv_val.ul; + } + ++rval; + } + break; + + case 'e': case 'E': + case 'f': case 'F': + case 'g': case 'G': + case 'a': case 'A': + if (width > 0) + --width; + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + seen_dot = seen_exp = 0; + is_neg = (c == '-' ? 1 : 0); + + if (c == '-' || c == '+') + { + if (width == 0 || (c = in_ch (s, &read_in)) == WEOF) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + if (width > 0) + --width; + } + + if (towlower (c) == 'n') + { + const wchar_t *match_txt = L"nan"; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + ++match_txt; + do + { + if (width == 0 || (c = in_ch (s, &read_in)) == WEOF + || towlower (c) != match_txt[0]) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + ++match_txt; + } + while (*match_txt != 0); + } + else if (towlower (c) == 'i') + { + const wchar_t *match_txt = L"inf"; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + ++match_txt; + do + { + if (width == 0 || (c = in_ch (s, &read_in)) == WEOF + || towlower (c) != match_txt[0]) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + ++match_txt; + } + while (*match_txt != 0); + + if (width != 0 && (c = in_ch (s, &read_in)) != WEOF && towlower (c) == 'i') + { + match_txt = L"inity"; + if (width > 0) + --width; + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + ++match_txt; + do + { + if (width == 0 || (c = in_ch (s, &read_in)) == WEOF + || towlower (c) != match_txt[0]) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + if (width > 0) + --width; + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + ++match_txt; + } + while (*match_txt != 0); + } + else if (width != 0 && c != WEOF) + back_ch (c, s, &read_in, 0); + } + else + { + not_in = 'e'; + if (width != 0 && c == '0') + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + c = in_ch (s, &read_in); + if (width > 0) + --width; + if (width != 0 && towlower (c) == 'x') + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + flags |= IS_HEX_FLOAT; + not_in = 'p'; + + flags &= ~USE_GROUP; + c = in_ch (s, &read_in); + if (width > 0) + --width; + } + } + + while (1) + { + if (iswdigit (c)) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + } + else if (!seen_exp && (flags & IS_HEX_FLOAT) != 0 && iswxdigit (c)) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + } + else if (seen_exp && wbuf[wbuf_cur_sz - 1] == not_in + && (c == '-' || c == '+')) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + } + else if (wbuf_cur_sz > 0 && !seen_exp + && (wchar_t) towlower (c) == not_in) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = not_in; + + seen_exp = seen_dot = 1; + } + else + { + if (!seen_dot && c == lc_decimal_point) + { + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = c; + + seen_dot = 1; + } + else if ((flags & USE_GROUP) != 0 && !seen_dot && c == lc_thousands_sep) + { + /* As our conversion routines aren't supporting thousands + separators, we are filtering them here. */ + } + else + { + back_ch (c, s, &read_in, 0); + break; + } + } + + if (width == 0 || (c = in_ch (s, &read_in)) == WEOF) + break; + + if (width > 0) + --width; + } + + if (wbuf_cur_sz == 0 || ((flags & IS_HEX_FLOAT) != 0 && wbuf_cur_sz == 2)) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + wbuf = resize_wbuf (wbuf_cur_sz, &wbuf_max_sz, wbuf); + wbuf[wbuf_cur_sz++] = 0; + + if ((flags & IS_LL) != 0) + { + long double d = __mingw_wcstold (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); + if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) + *(npos != 0 ? (long double *) get_va_nth (argp, npos) : va_arg (arg, long double *)) = is_neg ? -d : d; + } + else if ((flags & IS_L) != 0) + { + double d = __mingw_wcstod (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); + if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) + *(npos != 0 ? (double *) get_va_nth (argp, npos) : va_arg (arg, double *)) = is_neg ? -d : d; + } + else + { + float d = __mingw_wcstof (wbuf, &tmp_wbuf_ptr/*, flags & USE_GROUP*/); + if ((flags & IS_SUPPRESSED) == 0 && tmp_wbuf_ptr != wbuf) + *(npos != 0 ? (float *) get_va_nth (argp, npos) : va_arg (arg, float *)) = is_neg ? -d : d; + } + + if (wbuf == tmp_wbuf_ptr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + ++rval; + break; + + case '[': + if ((flags & IS_L) != 0) + { + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + str_sz = 100; + *pstr = (char *) malloc (100 * sizeof (wchar_t)); + if ((wstr = (wchar_t *) *pstr) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + wstr = (wchar_t *) get_va_nth (argp, npos); + else + wstr = va_arg (arg, wchar_t *); + if (!wstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + } + else if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0) + { + if (npos != 0) + pstr = (char **) get_va_nth (argp, npos); + else + pstr = va_arg (arg, char **); + + if (!pstr) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + str_sz = 100; + if ((str = *pstr = (char *) malloc (100)) == NULL) + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + gcollect = resize_gcollect (gcollect); + gcollect->ptrs[gcollect->count++] = pstr; + } + else + { + if (npos != 0) + str = (char *) get_va_nth (argp, npos); + else + str = va_arg (arg, char *); + if (!str) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + not_in = (*f == '^' ? 1 : 0); + if (*f == '^') + f++; + + if (width < 0) + width = INT_MAX; + + tmp_wbuf_ptr = (wchar_t *) f; + + if (*f == L']') + ++f; + + while ((fc = *f++) != 0 && fc != L']'); + + if (fc == 0) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + temp_wbuf_end = (wchar_t *) f - 1; + + if ((flags & IS_L) != 0) + { + read_in_sv = read_in; + + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + do + { + int ended = 0; + for (wbuf_iter = tmp_wbuf_ptr; wbuf_iter < temp_wbuf_end;) + { + if (wbuf_iter[0] == '-' && wbuf_iter[1] != 0 + && (wbuf_iter + 1) != temp_wbuf_end + && wbuf_iter != tmp_wbuf_ptr + && (unsigned int) wbuf_iter[-1] <= (unsigned int) wbuf_iter[1]) + { + for (wc = wbuf_iter[-1] + 1; wc <= wbuf_iter[1] && (wint_t) wc != c; ++wc); + + if (wc <= wbuf_iter[1] && !not_in) + break; + if (wc <= wbuf_iter[1] && not_in) + { + back_ch (c, s, &read_in, 0); + ended = 1; + break; + } + + wbuf_iter += 2; + } + else + { + if ((wint_t) *wbuf_iter == c && !not_in) + break; + if ((wint_t) *wbuf_iter == c && not_in) + { + back_ch (c, s, &read_in, 0); + ended = 1; + break; + } + + ++wbuf_iter; + } + } + if (ended) + break; + + if (wbuf_iter == temp_wbuf_end && !not_in) + { + back_ch (c, s, &read_in, 0); + break; + } + + if ((flags & IS_SUPPRESSED) == 0) + { + *wstr++ = c; + + if ((flags & IS_ALLOC_USED) != 0 + && wstr == ((wchar_t *) *pstr + str_sz)) + { + new_sz = str_sz * 2; + while ((wstr = (wchar_t *) realloc (*pstr, + new_sz * sizeof (wchar_t))) == NULL + && new_sz > (size_t) (str_sz + 1)) + new_sz = str_sz + 1; + if (!wstr) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + ((wchar_t *) (*pstr))[str_sz - 1] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = (char *) wstr; + wstr += str_sz; + str_sz = new_sz; + } + } + } + while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); + + if (read_in_sv == read_in) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + { + *wstr++ = 0; + + optimize_alloc ((flags & IS_ALLOC_USED) != 0, pstr, str_sz, (wstr - (wchar_t *) *pstr), sizeof (wchar_t)); + pstr = NULL; + ++rval; + } + } + else + { + read_in_sv = read_in; + + if ((c = in_ch (s, &read_in)) == WEOF) + return cleanup_return ((!rval ? WEOF : rval), &gcollect, pstr, &wbuf); + + memset (&state, 0, sizeof (state)); + + do + { + int ended = 0; + wbuf_iter = tmp_wbuf_ptr; + while (wbuf_iter < temp_wbuf_end) + { + if (wbuf_iter[0] == '-' && wbuf_iter[1] != 0 + && (wbuf_iter + 1) != temp_wbuf_end + && wbuf_iter != tmp_wbuf_ptr + && (unsigned int) wbuf_iter[-1] <= (unsigned int) wbuf_iter[1]) + { + for (wc = wbuf_iter[-1] + 1; wc <= wbuf_iter[1] && (wint_t) wc != c; ++wc); + + if (wc <= wbuf_iter[1] && !not_in) + break; + if (wc <= wbuf_iter[1] && not_in) + { + back_ch (c, s, &read_in, 0); + ended = 1; + break; + } + + wbuf_iter += 2; + } + else + { + if ((wint_t) *wbuf_iter == c && !not_in) + break; + if ((wint_t) *wbuf_iter == c && not_in) + { + back_ch (c, s, &read_in, 0); + ended = 1; + break; + } + + ++wbuf_iter; + } + } + + if (ended) + break; + if (wbuf_iter == temp_wbuf_end && !not_in) + { + back_ch (c, s, &read_in, 0); + break; + } + + if ((flags & IS_SUPPRESSED) == 0) + { + if ((flags & IS_ALLOC_USED) != 0 + && (str + MB_CUR_MAX) >= (*pstr + str_sz)) + { + new_sz = str_sz * 2; + str_len = (str - *pstr); + + while ((nstr = (char *) realloc (*pstr, new_sz)) == NULL + && new_sz > (str_len + MB_CUR_MAX)) + new_sz = str_len + MB_CUR_MAX; + if (!nstr) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + ((*pstr))[str_len] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = nstr; + str = nstr + str_len; + str_sz = new_sz; + } + } + + n = wcrtomb ((flags & IS_SUPPRESSED) == 0 ? str : NULL, c, &state); + if (n == (size_t) -1LL) + { + errno = EILSEQ; + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + + str += n; + } + while (--width > 0 && (c = in_ch (s, &read_in)) != WEOF); + + if (read_in_sv == read_in) + return cleanup_return (rval, &gcollect, pstr, &wbuf); + + if ((flags & IS_SUPPRESSED) == 0) + { + n = wcrtomb (buf, 0, &state); + if (n > 0 && (flags & IS_ALLOC_USED) != 0 + && (str + n) >= (*pstr + str_sz)) + { + str_len = (str - *pstr); + + if ((nstr = (char *) realloc (*pstr, str_len + n + 1)) == NULL) + { + if ((flags & USE_POSIX_ALLOC) == 0) + { + (*pstr)[str_len] = 0; + pstr = NULL; + ++rval; + } + return cleanup_return (((flags & USE_POSIX_ALLOC) != 0 ? WEOF : rval), &gcollect, pstr, &wbuf); + } + *pstr = nstr; + str = nstr + str_len; + str_sz = str_len + n + 1; + } + + if (n) + { + memcpy (str, buf, n); + str += n; + } + *str++ = 0; + + optimize_alloc ((flags & IS_ALLOC_USED) != 0, pstr, str_sz, (str - *pstr), sizeof (char)); + pstr = NULL; + ++rval; + } + } + break; + + default: + return cleanup_return (rval, &gcollect, pstr, &wbuf); + } + } + + if (ignore_ws) + { + while (iswspace ((c = in_ch (s, &read_in)))); + back_ch (c, s, &read_in, 0); + } + + return cleanup_return (rval, &gcollect, pstr, &wbuf); +} + +int +__mingw_vfwscanf (FILE *s, const wchar_t *format, va_list argp) +{ + _IFP ifp; + memset (&ifp, 0, sizeof (_IFP)); + ifp.fp = s; + return __mingw_swformat (&ifp, format, argp); +} + +int +__mingw_vswscanf (const wchar_t *s, const wchar_t *format, va_list argp) +{ + _IFP ifp; + memset (&ifp, 0, sizeof (_IFP)); + ifp.str = s; + ifp.is_string = 1; + return __mingw_swformat (&ifp, format, argp); +} + diff --git a/libc/mingw/stdio/scanf.S b/libc/mingw/stdio/scanf.S new file mode 100644 index 000000000..3a0e977a7 --- /dev/null +++ b/libc/mingw/stdio/scanf.S @@ -0,0 +1,232 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +/* vsscanf, vswscanf, vfscanf, and vfwscanf all come here for i386 and arm. + + The goal of this routine is to turn a call to v*scanf into a call to + s*scanf. This is needed because mingw-w64 uses msvcr100.dll, which doesn't + support the v*scanf functions instead of msvcr120.dll which does. + Unfortunately, there is no defined way to know exactly how big a va_list + is, so we use a hard-coded buffer. + + I suppose a sufficiently-motivated person could try to parse the format + to figure out how many tokens there are... */ + +/* The function prototype here is (essentially): + + int __ms_vsscanf_internal (void *s, + void *format, + void *arg, + void *func); + + I say 'essentially' because passing a function pointer as void in ISO + is not supported. But in the end, I take the first parameter (which + may be a char *, a wchar_t *, or a FILE *) and put it into the newly + formed stack, and eventually call the address in func. */ + +#if defined (__x86_64__) + + .text + .align 16 + + /* scl 2: C_EXT - External (public) symbol - covers globals and externs + type 32: DT_FCN - function returning T + */ + .def __argtos; .scl 2; .type 32; .endef + + /* The max number of pointers we support. Must be an even number + to keep the 64bit stack 16byte aligned. Must not be less than 4. */ + .equ entries, 30 + + /* 64bit pointers are 8 bytes. */ + .equ sizeof, 8 + + /* Size of our buffer. */ + .equ iBytes, entries * sizeof + + /* Stack space for first 2 args to s*scanf. */ + .equ iOffset, (2 * sizeof) + + .seh_proc __argtos +__argtos: + + /* When we are done: + - s must be in rcx. That's where it is on entry. + - format must be in rdx. That's where it is on entry. + - The first pointer in arg must be in r8. arg is in r8 on entry. + - The second pointer in arg must be in r9. arg is in r8 on entry. + - The ($entries - 2) other pointers in arg must be on the stack, + starting 32bytes into rsp. */ + + /* We need enough room to shadow (s + format) + + (enough room for all the other args). */ + subq $(iOffset + iBytes), %rsp + .seh_stackalloc iOffset + iBytes + + .seh_endprologue + + /* We are going to copy $entries pointers from arg to our + local stack. Except the first 2, since they will be + loaded in registers. */ + movq $entries - 2, %r10 /* # of ptrs to copy. */ + + /* The first 32 bytes are in registers, but by spec, space + must still be reserved for them on the stack. Put the + rest of the pointers in the stack after that. */ + lea 32(%rsp), %r11 /* dst. */ + +.LOOP: + subq $1, %r10 + + /* Use 16 to skip over the first 2 pointers. */ + movq 16(%r8, %r10, 8), %rax + movq %rax, (%r11, %r10, 8) + jnz .LOOP + + /* r9 contains the routine we are going to call. Since we are about to + overwrite it, move it somewhere safe. */ + movq %r9, %r10 + + /* The stack is now correctly populated, and so are rcx and rdx. + But we need to load the last 2 regs before making the call. */ + movq 0x8(%r8), %r9 /* 2nd dest location (may be garbage if only 1 arg). */ + movq (%r8), %r8 /* 1st dest location. */ + + /* Make the call. */ + callq *%r10 + + addq $(iOffset + iBytes), %rsp + + retq + .seh_endproc + +#elif defined (_X86_) + + .text + .align 16 + + /* scl 2: C_EXT - External (public) symbol - covers globals and externs + type 32: DT_FCN - function returning T + */ + .def __argtos; .scl 2; .type 32; .endef + + /* The max number of pointers we support. Must not be less than 1. */ + .equ entries, 30 + + /* 64bit pointers are 8 bytes. */ + .equ sizeof, 4 + + /* Size of our buffer. */ + .set iBytes, entries * sizeof + + /* Stack space for first 2 args to s*scanf. */ + .equ iOffset, (2 * sizeof) + +__argtos: + pushl %ebp + movl %esp, %ebp + pushl %edi + + /* Reserve enough stack space for everything. + + Stack usage will look like: + 4 bytes - s + 4 bytes - format + (iBytes) bytes - variable # of parameters for sscanf (all ptrs). */ + + subl $(iOffset + iBytes), %esp + + /* Write out s and format where they need to be for the sscanf call. */ + movl 8(%ebp), %eax + movl %eax, (%esp) /* s. */ + movl 12(%ebp), %edx + movl %edx, 0x4(%esp) /* format. */ + + /* We are going to copy $entries pointers from arg to our + local stack. */ + movl $entries, %ecx /* # of ptrs to copy. */ + lea iOffset(%esp), %edi /* dst. */ + movl 16(%ebp), %edx /* src. */ + +.LOOP: + subl $1, %ecx + + movl (%edx, %ecx, 4), %eax + movl %eax, (%edi, %ecx, 4) + jnz .LOOP + + /* The stack is now correctly populated. */ + + /* Make the call. */ + call *20(%ebp) + + /* Restore stack. */ + popl %edi + leave + + ret + +#elif defined (__arm__) + + .text + .align 2 + .thumb_func + .globl __argtos + +__argtos: + push {r4-r7, lr} + sub sp, sp, #128 + mov r12, r3 + mov r4, sp + + ldr r5, [r2], #4 + ldr r6, [r2], #4 + + mov r3, #116 +1: ldr r7, [r2], #4 + str r7, [r4], #4 + subs r3, r3, #4 + bne 1b + + mov r2, r5 + mov r3, r6 + blx r12 + add sp, sp, #128 + pop {r4-r7, pc} + +#elif defined (__aarch64__) + + .text + .align 2 + .globl __argtos + +__argtos: + stp x29, x30, [sp, #-16]! + mov x29, sp + sub sp, sp, #256 + mov x9, sp + mov x10, x2 + mov x11, x3 + + ldr x2, [x10], #8 + ldr x3, [x10], #8 + ldr x4, [x10], #8 + ldr x5, [x10], #8 + ldr x6, [x10], #8 + ldr x7, [x10], #8 + + mov x12, #240 +1: ldr x13, [x10], #8 + str x13, [x9], #8 + subs x12, x12, #8 + b.ne 1b + + blr x11 + mov sp, x29 + ldp x29, x30, [sp], #16 + ret + +#endif diff --git a/libc/mingw/stdio/scanf2-template.S b/libc/mingw/stdio/scanf2-template.S new file mode 100644 index 000000000..3c9aa2a4b --- /dev/null +++ b/libc/mingw/stdio/scanf2-template.S @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#if defined(_ARM_) || defined(__arm__) + .thumb +#endif + .text + .p2align 4,,15 + .globl FCT + .def FCT; .scl 2; .type 32; .endef +#ifdef __x86_64__ + .seh_proc FCT +#endif +FCT: +#ifdef __x86_64__ + .seh_endprologue +#endif +#if defined(_AMD64_) || defined(__x86_64__) || defined(_X86_) || defined(__i386__) + jmp FWD +#elif defined(_ARM_) || defined(__arm__) + .thumb_func + b FWD +#elif defined(_ARM64_) || defined(__aarch64__) + b FWD +#endif +#ifdef __x86_64__ + .seh_endproc +#endif + .def FWD; .scl 2; .type 32; .endef diff --git a/libc/mingw/stdio/snprintf.c b/libc/mingw/stdio/snprintf.c new file mode 100644 index 000000000..933001138 --- /dev/null +++ b/libc/mingw/stdio/snprintf.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +int __cdecl __ms_snprintf(char* buffer, size_t n, const char *format, ...) +{ + int retval; + va_list argptr; + + va_start(argptr, format); + retval = _vsnprintf (buffer, n, format, argptr); + va_end(argptr); + return retval; +} diff --git a/libc/mingw/stdio/snwprintf.c b/libc/mingw/stdio/snwprintf.c new file mode 100644 index 000000000..c57a46d89 --- /dev/null +++ b/libc/mingw/stdio/snwprintf.c @@ -0,0 +1,18 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include +#include + +int __cdecl __ms_snwprintf(wchar_t *buffer, size_t n, const wchar_t *format, ...) +{ + int retval; + va_list argptr; + + va_start(argptr, format); + retval = _vsnwprintf(buffer, n, format, argptr); + va_end(argptr); + return retval; +} diff --git a/libc/mingw/stdio/strtof.c b/libc/mingw/stdio/strtof.c new file mode 100644 index 000000000..5697eb4b5 --- /dev/null +++ b/libc/mingw/stdio/strtof.c @@ -0,0 +1,11 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include + +float strtof( const char *nptr, char **endptr) +{ + return (strtod(nptr, endptr)); +} diff --git a/libc/mingw/stdio/strtok_r.c b/libc/mingw/stdio/strtok_r.c new file mode 100644 index 000000000..b804e0b39 --- /dev/null +++ b/libc/mingw/stdio/strtok_r.c @@ -0,0 +1,98 @@ +/*- + * Copyright (c) 1998 Softweyr LLC. All rights reserved. + * + * strtok_r, from Berkeley strtok + * Oct 13, 1998 by Wes Peters + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notices, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notices, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE + * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#define _POSIX_SOURCE 1 +#include + +/* + * strtok_r documentation: + * http://pubs.opengroup.org/onlinepubs/009695399/functions/strtok.html + * + * Implementation: + * http://svnweb.freebsd.org/base/head/lib/libc/string/strtok.c?view=co + * + * strtok_r cannot completely be implemented by strtok because of the internal state. + * It breaks when used on 2 strings where they are scanned A, B then A, B. + * Thread-safety is not the issue. + * + * Sample strtok implemenatation, note the internal state: + * char *strtok(char *s, const char *d) { static char *t; return strtok_r(s,d,t); } + * + */ + +char * +strtok_r(char * __restrict s, const char * __restrict delim, char ** __restrict last) +{ + char *spanp, *tok; + int c, sc; + + if (s == NULL && (s = *last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = '\0'; + *last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/libc/mingw/stdio/truncate.c b/libc/mingw/stdio/truncate.c new file mode 100644 index 000000000..d83bd2eb4 --- /dev/null +++ b/libc/mingw/stdio/truncate.c @@ -0,0 +1,25 @@ +#include +#include +#include + +int truncate(const char *pathname, _off_t len){ + int ret, err; + int fd = _open(pathname,_O_BINARY|_O_RDWR); + if (fd == -1) return fd; + ret = ftruncate(fd,len); + _get_errno(&err); + _close(fd); + _set_errno(err); + return ret; +} + +int truncate64(const char *pathname, _off64_t len){ + int ret, err; + int fd = _open(pathname,_O_BINARY|_O_RDWR); + if (fd == -1) return fd; + ret = ftruncate64(fd,len); + _get_errno(&err); + _close(fd); + _set_errno(err); + return ret; +} diff --git a/libc/mingw/stdio/ulltoa.c b/libc/mingw/stdio/ulltoa.c new file mode 100644 index 000000000..9985dfe9f --- /dev/null +++ b/libc/mingw/stdio/ulltoa.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +char* ulltoa(unsigned long long _n, char * _c, int _i) + { return _ui64toa (_n, _c, _i); } diff --git a/libc/mingw/stdio/ulltow.c b/libc/mingw/stdio/ulltow.c new file mode 100644 index 000000000..145e7554f --- /dev/null +++ b/libc/mingw/stdio/ulltow.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +wchar_t* ulltow(unsigned long long _n, wchar_t * _w, int _i) + { return _ui64tow (_n, _w, _i); } diff --git a/libc/mingw/stdio/vasprintf.c b/libc/mingw/stdio/vasprintf.c new file mode 100644 index 000000000..7036e96cf --- /dev/null +++ b/libc/mingw/stdio/vasprintf.c @@ -0,0 +1,25 @@ +#define _GNU_SOURCE +#define __CRT__NO_INLINE + +#include +#include +#include + +int vasprintf(char ** __restrict__ ret, + const char * __restrict__ format, + va_list ap) { + int len; + /* Get Length */ + len = _vsnprintf(NULL,0,format,ap); + if (len < 0) return -1; + /* +1 for \0 terminator. */ + *ret = malloc(len + 1); + /* Check malloc fail*/ + if (!*ret) return -1; + /* Write String */ + _vsnprintf(*ret,len+1,format,ap); + /* Terminate explicitly */ + (*ret)[len] = '\0'; + return len; +} + diff --git a/libc/mingw/stdio/vfscanf.c b/libc/mingw/stdio/vfscanf.c new file mode 100644 index 000000000..dab72fe4a --- /dev/null +++ b/libc/mingw/stdio/vfscanf.c @@ -0,0 +1,31 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +extern int __ms_vfscanf_internal ( + FILE * s, + const char * format, + va_list arg, + int (*func)(FILE * __restrict__, const char * __restrict__, ...)) + asm("__argtos"); + +int __ms_vfscanf (FILE * __restrict__ stream, const char * __restrict__ format, va_list arg) +{ + int ret; + +#if defined(_AMD64_) || defined(__x86_64__) || \ + defined(_X86_) || defined(__i386__) || \ + defined(_ARM_) || defined(__arm__) || \ + defined(_ARM64_) || defined(__aarch64__) + ret = __ms_vfscanf_internal (stream, format, arg, fscanf); +#else +#error "unknown platform" +#endif + + return ret; +} diff --git a/libc/mingw/stdio/vfscanf2.S b/libc/mingw/stdio/vfscanf2.S new file mode 100644 index 000000000..36f38c5fd --- /dev/null +++ b/libc/mingw/stdio/vfscanf2.S @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + +#define FCT __MINGW_USYMBOL(vfscanf) +#define FWD __MINGW_USYMBOL(__ms_vfscanf) + + .file "vfscanf2.S" +#include "scanf2-template.S" diff --git a/libc/mingw/stdio/vfwscanf.c b/libc/mingw/stdio/vfwscanf.c new file mode 100644 index 000000000..52cf92835 --- /dev/null +++ b/libc/mingw/stdio/vfwscanf.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +extern int __ms_vfwscanf_internal ( + FILE * s, + const wchar_t * format, + va_list arg, + int (*func)(FILE * __restrict__, const wchar_t * __restrict__, ...)) + asm("__argtos"); + +int __ms_vfwscanf (FILE * __restrict__ stream, + const wchar_t * __restrict__ format, va_list arg) +{ + int ret; + +#if defined(_AMD64_) || defined(__x86_64__) || \ + defined(_X86_) || defined(__i386__) || \ + defined(_ARM_) || defined(__arm__) || \ + defined (_ARM64_) || defined (__aarch64__) + ret = __ms_vfwscanf_internal (stream, format, arg, fwscanf); +#else +#error "unknown platform" +#endif + + return ret; +} diff --git a/libc/mingw/stdio/vfwscanf2.S b/libc/mingw/stdio/vfwscanf2.S new file mode 100644 index 000000000..9d98647a7 --- /dev/null +++ b/libc/mingw/stdio/vfwscanf2.S @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + +#define FCT __MINGW_USYMBOL(vfwscanf) +#define FWD __MINGW_USYMBOL(__ms_vfwscanf) + + .file "vfwscanf2.S" +#include "scanf2-template.S" diff --git a/libc/mingw/stdio/vscanf.c b/libc/mingw/stdio/vscanf.c new file mode 100644 index 000000000..f255e6825 --- /dev/null +++ b/libc/mingw/stdio/vscanf.c @@ -0,0 +1,15 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +// By aaronwl 2003-01-28 for mingw-msvcrt +// Public domain: all copyrights disclaimed, absolutely no warranties + +#include +#include + +int __ms_vscanf(const char * __restrict__ format, va_list arg) +{ + return __ms_vfscanf(stdin, format, arg); +} diff --git a/libc/mingw/stdio/vscanf2.S b/libc/mingw/stdio/vscanf2.S new file mode 100644 index 000000000..b0e2a09f0 --- /dev/null +++ b/libc/mingw/stdio/vscanf2.S @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + +#define FCT __MINGW_USYMBOL(vscanf) +#define FWD __MINGW_USYMBOL(__ms_vscanf) + + .file "vscanf2.S" +#include "scanf2-template.S" diff --git a/libc/mingw/stdio/vsnprintf.c b/libc/mingw/stdio/vsnprintf.c new file mode 100644 index 000000000..1346c5c84 --- /dev/null +++ b/libc/mingw/stdio/vsnprintf.c @@ -0,0 +1,13 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include +#include + +int __cdecl __ms_vsnprintf (char *s,size_t n,const char *format,va_list arg) +{ + return _vsnprintf(s, n, format, arg); +} diff --git a/libc/mingw/stdio/vsnwprintf.c b/libc/mingw/stdio/vsnwprintf.c new file mode 100644 index 000000000..b5c5ae65c --- /dev/null +++ b/libc/mingw/stdio/vsnwprintf.c @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include <_mingw.h> +#include +#include + +int __cdecl __ms_vsnwprintf(wchar_t *buffer, size_t n, const wchar_t * format, va_list argptr); + +int __cdecl __ms_vsnwprintf(wchar_t *buffer, size_t n, const wchar_t * format, va_list argptr) +{ + return _vsnwprintf(buffer, n, format, argptr); +} diff --git a/libc/mingw/stdio/vsscanf.c b/libc/mingw/stdio/vsscanf.c new file mode 100644 index 000000000..6c8fe5a56 --- /dev/null +++ b/libc/mingw/stdio/vsscanf.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +extern int __ms_vsscanf_internal ( + const char * s, + const char * format, + va_list arg, + int (*func)(const char * __restrict__, const char * __restrict__, ...)) + asm("__argtos"); + +int __ms_vsscanf (const char * __restrict__ s, + const char * __restrict__ format, va_list arg) +{ + int ret; + +#if defined(_AMD64_) || defined(__x86_64__) || \ + defined(_X86_) || defined(__i386__) || \ + defined(_ARM_) || defined(__arm__) || \ + defined(_ARM64_) || defined(__aarch64__) + ret = __ms_vsscanf_internal (s, format, arg, sscanf); +#else +#error "unknown platform" +#endif + + return ret; +} diff --git a/libc/mingw/stdio/vsscanf2.S b/libc/mingw/stdio/vsscanf2.S new file mode 100644 index 000000000..e840a972b --- /dev/null +++ b/libc/mingw/stdio/vsscanf2.S @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + +#define FCT __MINGW_USYMBOL(vsscanf) +#define FWD __MINGW_USYMBOL(__ms_vsscanf) + + .file "vsscanf2.S" +#include "scanf2-template.S" diff --git a/libc/mingw/stdio/vswscanf.c b/libc/mingw/stdio/vswscanf.c new file mode 100644 index 000000000..941ed1205 --- /dev/null +++ b/libc/mingw/stdio/vswscanf.c @@ -0,0 +1,32 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ + +#include +#include + +extern int __ms_vswscanf_internal ( + const wchar_t * s, + const wchar_t * format, + va_list arg, + int (*func)(const wchar_t * __restrict__, const wchar_t * __restrict__, ...)) + asm("__argtos"); + +int __ms_vswscanf(const wchar_t * __restrict__ s, const wchar_t * __restrict__ format, + va_list arg) +{ + int ret; + +#if defined(_AMD64_) || defined(__x86_64__) || \ + defined(_X86_) || defined(__i386__) || \ + defined(_ARM_) || defined(__arm__) || \ + defined(_ARM64_) || defined(__aarch64__) + ret = __ms_vswscanf_internal (s, format, arg, swscanf); +#else +#error "unknown platform" +#endif + + return ret; +} diff --git a/libc/mingw/stdio/vswscanf2.S b/libc/mingw/stdio/vswscanf2.S new file mode 100644 index 000000000..529f71b7e --- /dev/null +++ b/libc/mingw/stdio/vswscanf2.S @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + +#define FCT __MINGW_USYMBOL(vswscanf) +#define FWD __MINGW_USYMBOL(__ms_vswscanf) + + .file "vswscanf2.S" +#include "scanf2-template.S" diff --git a/libc/mingw/stdio/vwscanf.c b/libc/mingw/stdio/vwscanf.c new file mode 100644 index 000000000..3360eefad --- /dev/null +++ b/libc/mingw/stdio/vwscanf.c @@ -0,0 +1,16 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +// By aaronwl 2003-01-28 for mingw-msvcrt. +// Public domain: all copyrights disclaimed, absolutely no warranties. + +#include +#include +#include + +int __ms_vwscanf (const wchar_t * __restrict__ format, va_list arg) +{ + return __ms_vfwscanf(stdin, format, arg); +} diff --git a/libc/mingw/stdio/vwscanf2.S b/libc/mingw/stdio/vwscanf2.S new file mode 100644 index 000000000..e52c8c2a0 --- /dev/null +++ b/libc/mingw/stdio/vwscanf2.S @@ -0,0 +1,12 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#include <_mingw_mac.h> + +#define FCT __MINGW_USYMBOL(vwscanf) +#define FWD __MINGW_USYMBOL(__ms_vwscanf) + + .file "vwscanf2.S" +#include "scanf2-template.S" diff --git a/libc/mingw/stdio/wtoll.c b/libc/mingw/stdio/wtoll.c new file mode 100644 index 000000000..eb460436e --- /dev/null +++ b/libc/mingw/stdio/wtoll.c @@ -0,0 +1,10 @@ +/** + * This file has no copyright assigned and is placed in the Public Domain. + * This file is part of the mingw-w64 runtime package. + * No warranty is given; refer to the file DISCLAIMER.PD within this package. + */ +#define __CRT__NO_INLINE +#include + +long long wtoll(const wchar_t * _w) + { return _wtoi64 (_w); } diff --git a/src/link.cpp b/src/link.cpp index 526f9e07f..59d6b56ad 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -13,6 +13,543 @@ #include "install_files.h" #include "glibc.hpp" +static const char *msvcrt_common_src[] = { + "misc" OS_SEP "onexit_table.c", + "misc" OS_SEP "register_tls_atexit.c", + "stdio" OS_SEP "acrt_iob_func.c", + "misc" OS_SEP "_configthreadlocale.c", + "misc" OS_SEP "_get_current_locale.c", + "misc" OS_SEP "invalid_parameter_handler.c", + "misc" OS_SEP "output_format.c", + "misc" OS_SEP "purecall.c", + "secapi" OS_SEP "_access_s.c", + "secapi" OS_SEP "_cgets_s.c", + "secapi" OS_SEP "_cgetws_s.c", + "secapi" OS_SEP "_chsize_s.c", + "secapi" OS_SEP "_controlfp_s.c", + "secapi" OS_SEP "_cprintf_s.c", + "secapi" OS_SEP "_cprintf_s_l.c", + "secapi" OS_SEP "_ctime32_s.c", + "secapi" OS_SEP "_ctime64_s.c", + "secapi" OS_SEP "_cwprintf_s.c", + "secapi" OS_SEP "_cwprintf_s_l.c", + "secapi" OS_SEP "_gmtime32_s.c", + "secapi" OS_SEP "_gmtime64_s.c", + "secapi" OS_SEP "_localtime32_s.c", + "secapi" OS_SEP "_localtime64_s.c", + "secapi" OS_SEP "_mktemp_s.c", + "secapi" OS_SEP "_sopen_s.c", + "secapi" OS_SEP "_strdate_s.c", + "secapi" OS_SEP "_strtime_s.c", + "secapi" OS_SEP "_umask_s.c", + "secapi" OS_SEP "_vcprintf_s.c", + "secapi" OS_SEP "_vcprintf_s_l.c", + "secapi" OS_SEP "_vcwprintf_s.c", + "secapi" OS_SEP "_vcwprintf_s_l.c", + "secapi" OS_SEP "_vscprintf_p.c", + "secapi" OS_SEP "_vscwprintf_p.c", + "secapi" OS_SEP "_vswprintf_p.c", + "secapi" OS_SEP "_waccess_s.c", + "secapi" OS_SEP "_wasctime_s.c", + "secapi" OS_SEP "_wctime32_s.c", + "secapi" OS_SEP "_wctime64_s.c", + "secapi" OS_SEP "_wstrtime_s.c", + "secapi" OS_SEP "_wmktemp_s.c", + "secapi" OS_SEP "_wstrdate_s.c", + "secapi" OS_SEP "asctime_s.c", + "secapi" OS_SEP "memcpy_s.c", + "secapi" OS_SEP "memmove_s.c", + "secapi" OS_SEP "rand_s.c", + "secapi" OS_SEP "sprintf_s.c", + "secapi" OS_SEP "strerror_s.c", + "secapi" OS_SEP "vsprintf_s.c", + "secapi" OS_SEP "wmemcpy_s.c", + "secapi" OS_SEP "wmemmove_s.c", + "stdio" OS_SEP "mingw_lock.c", +}; + +static const char *msvcrt_i386_src[] = { + "misc" OS_SEP "lc_locale_func.c", + +}; + +static const char *msvcrt_other_src[] = { + "misc" OS_SEP "__p___argv.c", + "misc" OS_SEP "__p__acmdln.c", + "misc" OS_SEP "__p__fmode.c", + "misc" OS_SEP "__p__wcmdln.c", +}; + +static const char *mingwex_generic_src[] = { + "complex" OS_SEP "_cabs.c", + "complex" OS_SEP "cabs.c", + "complex" OS_SEP "cabsf.c", + "complex" OS_SEP "cabsl.c", + "complex" OS_SEP "cacos.c", + "complex" OS_SEP "cacosf.c", + "complex" OS_SEP "cacosl.c", + "complex" OS_SEP "carg.c", + "complex" OS_SEP "cargf.c", + "complex" OS_SEP "cargl.c", + "complex" OS_SEP "casin.c", + "complex" OS_SEP "casinf.c", + "complex" OS_SEP "casinl.c", + "complex" OS_SEP "catan.c", + "complex" OS_SEP "catanf.c", + "complex" OS_SEP "catanl.c", + "complex" OS_SEP "ccos.c", + "complex" OS_SEP "ccosf.c", + "complex" OS_SEP "ccosl.c", + "complex" OS_SEP "cexp.c", + "complex" OS_SEP "cexpf.c", + "complex" OS_SEP "cexpl.c", + "complex" OS_SEP "cimag.c", + "complex" OS_SEP "cimagf.c", + "complex" OS_SEP "cimagl.c", + "complex" OS_SEP "clog.c", + "complex" OS_SEP "clog10.c", + "complex" OS_SEP "clog10f.c", + "complex" OS_SEP "clog10l.c", + "complex" OS_SEP "clogf.c", + "complex" OS_SEP "clogl.c", + "complex" OS_SEP "conj.c", + "complex" OS_SEP "conjf.c", + "complex" OS_SEP "conjl.c", + "complex" OS_SEP "cpow.c", + "complex" OS_SEP "cpowf.c", + "complex" OS_SEP "cpowl.c", + "complex" OS_SEP "cproj.c", + "complex" OS_SEP "cprojf.c", + "complex" OS_SEP "cprojl.c", + "complex" OS_SEP "creal.c", + "complex" OS_SEP "crealf.c", + "complex" OS_SEP "creall.c", + "complex" OS_SEP "csin.c", + "complex" OS_SEP "csinf.c", + "complex" OS_SEP "csinl.c", + "complex" OS_SEP "csqrt.c", + "complex" OS_SEP "csqrtf.c", + "complex" OS_SEP "csqrtl.c", + "complex" OS_SEP "ctan.c", + "complex" OS_SEP "ctanf.c", + "complex" OS_SEP "ctanl.c", + "crt" OS_SEP "dllentry.c", + "crt" OS_SEP "dllmain.c", + "gdtoa" OS_SEP "arithchk.c", + "gdtoa" OS_SEP "dmisc.c", + "gdtoa" OS_SEP "dtoa.c", + "gdtoa" OS_SEP "g__fmt.c", + "gdtoa" OS_SEP "g_dfmt.c", + "gdtoa" OS_SEP "g_ffmt.c", + "gdtoa" OS_SEP "g_xfmt.c", + "gdtoa" OS_SEP "gdtoa.c", + "gdtoa" OS_SEP "gethex.c", + "gdtoa" OS_SEP "gmisc.c", + "gdtoa" OS_SEP "hd_init.c", + "gdtoa" OS_SEP "hexnan.c", + "gdtoa" OS_SEP "misc.c", + "gdtoa" OS_SEP "qnan.c", + "gdtoa" OS_SEP "smisc.c", + "gdtoa" OS_SEP "strtodg.c", + "gdtoa" OS_SEP "strtodnrp.c", + "gdtoa" OS_SEP "strtof.c", + "gdtoa" OS_SEP "strtopx.c", + "gdtoa" OS_SEP "sum.c", + "gdtoa" OS_SEP "ulp.c", + "math" OS_SEP "abs64.c", + "math" OS_SEP "cbrt.c", + "math" OS_SEP "cbrtf.c", + "math" OS_SEP "cbrtl.c", + "math" OS_SEP "cephes_emath.c", + "math" OS_SEP "copysign.c", + "math" OS_SEP "copysignf.c", + "math" OS_SEP "coshf.c", + "math" OS_SEP "coshl.c", + "math" OS_SEP "erfl.c", + "math" OS_SEP "expf.c", + "math" OS_SEP "fabs.c", + "math" OS_SEP "fabsf.c", + "math" OS_SEP "fabsl.c", + "math" OS_SEP "fdim.c", + "math" OS_SEP "fdimf.c", + "math" OS_SEP "fdiml.c", + "math" OS_SEP "fma.c", + "math" OS_SEP "fmaf.c", + "math" OS_SEP "fmal.c", + "math" OS_SEP "fmax.c", + "math" OS_SEP "fmaxf.c", + "math" OS_SEP "fmaxl.c", + "math" OS_SEP "fmin.c", + "math" OS_SEP "fminf.c", + "math" OS_SEP "fminl.c", + "math" OS_SEP "fp_consts.c", + "math" OS_SEP "fp_constsf.c", + "math" OS_SEP "fp_constsl.c", + "math" OS_SEP "fpclassify.c", + "math" OS_SEP "fpclassifyf.c", + "math" OS_SEP "fpclassifyl.c", + "math" OS_SEP "frexpf.c", + "math" OS_SEP "hypot.c", + "math" OS_SEP "hypotf.c", + "math" OS_SEP "hypotl.c", + "math" OS_SEP "isnan.c", + "math" OS_SEP "isnanf.c", + "math" OS_SEP "isnanl.c", + "math" OS_SEP "ldexpf.c", + "math" OS_SEP "lgamma.c", + "math" OS_SEP "lgammaf.c", + "math" OS_SEP "lgammal.c", + "math" OS_SEP "llrint.c", + "math" OS_SEP "llrintf.c", + "math" OS_SEP "llrintl.c", + "math" OS_SEP "llround.c", + "math" OS_SEP "llroundf.c", + "math" OS_SEP "llroundl.c", + "math" OS_SEP "log10f.c", + "math" OS_SEP "logf.c", + "math" OS_SEP "lrint.c", + "math" OS_SEP "lrintf.c", + "math" OS_SEP "lrintl.c", + "math" OS_SEP "lround.c", + "math" OS_SEP "lroundf.c", + "math" OS_SEP "lroundl.c", + "math" OS_SEP "modf.c", + "math" OS_SEP "modff.c", + "math" OS_SEP "modfl.c", + "math" OS_SEP "nextafterf.c", + "math" OS_SEP "nextafterl.c", + "math" OS_SEP "nexttoward.c", + "math" OS_SEP "nexttowardf.c", + "math" OS_SEP "powf.c", + "math" OS_SEP "powi.c", + "math" OS_SEP "powif.c", + "math" OS_SEP "powil.c", + "math" OS_SEP "rint.c", + "math" OS_SEP "rintf.c", + "math" OS_SEP "rintl.c", + "math" OS_SEP "round.c", + "math" OS_SEP "roundf.c", + "math" OS_SEP "roundl.c", + "math" OS_SEP "s_erf.c", + "math" OS_SEP "sf_erf.c", + "math" OS_SEP "signbit.c", + "math" OS_SEP "signbitf.c", + "math" OS_SEP "signbitl.c", + "math" OS_SEP "signgam.c", + "math" OS_SEP "sinhf.c", + "math" OS_SEP "sinhl.c", + "math" OS_SEP "sqrt.c", + "math" OS_SEP "sqrtf.c", + "math" OS_SEP "sqrtl.c", + "math" OS_SEP "tanhf.c", + "math" OS_SEP "tanhl.c", + "math" OS_SEP "tgamma.c", + "math" OS_SEP "tgammaf.c", + "math" OS_SEP "tgammal.c", + "math" OS_SEP "truncl.c", + "misc" OS_SEP "alarm.c", + "misc" OS_SEP "assert.c", + "misc" OS_SEP "basename.c", + "misc" OS_SEP "btowc.c", + "misc" OS_SEP "delay-f.c", + "misc" OS_SEP "delay-n.c", + "misc" OS_SEP "delayimp.c", + "misc" OS_SEP "difftime.c", + "misc" OS_SEP "difftime32.c", + "misc" OS_SEP "difftime64.c", + "misc" OS_SEP "dirent.c", + "misc" OS_SEP "dirname.c", + "misc" OS_SEP "execv.c", + "misc" OS_SEP "execve.c", + "misc" OS_SEP "execvp.c", + "misc" OS_SEP "execvpe.c", + "misc" OS_SEP "feclearexcept.c", + "misc" OS_SEP "fegetenv.c", + "misc" OS_SEP "fegetexceptflag.c", + "misc" OS_SEP "fegetround.c", + "misc" OS_SEP "feholdexcept.c", + "misc" OS_SEP "feraiseexcept.c", + "misc" OS_SEP "fesetenv.c", + "misc" OS_SEP "fesetexceptflag.c", + "misc" OS_SEP "fesetround.c", + "misc" OS_SEP "fetestexcept.c", + "misc" OS_SEP "feupdateenv.c", + "misc" OS_SEP "ftruncate.c", + "misc" OS_SEP "ftw.c", + "misc" OS_SEP "ftw64.c", + "misc" OS_SEP "fwide.c", + "misc" OS_SEP "getlogin.c", + "misc" OS_SEP "getopt.c", + "misc" OS_SEP "gettimeofday.c", + "misc" OS_SEP "imaxabs.c", + "misc" OS_SEP "imaxdiv.c", + "misc" OS_SEP "isblank.c", + "misc" OS_SEP "iswblank.c", + "misc" OS_SEP "mbrtowc.c", + "misc" OS_SEP "mbsinit.c", + "misc" OS_SEP "mempcpy.c", + "misc" OS_SEP "mingw-aligned-malloc.c", + "misc" OS_SEP "mingw-fseek.c", + "misc" OS_SEP "mingw_getsp.S", + "misc" OS_SEP "mingw_matherr.c", + "misc" OS_SEP "mingw_mbwc_convert.c", + "misc" OS_SEP "mingw_usleep.c", + "misc" OS_SEP "mingw_wcstod.c", + "misc" OS_SEP "mingw_wcstof.c", + "misc" OS_SEP "mingw_wcstold.c", + "misc" OS_SEP "mkstemp.c", + "misc" OS_SEP "seterrno.c", + "misc" OS_SEP "sleep.c", + "misc" OS_SEP "spawnv.c", + "misc" OS_SEP "spawnve.c", + "misc" OS_SEP "spawnvp.c", + "misc" OS_SEP "spawnvpe.c", + "misc" OS_SEP "strnlen.c", + "misc" OS_SEP "strsafe.c", + "misc" OS_SEP "strtoimax.c", + "misc" OS_SEP "strtold.c", + "misc" OS_SEP "strtoumax.c", + "misc" OS_SEP "tdelete.c", + "misc" OS_SEP "tfind.c", + "misc" OS_SEP "tsearch.c", + "misc" OS_SEP "twalk.c", + "misc" OS_SEP "uchar_c16rtomb.c", + "misc" OS_SEP "uchar_c32rtomb.c", + "misc" OS_SEP "uchar_mbrtoc16.c", + "misc" OS_SEP "uchar_mbrtoc32.c", + "misc" OS_SEP "wassert.c", + "misc" OS_SEP "wcrtomb.c", + "misc" OS_SEP "wcsnlen.c", + "misc" OS_SEP "wcstof.c", + "misc" OS_SEP "wcstoimax.c", + "misc" OS_SEP "wcstold.c", + "misc" OS_SEP "wcstoumax.c", + "misc" OS_SEP "wctob.c", + "misc" OS_SEP "wctrans.c", + "misc" OS_SEP "wctype.c", + "misc" OS_SEP "wdirent.c", + "misc" OS_SEP "winbs_uint64.c", + "misc" OS_SEP "winbs_ulong.c", + "misc" OS_SEP "winbs_ushort.c", + "misc" OS_SEP "wmemchr.c", + "misc" OS_SEP "wmemcmp.c", + "misc" OS_SEP "wmemcpy.c", + "misc" OS_SEP "wmemmove.c", + "misc" OS_SEP "wmempcpy.c", + "misc" OS_SEP "wmemset.c", + "stdio" OS_SEP "_Exit.c", + "stdio" OS_SEP "_findfirst64i32.c", + "stdio" OS_SEP "_findnext64i32.c", + "stdio" OS_SEP "_fstat.c", + "stdio" OS_SEP "_fstat64i32.c", + "stdio" OS_SEP "_ftime.c", + "stdio" OS_SEP "_getc_nolock.c", + "stdio" OS_SEP "_getwc_nolock.c", + "stdio" OS_SEP "_putc_nolock.c", + "stdio" OS_SEP "_putwc_nolock.c", + "stdio" OS_SEP "_stat.c", + "stdio" OS_SEP "_stat64i32.c", + "stdio" OS_SEP "_wfindfirst64i32.c", + "stdio" OS_SEP "_wfindnext64i32.c", + "stdio" OS_SEP "_wstat.c", + "stdio" OS_SEP "_wstat64i32.c", + "stdio" OS_SEP "asprintf.c", + "stdio" OS_SEP "atoll.c", + "stdio" OS_SEP "fgetpos64.c", + "stdio" OS_SEP "fopen64.c", + "stdio" OS_SEP "fseeko32.c", + "stdio" OS_SEP "fseeko64.c", + "stdio" OS_SEP "fsetpos64.c", + "stdio" OS_SEP "ftello.c", + "stdio" OS_SEP "ftello64.c", + "stdio" OS_SEP "ftruncate64.c", + "stdio" OS_SEP "lltoa.c", + "stdio" OS_SEP "lltow.c", + "stdio" OS_SEP "lseek64.c", + "stdio" OS_SEP "mingw_asprintf.c", + "stdio" OS_SEP "mingw_fprintf.c", + "stdio" OS_SEP "mingw_fprintfw.c", + "stdio" OS_SEP "mingw_fscanf.c", + "stdio" OS_SEP "mingw_fwscanf.c", + "stdio" OS_SEP "mingw_pformat.c", + "stdio" OS_SEP "mingw_pformatw.c", + "stdio" OS_SEP "mingw_printf.c", + "stdio" OS_SEP "mingw_printfw.c", + "stdio" OS_SEP "mingw_scanf.c", + "stdio" OS_SEP "mingw_snprintf.c", + "stdio" OS_SEP "mingw_snprintfw.c", + "stdio" OS_SEP "mingw_sprintf.c", + "stdio" OS_SEP "mingw_sprintfw.c", + "stdio" OS_SEP "mingw_sscanf.c", + "stdio" OS_SEP "mingw_swscanf.c", + "stdio" OS_SEP "mingw_vasprintf.c", + "stdio" OS_SEP "mingw_vfprintf.c", + "stdio" OS_SEP "mingw_vfprintfw.c", + "stdio" OS_SEP "mingw_vfscanf.c", + "stdio" OS_SEP "mingw_vprintf.c", + "stdio" OS_SEP "mingw_vprintfw.c", + "stdio" OS_SEP "mingw_vsnprintf.c", + "stdio" OS_SEP "mingw_vsnprintfw.c", + "stdio" OS_SEP "mingw_vsprintf.c", + "stdio" OS_SEP "mingw_vsprintfw.c", + "stdio" OS_SEP "mingw_wscanf.c", + "stdio" OS_SEP "mingw_wvfscanf.c", + "stdio" OS_SEP "scanf.S", + "stdio" OS_SEP "snprintf.c", + "stdio" OS_SEP "snwprintf.c", + "stdio" OS_SEP "strtof.c", + "stdio" OS_SEP "strtok_r.c", + "stdio" OS_SEP "truncate.c", + "stdio" OS_SEP "ulltoa.c", + "stdio" OS_SEP "ulltow.c", + "stdio" OS_SEP "vasprintf.c", + "stdio" OS_SEP "vfscanf.c", + "stdio" OS_SEP "vfscanf2.S", + "stdio" OS_SEP "vfwscanf.c", + "stdio" OS_SEP "vfwscanf2.S", + "stdio" OS_SEP "vscanf.c", + "stdio" OS_SEP "vscanf2.S", + "stdio" OS_SEP "vsnprintf.c", + "stdio" OS_SEP "vsnwprintf.c", + "stdio" OS_SEP "vsscanf.c", + "stdio" OS_SEP "vsscanf2.S", + "stdio" OS_SEP "vswscanf.c", + "stdio" OS_SEP "vswscanf2.S", + "stdio" OS_SEP "vwscanf.c", + "stdio" OS_SEP "vwscanf2.S", + "stdio" OS_SEP "wtoll.c", +}; + +static const char *mingwex_x86_src[] = { + "math" OS_SEP "x86" OS_SEP "acosf.c", + "math" OS_SEP "x86" OS_SEP "acosh.c", + "math" OS_SEP "x86" OS_SEP "acoshf.c", + "math" OS_SEP "x86" OS_SEP "acoshl.c", + "math" OS_SEP "x86" OS_SEP "acosl.c", + "math" OS_SEP "x86" OS_SEP "asinf.c", + "math" OS_SEP "x86" OS_SEP "asinh.c", + "math" OS_SEP "x86" OS_SEP "asinhf.c", + "math" OS_SEP "x86" OS_SEP "asinhl.c", + "math" OS_SEP "x86" OS_SEP "asinl.c", + "math" OS_SEP "x86" OS_SEP "atan2.c", + "math" OS_SEP "x86" OS_SEP "atan2f.c", + "math" OS_SEP "x86" OS_SEP "atan2l.c", + "math" OS_SEP "x86" OS_SEP "atanf.c", + "math" OS_SEP "x86" OS_SEP "atanh.c", + "math" OS_SEP "x86" OS_SEP "atanhf.c", + "math" OS_SEP "x86" OS_SEP "atanhl.c", + "math" OS_SEP "x86" OS_SEP "atanl.c", + "math" OS_SEP "x86" OS_SEP "ceilf.S", + "math" OS_SEP "x86" OS_SEP "ceill.S", + "math" OS_SEP "x86" OS_SEP "ceil.S", + "math" OS_SEP "x86" OS_SEP "_chgsignl.S", + "math" OS_SEP "x86" OS_SEP "copysignl.S", + "math" OS_SEP "x86" OS_SEP "cos.c", + "math" OS_SEP "x86" OS_SEP "cosf.c", + "math" OS_SEP "x86" OS_SEP "cosl.c", + "math" OS_SEP "x86" OS_SEP "cosl_internal.S", + "math" OS_SEP "x86" OS_SEP "cossin.c", + "math" OS_SEP "x86" OS_SEP "exp2f.S", + "math" OS_SEP "x86" OS_SEP "exp2l.S", + "math" OS_SEP "x86" OS_SEP "exp2.S", + "math" OS_SEP "x86" OS_SEP "exp.c", + "math" OS_SEP "x86" OS_SEP "expl.c", + "math" OS_SEP "x86" OS_SEP "expm1.c", + "math" OS_SEP "x86" OS_SEP "expm1f.c", + "math" OS_SEP "x86" OS_SEP "expm1l.c", + "math" OS_SEP "x86" OS_SEP "floorf.S", + "math" OS_SEP "x86" OS_SEP "floorl.S", + "math" OS_SEP "x86" OS_SEP "floor.S", + "math" OS_SEP "x86" OS_SEP "fmod.c", + "math" OS_SEP "x86" OS_SEP "fmodf.c", + "math" OS_SEP "x86" OS_SEP "fmodl.c", + "math" OS_SEP "x86" OS_SEP "frexpl.S", + "math" OS_SEP "x86" OS_SEP "fucom.c", + "math" OS_SEP "x86" OS_SEP "ilogbf.S", + "math" OS_SEP "x86" OS_SEP "ilogbl.S", + "math" OS_SEP "x86" OS_SEP "ilogb.S", + "math" OS_SEP "x86" OS_SEP "internal_logl.S", + "math" OS_SEP "x86" OS_SEP "ldexp.c", + "math" OS_SEP "x86" OS_SEP "ldexpl.c", + "math" OS_SEP "x86" OS_SEP "log10l.S", + "math" OS_SEP "x86" OS_SEP "log1pf.S", + "math" OS_SEP "x86" OS_SEP "log1pl.S", + "math" OS_SEP "x86" OS_SEP "log1p.S", + "math" OS_SEP "x86" OS_SEP "log2f.S", + "math" OS_SEP "x86" OS_SEP "log2l.S", + "math" OS_SEP "x86" OS_SEP "log2.S", + "math" OS_SEP "x86" OS_SEP "logb.c", + "math" OS_SEP "x86" OS_SEP "logbf.c", + "math" OS_SEP "x86" OS_SEP "logbl.c", + "math" OS_SEP "x86" OS_SEP "log.c", + "math" OS_SEP "x86" OS_SEP "logl.c", + "math" OS_SEP "x86" OS_SEP "nearbyintf.S", + "math" OS_SEP "x86" OS_SEP "nearbyintl.S", + "math" OS_SEP "x86" OS_SEP "nearbyint.S", + "math" OS_SEP "x86" OS_SEP "pow.c", + "math" OS_SEP "x86" OS_SEP "powl.c", + "math" OS_SEP "x86" OS_SEP "remainderf.S", + "math" OS_SEP "x86" OS_SEP "remainderl.S", + "math" OS_SEP "x86" OS_SEP "remainder.S", + "math" OS_SEP "x86" OS_SEP "remquof.S", + "math" OS_SEP "x86" OS_SEP "remquol.S", + "math" OS_SEP "x86" OS_SEP "remquo.S", + "math" OS_SEP "x86" OS_SEP "scalbnf.S", + "math" OS_SEP "x86" OS_SEP "scalbnl.S", + "math" OS_SEP "x86" OS_SEP "scalbn.S", + "math" OS_SEP "x86" OS_SEP "sin.c", + "math" OS_SEP "x86" OS_SEP "sinf.c", + "math" OS_SEP "x86" OS_SEP "sinl.c", + "math" OS_SEP "x86" OS_SEP "sinl_internal.S", + "math" OS_SEP "x86" OS_SEP "tanf.c", + "math" OS_SEP "x86" OS_SEP "tanl.S", + "math" OS_SEP "x86" OS_SEP "truncf.S", + "math" OS_SEP "x86" OS_SEP "trunc.S", +}; + +static const char *mingwex_arm32_src[] = { + "math" OS_SEP "arm" OS_SEP "_chgsignl.S", + "math" OS_SEP "arm" OS_SEP "ceil.S", + "math" OS_SEP "arm" OS_SEP "ceilf.S", + "math" OS_SEP "arm" OS_SEP "ceill.S", + "math" OS_SEP "arm" OS_SEP "copysignl.c", + "math" OS_SEP "arm" OS_SEP "exp2.c", + "math" OS_SEP "arm" OS_SEP "floor.S", + "math" OS_SEP "arm" OS_SEP "floorf.S", + "math" OS_SEP "arm" OS_SEP "floorl.S", + "math" OS_SEP "arm" OS_SEP "ldexpl.c", + "math" OS_SEP "arm" OS_SEP "log2.c", + "math" OS_SEP "arm" OS_SEP "nearbyint.S", + "math" OS_SEP "arm" OS_SEP "nearbyintf.S", + "math" OS_SEP "arm" OS_SEP "nearbyintl.S", + "math" OS_SEP "arm" OS_SEP "scalbn.c", + "math" OS_SEP "arm" OS_SEP "sincos.c", + "math" OS_SEP "arm" OS_SEP "trunc.S", + "math" OS_SEP "arm" OS_SEP "truncf.S", +}; + +static const char *mingwex_arm64_src[] = { + "math" OS_SEP "arm64" OS_SEP "ceilf.S", + "math" OS_SEP "arm64" OS_SEP "ceill.S", + "math" OS_SEP "arm64" OS_SEP "ceil.S", + "math" OS_SEP "arm64" OS_SEP "_chgsignl.S", + "math" OS_SEP "arm64" OS_SEP "copysignl.c", + "math" OS_SEP "arm64" OS_SEP "exp2f.S", + "math" OS_SEP "arm64" OS_SEP "exp2.S", + "math" OS_SEP "arm64" OS_SEP "floorf.S", + "math" OS_SEP "arm64" OS_SEP "floorl.S", + "math" OS_SEP "arm64" OS_SEP "floor.S", + "math" OS_SEP "arm64" OS_SEP "ldexpl.c", + "math" OS_SEP "arm64" OS_SEP "log2.c", + "math" OS_SEP "arm64" OS_SEP "nearbyintf.S", + "math" OS_SEP "arm64" OS_SEP "nearbyintl.S", + "math" OS_SEP "arm64" OS_SEP "nearbyint.S", + "math" OS_SEP "arm64" OS_SEP "scalbn.c", + "math" OS_SEP "arm64" OS_SEP "sincos.c", + "math" OS_SEP "arm64" OS_SEP "truncf.S", + "math" OS_SEP "arm64" OS_SEP "trunc.S", +}; + struct LinkJob { CodeGen *codegen; ZigList args; @@ -570,73 +1107,6 @@ static const char *build_musl(CodeGen *parent) { return buf_ptr(&child_gen->output_file_path); } -static const char *msvcrt_common_src[] = { - "misc" OS_SEP "onexit_table.c", - "misc" OS_SEP "register_tls_atexit.c", - "stdio" OS_SEP "acrt_iob_func.c", - "misc" OS_SEP "_configthreadlocale.c", - "misc" OS_SEP "_get_current_locale.c", - "misc" OS_SEP "invalid_parameter_handler.c", - "misc" OS_SEP "output_format.c", - "misc" OS_SEP "purecall.c", - "secapi" OS_SEP "_access_s.c", - "secapi" OS_SEP "_cgets_s.c", - "secapi" OS_SEP "_cgetws_s.c", - "secapi" OS_SEP "_chsize_s.c", - "secapi" OS_SEP "_controlfp_s.c", - "secapi" OS_SEP "_cprintf_s.c", - "secapi" OS_SEP "_cprintf_s_l.c", - "secapi" OS_SEP "_ctime32_s.c", - "secapi" OS_SEP "_ctime64_s.c", - "secapi" OS_SEP "_cwprintf_s.c", - "secapi" OS_SEP "_cwprintf_s_l.c", - "secapi" OS_SEP "_gmtime32_s.c", - "secapi" OS_SEP "_gmtime64_s.c", - "secapi" OS_SEP "_localtime32_s.c", - "secapi" OS_SEP "_localtime64_s.c", - "secapi" OS_SEP "_mktemp_s.c", - "secapi" OS_SEP "_sopen_s.c", - "secapi" OS_SEP "_strdate_s.c", - "secapi" OS_SEP "_strtime_s.c", - "secapi" OS_SEP "_umask_s.c", - "secapi" OS_SEP "_vcprintf_s.c", - "secapi" OS_SEP "_vcprintf_s_l.c", - "secapi" OS_SEP "_vcwprintf_s.c", - "secapi" OS_SEP "_vcwprintf_s_l.c", - "secapi" OS_SEP "_vscprintf_p.c", - "secapi" OS_SEP "_vscwprintf_p.c", - "secapi" OS_SEP "_vswprintf_p.c", - "secapi" OS_SEP "_waccess_s.c", - "secapi" OS_SEP "_wasctime_s.c", - "secapi" OS_SEP "_wctime32_s.c", - "secapi" OS_SEP "_wctime64_s.c", - "secapi" OS_SEP "_wstrtime_s.c", - "secapi" OS_SEP "_wmktemp_s.c", - "secapi" OS_SEP "_wstrdate_s.c", - "secapi" OS_SEP "asctime_s.c", - "secapi" OS_SEP "memcpy_s.c", - "secapi" OS_SEP "memmove_s.c", - "secapi" OS_SEP "rand_s.c", - "secapi" OS_SEP "sprintf_s.c", - "secapi" OS_SEP "strerror_s.c", - "secapi" OS_SEP "vsprintf_s.c", - "secapi" OS_SEP "wmemcpy_s.c", - "secapi" OS_SEP "wmemmove_s.c", - "stdio" OS_SEP "mingw_lock.c", -}; - -static const char *msvcrt_i386_src[] = { - "misc" OS_SEP "lc_locale_func.c", - -}; - -static const char *msvcrt_other_src[] = { - "misc" OS_SEP "__p___argv.c", - "misc" OS_SEP "__p__acmdln.c", - "misc" OS_SEP "__p__fmode.c", - "misc" OS_SEP "__p__wcmdln.c", -}; - static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) { CFile *c_file = allocate(1); c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s", @@ -645,7 +1115,7 @@ static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *s c_file->args.append("-D__LIBMSVCRT__"); c_file->args.append("-I"); - c_file->args.append(path_from_libc(parent, "mingw" OS_SEP "include" OS_SEP)); + c_file->args.append(path_from_libc(parent, "mingw" OS_SEP "include")); c_file->args.append("-std=gnu99"); c_file->args.append("-D_CRTBLD"); @@ -661,6 +1131,31 @@ static void add_msvcrt_os_dep(CodeGen *parent, CodeGen *child_gen, const char *s child_gen->c_source_files.append(c_file); } +static void add_mingwex_os_dep(CodeGen *parent, CodeGen *child_gen, const char *src_path) { + CFile *c_file = allocate(1); + c_file->source_path = buf_ptr(buf_sprintf("%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s", + buf_ptr(parent->zig_lib_dir), src_path)); + c_file->args.append("-DHAVE_CONFIG_H"); + + c_file->args.append("-I"); + c_file->args.append(path_from_libc(parent, "mingw")); + + c_file->args.append("-I"); + c_file->args.append(path_from_libc(parent, "mingw" OS_SEP "include")); + + c_file->args.append("-std=gnu99"); + c_file->args.append("-D_CRTBLD"); + c_file->args.append("-D_WIN32_WINNT=0x0f00"); + c_file->args.append("-D__MSVCRT_VERSION__=0x700"); + c_file->args.append("-g"); + c_file->args.append("-O2"); + + c_file->args.append("-isystem"); + c_file->args.append(path_from_libc(parent, "include" OS_SEP "any-windows-any")); + + child_gen->c_source_files.append(c_file); +} + static const char *get_libc_crt_file(CodeGen *parent, const char *file) { if (parent->libc == nullptr && parent->zig_target->os == OsWindows) { if (strcmp(file, "crt2.obj") == 0) { @@ -759,6 +1254,32 @@ static const char *get_libc_crt_file(CodeGen *parent, const char *file) { } codegen_build_and_link(child_gen); return buf_ptr(&child_gen->output_file_path); + } else if (strcmp(file, "mingwex.lib") == 0) { + CodeGen *child_gen = create_child_codegen(parent, nullptr, OutTypeLib, nullptr); + codegen_set_out_name(child_gen, buf_create_from_str("mingwex")); + + for (size_t i = 0; i < array_length(mingwex_generic_src); i += 1) { + add_mingwex_os_dep(parent, child_gen, mingwex_generic_src[i]); + } + if (parent->zig_target->arch == ZigLLVM_x86 || parent->zig_target->arch == ZigLLVM_x86_64) { + for (size_t i = 0; i < array_length(mingwex_x86_src); i += 1) { + add_mingwex_os_dep(parent, child_gen, mingwex_x86_src[i]); + } + } else if (target_is_arm(parent->zig_target)) { + if (target_arch_pointer_bit_width(parent->zig_target->arch) == 32) { + for (size_t i = 0; i < array_length(mingwex_arm32_src); i += 1) { + add_mingwex_os_dep(parent, child_gen, mingwex_arm32_src[i]); + } + } else { + for (size_t i = 0; i < array_length(mingwex_arm64_src); i += 1) { + add_mingwex_os_dep(parent, child_gen, mingwex_arm64_src[i]); + } + } + } else { + zig_unreachable(); + } + codegen_build_and_link(child_gen); + return buf_ptr(&child_gen->output_file_path); } else { zig_unreachable(); } @@ -1555,6 +2076,7 @@ static void add_mingw_link_args(LinkJob *lj, bool is_library) { } lj->args.append(get_libc_crt_file(g, "mingw32.lib")); + lj->args.append(get_libc_crt_file(g, "mingwex.lib")); lj->args.append(get_libc_crt_file(g, "msvcrt-os.lib")); lj->args.append(get_def_lib(g, "msvcrt", "mingw" OS_SEP "lib-common" OS_SEP "msvcrt.def.in")); lj->args.append(get_def_lib(g, "kernel32", "mingw" OS_SEP "lib-common" OS_SEP "kernel32.def.in")); @@ -2089,3 +2611,4 @@ void codegen_link(CodeGen *g) { exit(1); } } +