mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +00:00
Since nan() is supposed to work the same as strtod("nan(...)", NULL),
my original implementation made both use the same code. Unfortunately, this meant libm depended on a vendor header at compile time and previously- unexposed vendor bits in libc at runtime. Hence, I just wrote my own version of the relevant vendor routine. As it turns out, mine has a factor of 8 fewer of lines of code, and is a bit more readable anyway. The strtod() and *scanf() routines still use vendor code. Reviewed by: bde
This commit is contained in:
parent
b96ebbf2e8
commit
7cd4a83267
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=174759
@ -71,7 +71,4 @@ FBSDprivate_1.0 {
|
||||
_end;
|
||||
__sys_vfork;
|
||||
_vfork;
|
||||
|
||||
/* used in libm */
|
||||
__ULtox_D2A;
|
||||
};
|
||||
|
@ -68,7 +68,4 @@ FBSDprivate_1.0 {
|
||||
_brk;
|
||||
.curbrk;
|
||||
.minbrk;
|
||||
|
||||
/* used in libm */
|
||||
__ULtox_D2A;
|
||||
};
|
||||
|
@ -69,7 +69,4 @@ FBSDprivate_1.0 {
|
||||
minbrk;
|
||||
.cerror;
|
||||
curbrk;
|
||||
|
||||
/* used in libm */
|
||||
__ULtox_D2A;
|
||||
};
|
||||
|
@ -96,7 +96,4 @@ FBSDprivate_1.0 {
|
||||
|
||||
/* used in src/lib/csu/sparc64/crt1.c */
|
||||
__sparc_utrap_setup;
|
||||
|
||||
/* used in libm */
|
||||
__ULtoQ_D2A;
|
||||
};
|
||||
|
@ -29,19 +29,18 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "fpmath.h"
|
||||
#include "../../../contrib/gdtoa/gdtoaimp.h"
|
||||
#include "../src/math_private.h"
|
||||
|
||||
long double
|
||||
nanl(const char *s)
|
||||
{
|
||||
static FPI fpi = { 113, -16494, 16271, 1, SI };
|
||||
union {
|
||||
union IEEEl2bits ieee;
|
||||
uint32_t bits[4];
|
||||
} u;
|
||||
|
||||
union IEEEl2bits result;
|
||||
ULong bits[2];
|
||||
int k;
|
||||
|
||||
s--;
|
||||
k = hexnan(&s, &fpi, bits);
|
||||
ULtoQ((UShort *)&result.e, bits, 16272, k);
|
||||
return (result.e);
|
||||
_scan_nan(u.bits, 4, s);
|
||||
u.ieee.bits.exp = 0x7fff;
|
||||
u.ieee.bits.manh |= 1 << 47; /* make it a quiet NaN */
|
||||
return (u.ieee.e);
|
||||
}
|
||||
|
@ -29,19 +29,18 @@
|
||||
#include <math.h>
|
||||
|
||||
#include "fpmath.h"
|
||||
#include "../../../contrib/gdtoa/gdtoaimp.h"
|
||||
#include "../src/math_private.h"
|
||||
|
||||
long double
|
||||
nanl(const char *s)
|
||||
{
|
||||
static FPI fpi = { 64, -16445, 16320, 1, SI };
|
||||
union {
|
||||
union IEEEl2bits ieee;
|
||||
uint32_t bits[3];
|
||||
} u;
|
||||
|
||||
union IEEEl2bits result;
|
||||
ULong bits[2];
|
||||
int k;
|
||||
|
||||
s--;
|
||||
k = hexnan(&s, &fpi, bits);
|
||||
ULtox((UShort *)&result.e, bits, 16321, k);
|
||||
return (result.e);
|
||||
_scan_nan(u.bits, 3, s);
|
||||
u.ieee.bits.exp = 0x7fff;
|
||||
u.ieee.bits.manh |= 0xc0000000; /* make it a quiet NaN */
|
||||
return (u.ieee.e);
|
||||
}
|
||||
|
@ -154,6 +154,11 @@ do { \
|
||||
(d) = sf_u.value; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Common routine to process the arguments to nan(), nanf(), and nanl().
|
||||
*/
|
||||
void _scan_nan(uint32_t *__words, int __num_words, const char *__s);
|
||||
|
||||
#ifdef _COMPLEX_H
|
||||
/*
|
||||
* Inline functions that can be used to construct complex values.
|
||||
|
@ -26,39 +26,83 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/endian.h>
|
||||
#include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include "../../../contrib/gdtoa/gdtoaimp.h"
|
||||
#include "math_private.h"
|
||||
|
||||
/*
|
||||
* Scan a string of hexadecimal digits (the format nan(3) expects) and
|
||||
* make a bit array (using the local endianness). We stop when we
|
||||
* encounter an invalid character, NUL, etc. If we overflow, we do
|
||||
* the same as gcc's __builtin_nan(), namely, discard the high order bits.
|
||||
*
|
||||
* The format this routine accepts needs to be compatible with what is used
|
||||
* in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in
|
||||
* __builtin_nan(). In fact, we're only 100% compatible for strings we
|
||||
* consider valid, so we might be violating the C standard. But it's
|
||||
* impossible to use nan(3) portably anyway, so this seems good enough.
|
||||
*/
|
||||
void
|
||||
_scan_nan(uint32_t *words, int num_words, const char *s)
|
||||
{
|
||||
int si; /* index into s */
|
||||
int bitpos; /* index into words (in bits) */
|
||||
|
||||
bzero(words, num_words * sizeof(uint32_t));
|
||||
|
||||
/* Allow a leading '0x'. (It's expected, but redundant.) */
|
||||
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
|
||||
s += 2;
|
||||
|
||||
/* Scan forwards in the string, looking for the end of the sequence. */
|
||||
for (si = 0; isxdigit(s[si]); si++)
|
||||
;
|
||||
|
||||
/* Scan backwards, filling in the bits in words[] as we go. */
|
||||
#if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) {
|
||||
#else
|
||||
for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) {
|
||||
#endif
|
||||
if (--si < 0)
|
||||
break;
|
||||
words[bitpos / 32] |= digittoint(s[si]) << (bitpos % 32);
|
||||
}
|
||||
}
|
||||
|
||||
double
|
||||
nan(const char *s)
|
||||
{
|
||||
static FPI fpi = { 52, -1074, 971, 1, SI };
|
||||
union {
|
||||
double d;
|
||||
uint32_t bits[2];
|
||||
} u;
|
||||
|
||||
double result;
|
||||
ULong bits[2];
|
||||
|
||||
s--;
|
||||
hexnan(&s, &fpi, bits);
|
||||
SET_HIGH_WORD(result, 0x7ff80000 | bits[1]);
|
||||
SET_LOW_WORD(result, bits[0]);
|
||||
return (result);
|
||||
_scan_nan(u.bits, 2, s);
|
||||
#if _BYTE_ORDER == _LITTLE_ENDIAN
|
||||
u.bits[1] |= 0x7ff80000;
|
||||
#else
|
||||
u.bits[0] |= 0x7ff80000;
|
||||
#endif
|
||||
return (u.d);
|
||||
}
|
||||
|
||||
float
|
||||
nanf(const char *s)
|
||||
{
|
||||
static FPI fpi = { 24, -149, 104, 1, SI };
|
||||
union {
|
||||
float f;
|
||||
uint32_t bits[1];
|
||||
} u;
|
||||
|
||||
float result;
|
||||
ULong bits[1];
|
||||
|
||||
s--;
|
||||
hexnan(&s, &fpi, bits);
|
||||
SET_FLOAT_WORD(result, 0x7fc00000 | bits[0]);
|
||||
return (result);
|
||||
_scan_nan(u.bits, 1, s);
|
||||
u.bits[0] |= 0x7fc00000;
|
||||
return (u.f);
|
||||
}
|
||||
|
||||
#if (LDBL_MANT_DIG == 53)
|
||||
|
Loading…
Reference in New Issue
Block a user