raspberrypi / pico-sdk

BSD 3-Clause "New" or "Revised" License
3.67k stars 913 forks source link

Floating point subnormals are not handled correctly #1582

Open dpgeorge opened 9 months ago

dpgeorge commented 9 months ago

It seems that subnormal floats are not handled by the ROM float routines, and the pico-sdk wrappers don't account for this.

Code to reproduce on pico-sdk 1.5.1 (EDIT: fixed typo where it used to say one = 0):

#include <math.h>

static void pr(float f_in) {
    volatile float f = f_in;
    const uint8_t *b = (void *)&f;
    printf("%02x:%02x:%02x:%02x\n", b[0], b[1], b[2], b[3]);
}

int main(int argc, char **argv) {
    stdio_init_all();

    union {
        volatile float f;
        volatile uint32_t i;
    } x;
    volatile float zero = 0;
    volatile float one = 1;

    x.i = 29972;
    pr(x.f);
    pr(x.f + zero);
    pr(x.f * one);

    x.i = 2997220;
    pr(x.f);
    pr(x.f + zero);
    pr(x.f * one);

    return 0;
}

Output is:

14:75:00:00
00:00:00:00
00:00:00:00
e4:bb:2d:00
00:00:00:00
00:00:00:00

It should be:

14:75:00:00
14:75:00:00
14:75:00:00
e4:bb:2d:00
e4:bb:2d:00
e4:bb:2d:00

Above are just some simple examples, but most other operations on subnormals also return incorrect results (according to IEEE).

lurch commented 9 months ago

volatile float one = 0; Is that a bug, or just a typo? :wink:

dpgeorge commented 9 months ago

Is that a bug, or just a typo?

Ooops! That's a typo. I just tested it again with the fixed typo and the output is as in the original post (ie the subnormal bug is there).

dpgeorge commented 9 months ago

Note that the volatile's are necessary, otherwise the compiler can optimise things away.