[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.