#1169 PIC16 floating-point multiply bug (small numbers)

closed-fixed
Maarten Brock
5
2013-05-25
2006-07-12
Mark Rages
No

I ran into this bug while trying to implement a
moving-average IIR filter on a PIC18F4550.

I expect the following code to output numbers
descending toward "0.0".

void main() {

float fpnum=1.0;

InitializeUSART();

while (1) {
fpnum*=0.01;

printf_small(" %f\n",fpnum);
}
}

But what I get is this:
0.01
0.0001
0.000001
0.
0.
0.
0.
0.
0.
0.
0.
0.
0.
0.
0.
0.
0.
0.
0.
-0.
-0.
-0.
-0.
-0.
-0.
-0.
-0.
-0.
-0.
-0.
-0.
-2097152.
-2435456.
-292096.
-1579200.
-115792.
-1157.919922
-11.579199
-0.115792
-0.001158
-0.000012
-0.
-0.
-0.
-0.
-0.

and so forth. The excursion into negative territory
repeats periodically forever. See attached file
"output.log".

Another data point: If I start the code at 0.0, the
output remains at 0.0 forever. This is the expected
result.

$ sdcc -v
SDCC :
mcs51/gbz80/z80/avr/ds390/pic16/pic14/TININative/xa51/ds400/hc08
2.6.0 #4290 (Jul 11 2006) (UNIX)

Discussion

  • Mark Rages
    Mark Rages
    2006-07-12

    This is the whole project, Makefile, objects and all. See "output.log" for the first 100 lines of serial output.

     
    Attachments
  • Mark Rages
    Mark Rages
    2006-07-12

    • labels: --> 608414
     
  • Mark Rages
    Mark Rages
    2006-07-14

    Logged In: YES
    user_id=11637

    Here is a mail I sent to sdcc-user:

    The floating point routine in fsmul.c does not handle
    denormalized numbers well. I discovered this by doing:

    float f=1.0;
    while (1) {
    f*=0.25;
    }

    I expected f to decay to zero, but instead it wrapped around
    to a huge number! From looking at the source
    (device/lib/pic16/libsdcc/float/fsmul.c, but similar code
    for other architectures) I see there is no attemp at bounds
    checking when the exponents are being added together. So
    multiplying two numbers with very negative exponents can
    wrap to a very large positive exponent. It is also possible
    to get an infinite result, since the IEEE standard dedicates
    an exponent value to this.

    I found the source code's ancestor in GCC (3.3 or earlier).
    This code has the same problem in the multiply routine.
    Most GCC platforms have hardware floating-point support, so
    the code isn't used.

    In my code, I can work around this:

    #define SMALL_NUMBER 0.000001
    float f=1.0;
    while (1) {
    if (f<SMALL_NUMBER) f=0.0; // see
    http://thedailywtf.com/forums/71684/showpost.aspx
    else f*=0.25;
    }

    I post this as a warning to others: Beware the floating
    point routines when you have numbers that may be close to zero!

    Regards,
    Mark
    markrages@gmail

     
  • Logged In: YES
    user_id=589052

    thank you for the excellent report!

    Unfortunately the bug is not limited to PIC16. The mcs51
    also has it.

    I'd see this report as a candidate for a release critical bug?

     
    • labels: 608414 --> Run Time Library
     
  • Borut Ražem
    Borut Ražem
    2006-07-24

    Logged In: YES
    user_id=568035

    > I'd see this report as a candidate for a release critical
    bug?

    If it is an old bug, I then we can postpone it.
    If it is a new one:
    if it is a new functionality, introduced after 2.5.0, I
    think we can make a release without fixing it
    if it is an old functionality which worked in 2.5.0, then
    we are in troubles :-(

    Frieder and Mark Rages: can you please verify the status of
    this bug ASAP?

    Borut

     
  • Mark Rages
    Mark Rages
    2006-07-24

    Logged In: YES
    user_id=11637

    I'd like to set up for regression tests and write a test for
    this. Is there any documentation for the regression test suite?

     
  • Logged In: YES
    user_id=589052

    Hello Mark,

    Yep, you'll find the doc for the regression tests at
    http://sdcc.sourceforge.net/doc/test_suite_spec.pdf

    but, to avoid duplicate work, the bug can be reproduced in
    the regression tests with:

    ---------8<------------------------------------------
    /* bug1520966 "Floating-point bug with small numbers"
    */

    #include <testfwk.h>
    #include <math.h>

    void
    testFloatOp(void)
    {
    volatile float a,b;
    float result;

    a = 2.04e-38;
    b = 0.01;
    result = a * b;
    ASSERT( fabsf(result) < 1.0e36 );
    ASSERT( fabsf(result) < a );

    b = 100;
    result = a / b;
    ASSERT( fabsf(result) < a );
    }
    --------->8------------------------------------------

    > So I don't think it's a new bug.

    Yes, I verified 2.5.0 is also affected. So it's not a new
    bug. (And apparently few people seriously use floating point
    with SDCC.)

    Unfortunately it affects TWO of the four basic math
    operations: Multiply and Divide.

    Most likely, as multiply and divide are also used within the
    transcendental math routines there will be cases where this
    propagates into the transcendental routines.

     
  •  
    Attachments
  • Maarten Brock
    Maarten Brock
    2006-07-24

    Logged In: YES
    user_id=888171

    There's a document in your doc directory but it doesn't
    help much. It's not difficult though as long as you use
    some sort of unix (linux, cygwin, osx). Native windows
    cannot run the used simulator.

    1) Get a source copy of SDCC either as a snapshot or
    direct through subversion.
    2) run ./configure and make
    3) cd to support/regression
    4) run make

    'make clean' removes most generated files so you can start
    anew. If you have any more questions post them in the
    devel-list.

     
  • Maarten Brock
    Maarten Brock
    2006-07-24

    Logged In: YES
    user_id=888171

    There's a document in your doc directory but it doesn't
    help much. It's not difficult though as long as you use
    some sort of unix (linux, cygwin, osx). Native windows
    cannot run the used simulator.

    1) Get a source copy of SDCC either as a snapshot or
    direct through subversion.
    2) run ./configure and make
    3) cd to support/regression
    4) run make

    'make clean' removes most generated files so you can start
    anew. If you have any more questions post them in the
    devel-list.

     
  • Mark Rages
    Mark Rages
    2006-07-24

    Logged In: YES
    user_id=11637

    Thank you both for helping.

    That regression test looks good to me.

    Now, when's the bug going to get fixed...

    ;)

     
  • Maarten Brock
    Maarten Brock
    2006-07-25

    Logged In: YES
    user_id=888171

    I've got a solution for the C variants of __fsmul and
    __fsdiv. But not yet for the asm optimized verions. I also
    do not know if there are more places that have this bug.

    It all boils down to detecting overflow and underflow of
    the exponent and returning INF or 0.0.

    When I have the asm fixed I will commit.

     
  • Maarten Brock
    Maarten Brock
    2006-07-25

    • assigned_to: nobody --> maartenbrock
     
  • Borut Ražem
    Borut Ražem
    2006-07-25

    • assigned_to: maartenbrock --> nobody
     
  • Borut Ražem
    Borut Ražem
    2006-07-25

    Logged In: YES
    user_id=568035

    Since is an old bug, if won't be fixed in sdcc 2.6.0 release.

    > I found the source code's ancestor in GCC (3.3 or earlier).

    The current gcc implementation is in
    gcc/config/soft-fp/mulsf3.c. It should be verified if the
    bug is fixed in the latest version and borrow the fix.
    Unfortunately the new code is highly macro driven and
    published under LGPL with runtime exception. I doubt that we
    can use the same source file without modifications. But
    maybe we can get the permission from FSF to modify it and
    reuse in under the same license...

    Borut

     
  • Borut Ražem
    Borut Ražem
    2006-07-25

    Logged In: YES
    user_id=568035

    The last two messages were written almost in the same time,
    so I saw Maartens message only after I submitted mine.

    Maarten, it is great to hear that you have a solution. If
    you'll fix it in time, it will be included in the release.

    Borut

     
  • Maarten Brock
    Maarten Brock
    2006-07-26

    • milestone: --> fixed
    • assigned_to: nobody --> maartenbrock
    • status: open --> closed-fixed
     
  • Maarten Brock
    Maarten Brock
    2006-07-26

    Logged In: YES
    user_id=888171

    Thank you. At first I interpreted your message as: don't
    touch, we are at code freeze.

    Anyway, it's fixed now in SDCC #4303.
    But I think there are a lot more of these issues in the
    floating point library.