gcc - C++ Decimal Floating Point Erroneous Rounding -


i seeing strange behavior when attempting use libdfp in c++ program. specifically, appears if gcc rounding 8 decimal places, when use 64- , 128-bit decimal types.

to test this, created incredibly simple test program:

std::decimal::decimal64 testval = 0.044575289999999997dd; printf("decimal float test: expected=0.044575289999999997, actual=%.16da\n", testval); 

which outputs:

decimal float test: expected=0.044575289999999997, actual=0.04457529000000000 

i not printing problem in libdfp able trace source , found number rounded first line of printf handler. additionally, printf handler round, have verified code not being called.

for reference, building libdfp with:

./configure --with-backend=libdecnumber --enable-decimal-float=bid && make 

i suspect problem either in underlying decimal float representation (bid, in case) or raw types being provided gcc. looks if being rounded size of 32-bit decimal float. host arch x86_64 should supported natively. furthermore, gcc have corresponding _decimal[32|64|128] types , <decimal/decimal> can found on system. building on fedora 25 native x86_64 cpu (intel xenon). afaik, processor not have native decimal float support being rendered in software.

the clue have gcc not list --enable-decimal-float build option in configuration summary:

$ g++ -v using built-in specs. collect_gcc=g++ collect_lto_wrapper=/usr/libexec/gcc/x86_64-redhat-linux/6.3.1/lto-wrapper target: x86_64-redhat-linux configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux thread model: posix gcc version 6.3.1 20161221 (red hat 6.3.1-1) (gcc)  $ g++ --version g++ (gcc) 6.3.1 20161221 (red hat 6.3.1-1) copyright (c) 2016 free software foundation, inc. free software; see source copying conditions.  there no warranty; not merchantability or fitness particular purpose. 

that being said, compiler does define _decimal[32|64|128] types , provides operator<< overloads them. wouldn't expect these available @ if such support not enabled. shouldn't able compile program using them , almost valid output back.

finally, see being problem libdecnumber @ limit of current knowledge manages assignment these types.

has seen issue before? failing that, has build , used libdfp on similar setup? piece of software controls rounding internal representation (as opposed rounding display)?


edit

i managed disassembly. appears full value being loaded rdx , decimal64 constructor called. value 0x2fafd619589efa00 works out 3436200445056317952 in decimal, suspect 0.044575289999999997 represented in bid format. not sure how gcc knows used bid vs dpd specified @ libfdp build time, leave particular mystery post.

if understanding correct, seems imply gcc doing rounding. there can done other rebuilding compiler (which avoid)? know ieee-754 provides mechanisms 'tune' behavior of fp operations (including rounding mode), gcc expose of user?

disassembly

   │0x401180 <main(int, char**)>    push   rbp                                                                                                        │    │0x401181 <main(int, char**)+1>  mov    rbp,rsp                                                                                                    │    │0x401184 <main(int, char**)+4>  sub    rsp,0x30                                                                                                   │    │0x401188 <main(int, char**)+8>  mov    dword ptr [rbp-0x14],edi                                                                                   │    │0x40118b <main(int, char**)+11> mov    qword ptr [rbp-0x20],rsi                                                                                   │ b+ │0x40118f <main(int, char**)+15> movabs rdx,0x2fafd619589efa00                                                                                     │    │0x401199 <main(int, char**)+25> lea    rax,[rbp-0x10]                                                                                             │    │0x40119d <main(int, char**)+29> mov    qword ptr [rbp-0x28],rdx                                                                                   │    │0x4011a1 <main(int, char**)+33> movq   xmm0,qword ptr [rbp-0x28]                                                                                  │    │0x4011a6 <main(int, char**)+38> mov    rdi,rax                                                                                                    │    │0x4011a9 <main(int, char**)+41> call   0x4012e6 <std::decimal::decimal64::decimal64(decimal64)>                                                   │    │0x4011ae <main(int, char**)+46> mov    rax,qword ptr [rbp-0x10]                                                                                   │    │0x4011b2 <main(int, char**)+50> mov    qword ptr [rbp-0x28],rax                                                                                   │    │0x4011b6 <main(int, char**)+54> movq   xmm0,qword ptr [rbp-0x28]                                                                                  │    │0x4011bb <main(int, char**)+59> mov    edi,0x4018e8                                                                                               │    │0x4011c0 <main(int, char**)+64> mov    eax,0x1                                                                                                    │    │0x4011c5 <main(int, char**)+69> call   0x400a30 <printf@plt>                                                                                      │    │0x4011ca <main(int, char**)+74>                                         mov    eax,0x0                                                            │    │0x4011cf <main(int, char**)+79>                                         leave                                                                     │    │0x4011d0 <main(int, char**)+80>                                         ret                                                                       │    │0x4011d1 <__static_initialization_and_destruction_0(int, int)>          push   rbp                                                                │    │0x4011d2 <__static_initialization_and_destruction_0(int, int)+1>        mov    rbp,rsp                                                            │    │0x4011d5 <__static_initialization_and_destruction_0(int, int)+4>────────sub    rsp,0x10───────────────────────────────────────────────────────────│    │0x4011d9 <__static_initialization_and_destruction_0(int, int)+8>        mov    dword ptr [rbp-0x4],edi                                            │    │0x4011dc <__static_initialization_and_destruction_0(int, int)+11>       mov    dword ptr [rbp-0x8],esi                                            │    │0x4011df <__static_initialization_and_destruction_0(int, int)+14>       cmp    dword ptr [rbp-0x4],0x1                                            │    │0x4011e3 <__static_initialization_and_destruction_0(int, int)+18>       jne    0x40120c <__static_initialization_and_destruction_0(int, int)+59>  │    │0x4011e5 <__static_initialization_and_destruction_0(int, int)+20>       cmp    dword ptr [rbp-0x8],0xffff                                         │    │0x4011ec <__static_initialization_and_destruction_0(int, int)+27>       jne    0x40120c <__static_initialization_and_destruction_0(int, int)+59>  │    │0x4011e5 <__static_initialization_and_destruction_0(int, int)+20>       cmp    dword ptr [rbp-0x8],0xffff                                         │    │0x4011ec <__static_initialization_and_destruction_0(int, int)+27>       jne    0x40120c <__static_initialization_and_destruction_0(int, int)+59>  │    │0x4011ee <__static_initialization_and_destruction_0(int, int)+29>       mov    edi,0x60309d                                                       │    │0x4011f3 <__static_initialization_and_destruction_0(int, int)+34>       call   0x400ae0 <_znst8ios_base4initc1ev@plt>                             │    │0x4011f8 <__static_initialization_and_destruction_0(int, int)+39>       mov    edx,0x4018d8                                                       │    │0x4011fd <__static_initialization_and_destruction_0(int, int)+44>       mov    esi,0x60309d                                                       │    │0x401202 <__static_initialization_and_destruction_0(int, int)+49>       mov    edi,0x400aa0                                                       │    │0x401207 <__static_initialization_and_destruction_0(int, int)+54>       call   0x400ac0 <__cxa_atexit@plt>                                        │ 

complete test source

#include <float.h> #include <decimal/decimal> #include <math.h> #include <fenv.h> #include <stdlib.h> #include <wchar.h> #include <cstdlib>  int main (int argc, char *argv[]) {     std::decimal::decimal64 testval = 0.044575289999999997dd;     printf("decimal float test: expected=0.044575289999999997, actual=%.16da\n", testval);      return exit_success; } 


Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -