avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-libc-dev] [bug #1929] -Inf not detected


From: Dmitry K.
Subject: Re: [avr-libc-dev] [bug #1929] -Inf not detected
Date: Wed, 8 Jun 2005 09:46:55 +1100
User-agent: KMail/1.5

On Tuesday 07 June 2005 14:21, Dmitry K. wrote:
...
> 4.
> Avr-libc's functions 'isnan' and 'isinf' are not conform to other
> library. For example, next program is failed in AVR/avr-libc:
>
> ---------------------------------------
> #include <float.h>
> #include <math.h>
> volatile double vx;
>
> int main ()
> {
>     vx = DBL_MAX;
>     vx = vx * vx;       /* overflow must        */
>
>     if (!isinf(vx) && !isnan(vx))
>         return 1;       /* error: vx is not detekted, as non-normal     */
>
>     return 0;
> }
> ---------------------------------------
>
> 5.
> 'isinf', probably, should return always 0 as arithmetics with Inf is not
> realized.
>
> I have write a corrected variant 'isnan' (7 words only). I shall send it
> after testing.

Rationale for `isnan': it must return non-zero value for all numbers, that
are rejected by libm/avr-libc.

isnan.s (Without extra info lines):
---------------------------------------------
    .text
    .global     isnan
isnan:
        lsl     r24
        rol     r25             ; r25 := exponent
        cpi     r25, 0xff       ; C set, if not equal
        ldi     r25, 0
        ldi     r24, 1
        sbci    r24, 0
        ret
    .end
---------------------------------------------

Small test for isnan:
---------------------------------------------
#include <float.h>
#include <math.h>
#include <stdlib.h>

volatile union {
    long lo;
    float fl;
} vx1, vx2;

void t_isnan (double x, int testno)
{
    /* Is 'x' rejected by avr-libc?     */
    vx1.fl = x / 2.0;
    vx2.fl = vx1.fl / 2.0;
    if (vx2.lo != vx1.lo)       /* force pure comparison        */
        exit(0x0100 + testno);          /* 'x' is not rejected  */

    if (!isnan(x))
        exit(0x200 + testno);           /* isnan() is not work  */
}

void t_isnormal (double x, int testno)
{
    /* Indirect checking: is 'x' a normal number?       */
    vx1.fl = x / 2.0;
    vx2.fl = vx1.fl / 2.0;
    if (vx2.lo == vx1.lo) {     /* force pure comparison        */
        if (vx2.fl != 0)
            exit(0x0300 + testno);      /* 'x' is not rejected  */
    }

    if (isnan(x))
        exit(0x400 + testno);           /* isnan() is not work  */
}

int main ()
{
    static union {
        long lo;
        float fl;
    } x1[] = {                          /* NaNs */
        { 0x7fc0ffff }, { 0xffc0ffff },
        { 0x7f800000 }, { 0xff800000 },
        { 0x7fffffff }, { 0xffffffff },
    };
    static union {
        long lo;
        float fl;
    } x2[] = {                          /* not NaNs     */
        { 0x00000000 }, { 0x80000000 },
        { 0x00800000 }, { 0x80800000 },
        { 0x3f800000 }, { 0xbf800000 },
        { 0x3fffffff }, { 0xbfffffff },
    };
    int i;

    for (i = 0; i < (int)(sizeof(x1)/sizeof(x1[0])); i++)
        t_isnan (x1[i].fl, i+1);
    for (i = 0; i < (int)(sizeof(x2)/sizeof(x2[0])); i++)
        t_isnormal (x2[i].fl, i+1);
    return 0;
}
-------------------------------------------------------------------

Dmitry.





reply via email to

[Prev in Thread] Current Thread [Next in Thread]