| As always, it helps to specify the compiler version and OS version.
But with DEC C V5.5-002 on OpenVMS Alpha V6.2-1H3, what happens is
that compiling with the specified qualifiers causes HUGE_VAL to be
#defined to decc$gt_dbl_infinity, which is a double variable containing
an IEEE Infinity bit pattern. The atof function, however, appears to
be returning the largest representable finite double value instead of
Infinity.
|
| First of all, both ANSI C and XPG4 specify atof behavior on error as
undefined, so, generally, speaking, the customer should not rely on any
errno or HUGE_VAL when using atof.
ANSI C says:
The functions atof, atoi and atol need not affect the value of the
integer expression errno on an error. If the value of the result
cannot be represented, the behavior is undefined.
The same can be found in XPG4.
Unfortunately, :-) the DEC C RTL implementation of atof acts just as a
wrapper to strtod. In contrast to atof, the strtod *must* return plus or
minus HUGE_VAL and set errno to ERANGE if the value to be converted is
outside the range of representable values.
The strtod - like behavior on error is documented in the description of
atof in the DEC C RTL Manual, so the program in .0 must behave the same
for the default G_FLOAT floating point and for IEEE floating point.
Actually, what happened is that while building the CRTL, the IEEE-flavour
of atof() routine is compiled with /FLOAT=IEEE_FLOAT without /IEEE qualifier,
i.e. in default /IEEE=FAST IEEE mode.
The HUGE_VAL is defined in <math.h> as follows:
/*
** Define HUGE_VAL
*/
#if __G_FLOAT
# define HUGE_VAL 8.988465674311578540726371186585e+307
# define __MAXFLOAT 1.7014117e+38f
#elif __IEEE_FLOAT
# ifdef _IEEE_FP
extern double decc$gt_dbl_infinity;
# define HUGE_VAL decc$gt_dbl_infinity
# else
# define HUGE_VAL 1.7976931348623158e+308
# endif
# define __MAXFLOAT 3.40282347e+38f
#else
# ifdef __ALPHA
# define HUGE_VAL 1.70141183460469213e+38
# else
# define HUGE_VAL 1.70141183460469229e+38
# endif
# define __MAXFLOAT 1.7014117e+38f
#endif
I have no idea why _IEEE_FP macro is not defined in /IEEE=FAST IEEE mode.
The fact is that _IEEE_FP macro is defined for /IEEE_MODE=DENORM_RESULT
and is not defined for default /IEEE=FAST mode, so for IEEE-flavour of atof()
function the HUGE_VAL is 1.7976931348623158e+308. The function detects
overflow, sets errno to ERANGE and returns its HUGE_VAL, but for the test
program in .0, compiled with /IEEE_MODE=DENORM_RESULT, the HUGE_VAL is
decc$gt_dbl_infinity and these two HUGE_VALues are different.
I'm not sure if this a bug in the header, in the compiler or in the DEC C RTL.
Boris
X.C
===
#if __IEEE_FLOAT
# ifdef _IEEE_FP
extern double decc$gt_dbl_infinity;
# define HUGE_VAL decc$gt_dbl_infinity
# else
# define HUGE_VAL 1.7976931348623158e+308
# endif
# define __MAXFLOAT 3.40282347e+38f
#endif
$ cc/ver/noobj _nl0:
DEC C V5.0-003 on OpenVMS Alpha V6.2-1H1
$ cc/float=ieee/lis/show=all x.c
Source Listing 7-MAR-1997 01:13:26 DEC C V5.0-003 Page 1
7-MAR-1997 01:12:12 ENG17:[BORIS]X.C;3
1 #if __IEEE_FLOAT
2 # ifdef _IEEE_FP
X 3 extern double decc$gt_dbl_infinity;
X 4 # define HUGE_VAL decc$gt_dbl_infinity
X 5 # else
6 # define HUGE_VAL 1.7976931348623158e+308
7 # endif
8 # define __MAXFLOAT 3.40282347e+38f
9 #endif
$ cc/float=ieee/ieee=denorm/lis/show=all x.c
Source Listing 7-MAR-1997 01:14:23 DEC C V5.0-003 Page 1
7-MAR-1997 01:12:12 ENG17:[BORIS]X.C;3
1 #if __IEEE_FLOAT
2 # ifdef _IEEE_FP
3 extern double decc$gt_dbl_infinity;
4 # define HUGE_VAL decc$gt_dbl_infinity
5 # else
X 6 # define HUGE_VAL 1.7976931348623158e+308
X 7 # endif
8 # define __MAXFLOAT 3.40282347e+38f
9 #endif
|
| Boris, I think this is an example where the CRTL needs to be sensitive to
the mode in which the caller is compiled. If the caller is /IEEE=FAST,
it can't cope with infinities (or denorms), and you should return the value
you're returning today. If the caller is /IEEE=DENORM, you should return
infinity for overflow, and you should be able to return denorms too.
There are flags in the procedure descriptor that tell what mode a routine
was compiled in. It looks as if strtod needs to look at these flags when
it encounters an exceptional condition. atod needs to be compiled in the
mode that says "look at my caller's mode instead of mine." For more
information on how to do all this, talk to Jeff RTL::Arnold in the DPML group.
|