[Mingw-w64-public] Wrong output from %La specifier in printf()?
When the `%La` specifier is used in `printf()` to format the C99 hexdecimal floating point value `0x5p-80l`, a wrong result is generated, as shown in this example: E:\Desktop>cat test.c extern int __mingw_printf(const char *, ...); int main(){ __mingw_printf("%La\n", 0x5p-80l); } E:\Desktop>gcc test.c -std=c99 E:\Desktop>a.exe 0x0p-141 Removing the `__mingw_` prefix and testing the same program on Linux gives the correct result: lh_mouse@lhmouse-dev:~$ uname -a Linux lhmouse-dev 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux lh_mouse@lhmouse-dev:~$ gcc test.c -std=c99 lh_mouse@lhmouse-dev:~$ ./a.out 0xap-81 Is this a bug in `printf()`? -- Best regards, lh_mouse 2016-09-09 -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH 1/4] winstorecompat: Add a GetStartupInfo stub
On 9/8/2016 10:36 AM, Hugo Beauzée-Luyssen wrote: > This only happens when building with -lwindowsapp (see another patch of > mine). When building with the default -lkernel32, all is good, since > kernel32.lib contains GetStartupInfo. > windowsapp.lib, on the other hand, doesn't; which makes sense since the > symbol is forbidden. > Since the issue only happens when building test program within > configure, it seemed ok to add a stub for it. I'm not opposed to the idea of a stub for GetStartupInfo. I assume your plan is to add it to libwindowsapp.a? I'm guessing the idea is we want to avoid having to customize the startup code and that sounds like a good idea. I'm also thinking some comments to explain what is going on for future maintainers might be a good idea. Cuz this is gonna look a bit odd (ie why are we calling a function that doesn't do anything?). If the expectation is that the code never gets called, it may even make sense to have the stub call abort() (or its winstore-appropriate equivalent) instead of the memset. Configure doesn't actually run any of the programs it builds, does it? dw -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH 1/4] winstorecompat: Add a GetStartupInfo stub
On 09/08/2016 07:21 PM, David Wohlferd wrote: > On 9/7/2016 2:19 PM, Hugo Beauzée-Luyssen wrote: >>> Is this to deal with the fact that __tmainCRTStartup uses it? >> Exactly. In the end, the function won't be used since __tmainCRTStartup >> won't be used for a windows store app, but we still need the configure >> scripts to be able to compile executables. > > I haven't experimented with winstore. What configure parameters are you > using? > > dw > > -- > ___ > Mingw-w64-public mailing list > Mingw-w64-public@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/mingw-w64-public > This only happens when building with -lwindowsapp (see another patch of mine). When building with the default -lkernel32, all is good, since kernel32.lib contains GetStartupInfo. windowsapp.lib, on the other hand, doesn't; which makes sense since the symbol is forbidden. Since the issue only happens when building test program within configure, it seemed ok to add a stub for it. Regards, -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH 1/4] winstorecompat: Add a GetStartupInfo stub
On 9/7/2016 2:19 PM, Hugo Beauzée-Luyssen wrote: >> Is this to deal with the fact that __tmainCRTStartup uses it? > Exactly. In the end, the function won't be used since __tmainCRTStartup > won't be used for a windows store app, but we still need the configure > scripts to be able to compile executables. I haven't experimented with winstore. What configure parameters are you using? dw -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] [PATCH] Added standard-conforming fmaf(), fma() and fmal() functions.
Oops. Are there any volunteers to implement `fma()` functions for ARM ? -- Best regards, lh_mouse 2016-09-08 -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
[Mingw-w64-public] [PATCH] Added standard-conforming fmaf(), fma() and fmal() functions.
--- mingw-w64-crt/Makefile.am | 4 ++-- mingw-w64-crt/math/fma.S | 42 mingw-w64-crt/math/fma.c | 12 ++ mingw-w64-crt/math/fmaf.S | 43 - mingw-w64-crt/math/fmaf.c | 10 mingw-w64-crt/math/fmal.c | 61 ++- 6 files changed, 84 insertions(+), 88 deletions(-) delete mode 100644 mingw-w64-crt/math/fma.S create mode 100644 mingw-w64-crt/math/fma.c delete mode 100644 mingw-w64-crt/math/fmaf.S create mode 100644 mingw-w64-crt/math/fmaf.c diff --git a/mingw-w64-crt/Makefile.am b/mingw-w64-crt/Makefile.am index 886fcf0..1c6e534 100644 --- a/mingw-w64-crt/Makefile.am +++ b/mingw-w64-crt/Makefile.am @@ -244,7 +244,6 @@ src_libmingwex=\ \ math/_chgsignl.S math/ceil.Smath/ceilf.S math/ceill.S math/copysignl.S \ math/floor.S math/floorf.S math/floorl.S \ - math/fma.Smath/fmaf.S\ math/nearbyint.S math/nearbyintf.S math/nearbyintl.S \ math/trunc.S math/truncf.S \ math/cbrt.c \ @@ -252,7 +251,8 @@ src_libmingwex=\ math/coshf.c math/coshl.c math/erfl.c \ math/expf.c \ math/fabs.c math/fabsf.c math/fabsl.c math/fdim.c math/fdimf.c math/fdiml.c \ - math/fmal.c math/fmax.cmath/fmaxf.c math/fmaxl.c math/fmin.c math/fminf.c \ + math/fma.cmath/fmaf.cmath/fmal.c \ + math/fmax.c math/fmaxf.c math/fmaxl.c math/fmin.c math/fminf.c \ math/fminl.c math/fp_consts.c math/fp_constsf.c \ math/fp_constsl.c math/fpclassify.c math/fpclassifyf.c math/fpclassifyl.c math/frexpf.c\ math/hypotf.c math/hypot.c math/hypotl.c math/isnan.c math/isnanf.cmath/isnanl.c\ diff --git a/mingw-w64-crt/math/fma.S b/mingw-w64-crt/math/fma.S deleted file mode 100644 index 74becde..000 --- a/mingw-w64-crt/math/fma.S +++ /dev/null @@ -1,42 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public 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 "fma.S" - .text -#ifdef __x86_64__ - .align 8 -#else - .align 4 -#endif - .p2align 4,,15 - .globl __MINGW_USYMBOL(fma) - .def__MINGW_USYMBOL(fma); .scl2; .type 32; .endef -__MINGW_USYMBOL(fma): -#if defined(_AMD64_) || defined(__x86_64__) - subq$56, %rsp - movsd %xmm0,(%rsp) - movsd %xmm1,16(%rsp) - movsd %xmm2,32(%rsp) - fldl(%rsp) - fmull 16(%rsp) - fldl32(%rsp) - faddp - fstpl (%rsp) - movsd (%rsp),%xmm0 - addq$56, %rsp - ret -#elif defined(_ARM_) || defined(__arm__) - fmacd d2, d0, d1 - fcpyd d0, d2 - bx lr -#elif defined(_X86_) || defined(__i386__) - fldl4(%esp) - fmull 12(%esp) - fldl20(%esp) - faddp - ret -#endif diff --git a/mingw-w64-crt/math/fma.c b/mingw-w64-crt/math/fma.c new file mode 100644 index 000..3703e00 --- /dev/null +++ b/mingw-w64-crt/math/fma.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. + */ +long double fmal ( long double _x, long double _y, long double _z); + +double +fma ( double _x, double _y, double _z) +{ + return (double)fmal(_x, _y, _z); +} diff --git a/mingw-w64-crt/math/fmaf.S b/mingw-w64-crt/math/fmaf.S deleted file mode 100644 index 6bc7ef0..000 --- a/mingw-w64-crt/math/fmaf.S +++ /dev/null @@ -1,43 +0,0 @@ -/** - * This file has no copyright assigned and is placed in the Public 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 "fmaf.S" - .text -#ifdef __x86_64__ - .align 8 -#else - .align 2 -#endif - .p2align 4,,15 - .globl __MINGW_USYMBOL(fmaf) - .def__MINGW_USYMBOL(fmaf); .scl2; .type 32; .endef -__MINGW_USYMBOL(fmaf): -#if defined(_AMD64_) || defined(__x86_64__) - subq$56, %rsp - movss %xmm0,(%rsp) - movss %xmm1,16(%rsp) - movss %xmm2,32(%rsp) - flds(%rsp) - fmuls 16(%rsp) - flds32(%rsp) - faddp - fstps (%rsp) - movss (%rsp),%xmm0 - addq$56, %rsp - ret -#elif defined(_ARM_) || defined(__arm__) - fmacs s2, s0, s1 - fcpys s0, s2 - bx
Re: [Mingw-w64-public] sinl/cosl/tanl accuracy problem
Thanks for such nice work! I hope someone would accept it. Kai has been away for days. -- Best regards, lh_mouse 2016-09-08 - 发件人:Thomas Bickel发送日期:2016-09-08 21:01 收件人:mingw-w64-public 抄送: 主题:Re: [Mingw-w64-public] sinl/cosl/tanl accuracy problem On 07.09.2016 17:21, lhmouse wrote: > (I don't write AT assembly so I am unable to make a patch. > Nevertheless I hope someone who writes AT assembly could fix it.) I don't have time to write a patch but I can donate some code that AFAIK does what you need for the sin functions. >gcc -m32 sinl32.s sin.c >a sinl = -5.421010862427522170037264e-020 my_sinl = -0.e+000 sin = 1.224606353822377258211418e-016 my_sin = 1.225148454908620010428422e-016 sinf = -8.7422776573475858e-008 my_sinf = -8.7422780003674585e-008 >gcc -m64 sinl64.s sin.c >a sinl = -5.421010862427522170037264e-020 my_sinl = -0.e+000 sin = 1.224606353822377258211418e-016 my_sin = 1.225148454908620010428422e-016 sinf = -8.7422776573475858e-008 my_sinf = -8.7422776573475858e-008 Regards Thomas -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] sinl/cosl/tanl accuracy problem
On 07.09.2016 17:21, lhmouse wrote: (I don't write AT assembly so I am unable to make a patch. Nevertheless I hope someone who writes AT assembly could fix it.) I don't have time to write a patch but I can donate some code that AFAIK does what you need for the sin functions. >gcc -m32 sinl32.s sin.c >a sinl = -5.421010862427522170037264e-020 my_sinl = -0.e+000 sin = 1.224606353822377258211418e-016 my_sin = 1.225148454908620010428422e-016 sinf = -8.7422776573475858e-008 my_sinf = -8.7422780003674585e-008 >gcc -m64 sinl64.s sin.c >a sinl = -5.421010862427522170037264e-020 my_sinl = -0.e+000 sin = 1.224606353822377258211418e-016 my_sin = 1.225148454908620010428422e-016 sinf = -8.7422776573475858e-008 my_sinf = -8.7422776573475858e-008 Regards Thomas #define __USE_MINGW_ANSI_STDIO 1 #include #include #if defined(__x86_64__) extern long double my_sinl64(long double x); extern double my_sin64(double x); extern float my_sinf64(float x); #else extern long double __cdecl my_sinl32(long double x); extern double __cdecl my_sin32(double x); extern float __cdecl my_sinf32(float x); #endif void main() { const long double thetal = atanl(1.0l) * 4.0l; printf(" sinl = %.24Le\n", sinl(thetal)); #if defined(__x86_64__) printf("my_sinl = %.24Le\n", my_sinl64(thetal)); #else printf("my_sinl = %.24Le\n", my_sinl32(thetal)); #endif printf(" sin = %.24le\n", sin((double)thetal)); #if defined(__x86_64__) printf("my_sin = %.24le\n", my_sin64((double)thetal)); #else printf("my_sin = %.24le\n", my_sin32((double)thetal)); #endif printf(" sinf = %.16e\n", sinf((float)thetal)); #if defined(__x86_64__) printf("my_sinf = %.16e\n", my_sinf64((float)thetal)); #else printf("my_sinf = %.16e\n", my_sinf32((float)thetal)); #endif } .macro M_FSIN 2: fprem1 fnstsw %ax sahf jp 2b fstp%st(1) fsin testw $0x200, %ax jz 1f fchs 1: .endm .text .align 4 .globl _my_sinl32 _my_sinl32: fldpi fldt4(%esp) M_FSIN ret .align 4 .globl _my_sin32 _my_sin32: fldpi fldl4(%esp) M_FSIN ret .align 4 .globl _my_sinf32 _my_sinf32: fldpi flds4(%esp) M_FSIN ret .macro M_FSIN 2: fprem1 fnstsw %ax sahf jp 2b fstp%st(1) fsin testw $0x200, %ax jz 1f fchs 1: .endm .text .globl my_sinl64 my_sinl64: fldpi fldt(%rdx) M_FSIN movq%rcx, %rax fstpt (%rcx) ret .globl my_sin64 my_sin64: fldpi movsd %xmm0, 8(%rsp) fldl8(%rsp) M_FSIN fstpl 8(%rsp) movsd 8(%rsp), %xmm0 ret .globl my_sinf64 my_sinf64: fldpi movss %xmm0, 8(%rsp) flds8(%rsp) M_FSIN fstps 8(%rsp) movss 8(%rsp), %xmm0 ret -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
[Mingw-w64-public] `fma()` functions are completely wrong in mingw-w64
Reading `mingw-w64/mingw-w64-crt/math/fmal.c`: long double fmal ( long double _x, long double _y, long double _z) { return ((_x * _y) + _z); } This implementation is completely wrong. https://en.wikipedia.org/wiki/Multiply–accumulate_operation#Fused_multiply.E2.80.93add The multiplication in a single FMA operation must behave as if the result had infinite precision. That is, multiplying two x87-extended-precision floating point numbers (1 sign + 15 exp + 64 frac = 80 bits) yields a result of 144 bits (1 sign + 15 exp + 64 frac * 2 = 144 bits). For example, with a conforming `fmal()`, the expression `fmal(1.2l, 3.4l, -3.00010l)` shall yield approximately `8e-18`, because `1.2l * 3.4l` yields `3.000108l`. But in mingw-w64, this indeterminate result is truncated when converted to `long double`, yielding `3.0001l`, and adding `-3.00010l` to it yields zero. Since x87 does not have 128-bit registers, FMA must be done in software: 1. Split both multiplier into higher and lower parts. Since a `long double` has 64 significant bits (it does not have a hidden bit), either of the two parts has to have 32 bits so we don't get precision losses when multiplying them. 2. Keeping in mind that `(a+b)(c+d)=ac+ad+bc+bd`, calculate the sum IN THE FOLLOWING ORDER: long double ret = z; ret += xhi * yhi; ret += xhi * ylo + xlo * yhi; ret += xlo * ylo; A conforming implementation can be found here: https://github.com/lhmouse/MCF/blob/master/MCFCRT/src/stdc/math/fma.c -- Best regards, lh_mouse 2016-09-08 -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] sinl/cosl/tanl accuracy problem
It is merely a function guaranteed to be declared implicitly (thus requires no ) and has the same semantics with the standard function `sinl()`. The GCC optimizer can perform certain types of optimization such as constant folding and inlining only if `fsinl()` is supposed to do the same thing as specified by the C standard, which could be explicitly disabled using `-fno-builtin` or `-ffreestanding`. AFAICS there is otherwise no difference. `__builtin_fsinl()` may result in a call to `sinl()`. -- Best regards, lh_mouse 2016-09-08 - 发件人:NightStrike发送日期:2016-09-08 15:06 收件人:mingw-w64-public@lists.sourceforge.net 抄送: 主题:Re: [Mingw-w64-public] sinl/cosl/tanl accuracy problem What does gcc's __builtin_sinl() do? -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public
Re: [Mingw-w64-public] sinl/cosl/tanl accuracy problem
What does gcc's __builtin_sinl() do? On Wed, Sep 7, 2016 at 11:37 PM, lhmousewrote: > If performance is the problem there are a number of solutions such as > inline assembly, static lookup tables, etc. `fsinl()` is apparently not one > of them. > But yes, I am all ears > > -- > Best regards, > lh_mouse > 2016-09-08 > > - > 发件人:Riot > 发送日期:2016-09-08 04:00 > 收件人:mingw-w64-public > 抄送: > 主题:Re: [Mingw-w64-public] sinl/cosl/tanl accuracy problem > > Some of us (game developers especially) greatly prefer a minor inaccuracy > to a potentially major slowdown; I would personally opposed this change, as > you're noticeably increasing the cost of something that's used heavily in > tightly looped code. Perhaps an appropriately named #ifdef switch would be > a way to please everyone here? > > Regards, > Riot > > > -- > ___ > Mingw-w64-public mailing list > Mingw-w64-public@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/mingw-w64-public -- ___ Mingw-w64-public mailing list Mingw-w64-public@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/mingw-w64-public