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.