s_nan.c (7cd4a832675ea6d396dcb5f7688ac58f4b4645c6) | s_nan.c (4b6b5744552e9cdf01eb22407dee9277a379476c) |
---|---|
1/*- 2 * Copyright (c) 2007 David Schultz 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 | 1/*- 2 * Copyright (c) 2007 David Schultz 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 12 unchanged lines hidden (view full) --- 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 |
29#include <sys/endian.h> 30#include <ctype.h> | |
31#include <float.h> 32#include <math.h> | 29#include <float.h> 30#include <math.h> |
33#include <stdint.h> 34#include <strings.h> | |
35 | 31 |
32#include "../../../contrib/gdtoa/gdtoaimp.h" |
|
36#include "math_private.h" 37 | 33#include "math_private.h" 34 |
38/* 39 * Scan a string of hexadecimal digits (the format nan(3) expects) and 40 * make a bit array (using the local endianness). We stop when we 41 * encounter an invalid character, NUL, etc. If we overflow, we do 42 * the same as gcc's __builtin_nan(), namely, discard the high order bits. 43 * 44 * The format this routine accepts needs to be compatible with what is used 45 * in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in 46 * __builtin_nan(). In fact, we're only 100% compatible for strings we 47 * consider valid, so we might be violating the C standard. But it's 48 * impossible to use nan(3) portably anyway, so this seems good enough. 49 */ 50void 51_scan_nan(uint32_t *words, int num_words, const char *s) 52{ 53 int si; /* index into s */ 54 int bitpos; /* index into words (in bits) */ 55 56 bzero(words, num_words * sizeof(uint32_t)); 57 58 /* Allow a leading '0x'. (It's expected, but redundant.) */ 59 if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) 60 s += 2; 61 62 /* Scan forwards in the string, looking for the end of the sequence. */ 63 for (si = 0; isxdigit(s[si]); si++) 64 ; 65 66 /* Scan backwards, filling in the bits in words[] as we go. */ 67#if _BYTE_ORDER == _LITTLE_ENDIAN 68 for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) { 69#else 70 for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) { 71#endif 72 if (--si < 0) 73 break; 74 words[bitpos / 32] |= digittoint(s[si]) << (bitpos % 32); 75 } 76} 77 | |
78double 79nan(const char *s) 80{ | 35double 36nan(const char *s) 37{ |
81 union { 82 double d; 83 uint32_t bits[2]; 84 } u; | 38 static FPI fpi = { 52, -1074, 971, 1, SI }; |
85 | 39 |
86 _scan_nan(u.bits, 2, s); 87#if _BYTE_ORDER == _LITTLE_ENDIAN 88 u.bits[1] |= 0x7ff80000; 89#else 90 u.bits[0] |= 0x7ff80000; 91#endif 92 return (u.d); | 40 double result; 41 ULong bits[2]; 42 43 s--; 44 hexnan(&s, &fpi, bits); 45 SET_HIGH_WORD(result, 0x7ff80000 | bits[1]); 46 SET_LOW_WORD(result, bits[0]); 47 return (result); |
93} 94 95float 96nanf(const char *s) 97{ | 48} 49 50float 51nanf(const char *s) 52{ |
98 union { 99 float f; 100 uint32_t bits[1]; 101 } u; | 53 static FPI fpi = { 24, -149, 104, 1, SI }; |
102 | 54 |
103 _scan_nan(u.bits, 1, s); 104 u.bits[0] |= 0x7fc00000; 105 return (u.f); | 55 float result; 56 ULong bits[1]; 57 58 s--; 59 hexnan(&s, &fpi, bits); 60 SET_FLOAT_WORD(result, 0x7fc00000 | bits[0]); 61 return (result); |
106} 107 108#if (LDBL_MANT_DIG == 53) 109__weak_reference(nan, nanl); 110#endif | 62} 63 64#if (LDBL_MANT_DIG == 53) 65__weak_reference(nan, nanl); 66#endif |