X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=numeric.c;h=d15fdbdd75fe3f56c5bc1358a25ddc5ffabbf57c;hb=1cc8b4c566f7901a54e4b576f09608beb4c81f86;hp=8d94975f1df70ee869acce098f1e13af26a599af;hpb=a24374368d9ca399370d0bbf60ebc0aa16225436;p=p5sagit%2Fp5-mst-13.2.git diff --git a/numeric.c b/numeric.c index 8d94975..d15fdbd 100644 --- a/numeric.c +++ b/numeric.c @@ -572,24 +572,43 @@ S_mulexp10(NV value, I32 exponent) negative = 1; exponent = -exponent; } -#ifdef __VAX /* avoid %SYSTEM-F-FLTOVF_F sans VAXC$ESTABLISH */ -# if defined(__DECC_VER) && __DECC_VER <= 50390006 - /* __F_FLT_MAX_10_EXP - 5 == 33 */ + + /* On OpenVMS VAX we by default use the D_FLOAT double format, + * and that format does not have *easy* capabilities [1] for + * overflowing doubles 'silently' as IEEE fp does. We also need + * to support G_FLOAT on both VAX and Alpha, and though the exponent + * range is much larger than D_FLOAT it still doesn't do silent + * overflow. Therefore we need to detect early whether we would + * overflow (this is the behaviour of the native string-to-float + * conversion routines, and therefore of native applications, too). + * + * [1] Trying to establish a condition handler to trap floating point + * exceptions is not a good idea. */ +#if defined(VMS) && !defined(__IEEE_FP) && defined(NV_MAX_10_EXP) if (!negative && - (log10(value) + exponent) >= (__F_FLT_MAX_10_EXP - 5)) + (log10(value) + exponent) >= (NV_MAX_10_EXP)) return NV_MAX; -# endif #endif -#if defined(__alpha) && defined(__unix__) + + /* In UNICOS and in certain Cray models (such as T90) there is no + * IEEE fp, and no way at all from C to catch fp overflows gracefully. + * There is something you can do if you are willing to use some + * inline assembler: the instruction is called DFI-- but that will + * disable *all* floating point interrupts, a little bit too large + * a hammer. Therefore we need to catch potential overflows before + * it's too late. */ +#if defined(_UNICOS) && defined(NV_MAX_10_EXP) if (!negative && - (log10(value) + exponent) >= (DBL_MAX_10_EXP)) - return NV_INF; + (log10(value) + exponent) >= NV_MAX_10_EXP) + return NV_MAX; #endif + for (bit = 1; exponent; bit <<= 1) { if (exponent & bit) { exponent ^= bit; result *= power; } + /* Floating point exceptions are supposed to be turned off. */ power *= power; } return negative ? value / result : value * result;