ceill(0.9) returns 0 instead of 1 ?

classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

ceill(0.9) returns 0 instead of 1 ?

Assaf Gordon
Hello,

On OpenBSD-5.7/amd64 (under qemu/kvm), I'm getting incorrect results
when using ceill(3). For values between 0 and 1, the returned value
is 0, while I'd expected it to be 1. Using ceil(3) does return 1 as
expected. Is this my incorrect usage or a bug?
any advice/comment will be appreciated.

To reproduce:

    $ cat 1.c
    #include <math.h>
    #include <stdio.h>
    int main()
    {
        long double d;
        printf("d    ceill(d) ceil(d)\n");
        for (d = 0.3; d <= 3.8; d+=0.5)
                printf("%-4Lg %-8Lg %-5g\n",
                        d, ceill(d), ceil((double)d));
        return 0;
    }

    $ gcc -g -O0 -Wall -Wextra -o 1 1.c -lm
    $ ./1
    d    ceill(d) ceil(d)
    0.3  0        1        <----
    0.8  0        1        <----
    1.3  2        2
    1.8  2        2
    2.3  3        3
    2.8  3        3
    3.3  4        4

Thanks,
  - assaf

Reply | Threaded
Open this post in threaded view
|

Re: ceill(0.9) returns 0 instead of 1 ?

Matthew Martin-2
Same with 5.7 under virtualbox.

On 8/6/15, Assaf Gordon <[hidden email]> wrote:

> Hello,
>
> On OpenBSD-5.7/amd64 (under qemu/kvm), I'm getting incorrect results
> when using ceill(3). For values between 0 and 1, the returned value
> is 0, while I'd expected it to be 1. Using ceil(3) does return 1 as
> expected. Is this my incorrect usage or a bug?
> any advice/comment will be appreciated.
>
> To reproduce:
>
>     $ cat 1.c
>     #include <math.h>
>     #include <stdio.h>
>     int main()
>     {
>         long double d;
>         printf("d    ceill(d) ceil(d)\n");
>         for (d = 0.3; d <= 3.8; d+=0.5)
>                 printf("%-4Lg %-8Lg %-5g\n",
>                         d, ceill(d), ceil((double)d));
>         return 0;
>     }
>
>     $ gcc -g -O0 -Wall -Wextra -o 1 1.c -lm
>     $ ./1
>     d    ceill(d) ceil(d)
>     0.3  0        1        <----
>     0.8  0        1        <----
>     1.3  2        2
>     1.8  2        2
>     2.3  3        3
>     2.8  3        3
>     3.3  4        4
>
> Thanks,
>   - assaf

Reply | Threaded
Open this post in threaded view
|

Re: ceill(0.9) returns 0 instead of 1 ?

Chris Cappuccio
Graham Stephens [[hidden email]] wrote:
> Your code runs fine under the gcc version in OpenBSD 5.3.
>

So you get 1 and not 0 from the top two lines of ceill output?

Nothing has changed in /usr/src/lib/libm/src/ld80/s_ceill.c since
5.3 and the supporting headers have not changed in a way that should
affect ceill.

I get '0' with both current system GCC and ports clang. This requires
stepping through each line of ceill to see where things go haywire.

I gotta say, the asm implemetnation of ceil seems much easier to follow
than the C implementation of ceill.

Reply | Threaded
Open this post in threaded view
|

Re: ceill(0.9) returns 0 instead of 1 ?

Nick Permyakov
In reply to this post by Assaf Gordon
Assaf Gordon <assafgordon <at> gmail.com> writes:

>
> Hello,
>
> On OpenBSD-5.7/amd64 (under qemu/kvm), I'm getting incorrect results
> when using ceill(3). For values between 0 and 1, the returned value
> is 0, while I'd expected it to be 1. Using ceil(3) does return 1 as
> expected. Is this my incorrect usage or a bug?
> any advice/comment will be appreciated.
>

It's a bug in the libm library. The 80-bit extended precision format has an
explicit leading bit for the integer part of a significand. Thus the line

    else if((i0|i1)!=0) { se=0x3fff;i0=0;i1=0;}

in /src/lib/libm/src/ld80/s_ceill.c should read

    else if((i0|i1)!=0) { se=0x3fff;i0=0x80000000;i1=0;}

or simpler still

    else if((i0|i1)!=0) { return 1.0L; }

Best regards,
Nick Permyakov