[uClibc] Is there a workaround for this floating point bug?

Erik Andersen andersen at codepoet.org
Sun Aug 10 03:46:13 UTC 2003


On Sat Aug 09, 2003 at 06:44:26PM -0700, David Wuertele wrote:
> The bug demonstrated by the program below is a showstopper for my
> project.  If I can't fix it or find a workaround, I'll have to trash
> all my porting efforts and move back to glibc.  Can anyone out there
> reproduce it?  Does anyone have any ideas how I might work around it?

Are you _certain_ you do not see this with glibc?  Did you
compile glibc yourself using the same compiler you are using for
uClibc.  I suspect either your kernel or your compiler are
broken.

> Add equal parts mipsel, gcc-3.3, and uClibc to the program below and
> stir.  Serve on your favorite embedded system.

BTW, you really do not need to post your test app three times.
Once was plenty...  Your test app had a few little errors which I
fixed up.  Several sucessful trial runs on my mipsel test box
follow.  The last test is run inside the uClibc development
system for mips, available from the uClibc website. 


$ uname -a
Linux phoenix 2.4.21-pre4 #1 Fri Jun 13 01:36:16 MDT 2003 mips unknown unknown GNU/Linux
$ cat /proc/cpuinfo 
system type             : MIPS Cobalt
processor               : 0
cpu model               : Nevada V10.0  FPU V10.0
BogoMIPS                : 249.03
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 48
extra interrupt vector  : yes
hardware watchpoint     : no
VCED exceptions         : not available
VCEI exceptions         : not available
$
$
$ cat test.c 
#include <stdio.h>

int main ()       
{
    double thisdub = (double)0.1;
    if (thisdub != (double)0.1) { 
        fprintf (stderr, "doubles are hosed!\n"); 
        return 0;  
    }
    fprintf (stderr, "if %f and %f don't both equal 0.100000,"
            "suspect fprintf\n", (float)thisdub, (float)0.1);
    unsigned long height1 = 120;                                                               
    unsigned long height2 = 1200;
    float scale1 = (float)height1 / (float)height2;
    //double scale2 = (double)height1 / (double)height2;
    double height3 = height2 * scale1;                
    unsigned long height4 = (unsigned long) height3;
    fprintf (stderr, "if %f and %f aren't close to %lu, "
        "suspect float operations\n", 
        (float)height3, (float)height4, height1);
    return 0;                           
}
$ gcc --version | head -n1
gcc (GCC) 3.3 (Debian)
$ gcc -Wall -Os test.c -o test
$ ldd ./test
        libc.so.6 => /lib/libc.so.6 (0x2ab04000)
        /lib/ld.so.1 => /lib/ld.so.1 (0x2aaa8000)
$ ./test 
if 0.100000 and 0.100000 don't both equal 0.100000, suspect fprintf
if 120.000000 and 120.000000 aren't close to 120, suspect float operations
$
$
$ /usr/mipsel-linux-uclibc/bin/mipsel-uclibc-gcc --version | head -n1
gcc-3.3 (GCC) 3.3 (Debian)
$ /usr/mipsel-linux-uclibc/bin/mipsel-uclibc-gcc -Wall -Os test.c -o test
$ ldd ./test
        libc.so.0 => /usr/mipsel-linux-uclibc/lib/libc.so.0 (0x2aaee000)
        ld-uClibc.so.0 => /usr/mipsel-linux-uclibc/lib/ld-uClibc.so.0 (0x2aaa8000)
$ ./test 
if 0.100000 and 0.100000 don't both equal 0.100000, suspect fprintf
if 120.000000 and 120.000000 aren't close to 120, suspect float operations
$
$
$ cp test.c ~/CVS/buildroot/build_mipsel/root/root/
$ cd ~/CVS/buildroot/
$ sudo chroot build_mipsel/root
# gcc --version | head -n 1
gcc (GCC) 3.3
# ldd /usr/bin/gcc
        libc.so.0 => /lib/libc.so.0 (0x2aaee000)
        ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x2aaa8000)
# cd /root
# gcc -Wall -Os test.c -o test
# ./test 
if 0.100000 and 0.100000 don't both equal 0.100000, suspect fprintf
if 120.000000 and 120.000000 aren't close to 120, suspect float operations

 -Erik

--
Erik B. Andersen             http://codepoet-consulting.com/
--This message was written using 73% post-consumer electrons--



More information about the uClibc mailing list