1 |
|
|
/* $OpenBSD: s_nan.c,v 1.14 2016/09/12 19:47:02 guenther Exp $ */ |
2 |
|
|
/*- |
3 |
|
|
* Copyright (c) 2007 David Schultz |
4 |
|
|
* All rights reserved. |
5 |
|
|
* |
6 |
|
|
* Redistribution and use in source and binary forms, with or without |
7 |
|
|
* modification, are permitted provided that the following conditions |
8 |
|
|
* are met: |
9 |
|
|
* 1. Redistributions of source code must retain the above copyright |
10 |
|
|
* notice, this list of conditions and the following disclaimer. |
11 |
|
|
* 2. Redistributions in binary form must reproduce the above copyright |
12 |
|
|
* notice, this list of conditions and the following disclaimer in the |
13 |
|
|
* documentation and/or other materials provided with the distribution. |
14 |
|
|
* |
15 |
|
|
* THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND |
16 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
17 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
18 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE |
19 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
20 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
21 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
22 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
23 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
24 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
25 |
|
|
* SUCH DAMAGE. |
26 |
|
|
* |
27 |
|
|
* $FreeBSD: src/lib/msun/src/s_nan.c,v 1.2 2007/12/18 23:46:32 das Exp $ |
28 |
|
|
*/ |
29 |
|
|
|
30 |
|
|
#include <sys/types.h> |
31 |
|
|
#include <ctype.h> |
32 |
|
|
#include <endian.h> |
33 |
|
|
#include <float.h> |
34 |
|
|
#include <math.h> |
35 |
|
|
#include <stdint.h> |
36 |
|
|
#include <strings.h> |
37 |
|
|
|
38 |
|
|
#include "math_private.h" |
39 |
|
|
|
40 |
|
|
/* |
41 |
|
|
* OpenBSD's ctype doesn't have digittoint, so we define it here. |
42 |
|
|
*/ |
43 |
|
|
static int |
44 |
|
|
_digittoint(int c) |
45 |
|
|
{ |
46 |
|
|
if (!isxdigit(c)) |
47 |
|
|
return 0; |
48 |
|
|
|
49 |
|
|
if (isdigit(c)) |
50 |
|
|
return c - '0'; |
51 |
|
|
else |
52 |
|
|
return isupper(c) ? c - 'A' + 10 : c - 'a' + 10; |
53 |
|
|
} |
54 |
|
|
|
55 |
|
|
/* |
56 |
|
|
* Scan a string of hexadecimal digits (the format nan(3) expects) and |
57 |
|
|
* make a bit array (using the local endianness). We stop when we |
58 |
|
|
* encounter an invalid character, NUL, etc. If we overflow, we do |
59 |
|
|
* the same as gcc's __builtin_nan(), namely, discard the high order bits. |
60 |
|
|
* |
61 |
|
|
* The format this routine accepts needs to be compatible with what is used |
62 |
|
|
* in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in |
63 |
|
|
* __builtin_nan(). In fact, we're only 100% compatible for strings we |
64 |
|
|
* consider valid, so we might be violating the C standard. But it's |
65 |
|
|
* impossible to use nan(3) portably anyway, so this seems good enough. |
66 |
|
|
*/ |
67 |
|
|
void |
68 |
|
|
_scan_nan(uint32_t *words, int num_words, const char *s) |
69 |
|
|
{ |
70 |
|
|
int si; /* index into s */ |
71 |
|
|
int bitpos; /* index into words (in bits) */ |
72 |
|
|
|
73 |
|
|
bzero(words, num_words * sizeof(uint32_t)); |
74 |
|
|
|
75 |
|
|
/* Allow a leading '0x'. (It's expected, but redundant.) */ |
76 |
|
|
if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) |
77 |
|
|
s += 2; |
78 |
|
|
|
79 |
|
|
/* Scan forwards in the string, looking for the end of the sequence. */ |
80 |
|
|
for (si = 0; isxdigit((unsigned char)s[si]); si++) |
81 |
|
|
; |
82 |
|
|
|
83 |
|
|
/* Scan backwards, filling in the bits in words[] as we go. */ |
84 |
|
|
#if BYTE_ORDER == LITTLE_ENDIAN |
85 |
|
|
for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) { |
86 |
|
|
#else |
87 |
|
|
for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) { |
88 |
|
|
#endif |
89 |
|
|
if (--si < 0) |
90 |
|
|
break; |
91 |
|
|
words[bitpos / 32] |= _digittoint((unsigned char)s[si]) << (bitpos % 32); |
92 |
|
|
} |
93 |
|
|
} |
94 |
|
|
|
95 |
|
|
double |
96 |
|
|
nan(const char *s) |
97 |
|
|
{ |
98 |
|
|
union { |
99 |
|
|
double d; |
100 |
|
|
uint32_t bits[2]; |
101 |
|
|
} u; |
102 |
|
|
|
103 |
|
|
_scan_nan(u.bits, 2, s); |
104 |
|
|
#if BYTE_ORDER == LITTLE_ENDIAN |
105 |
|
|
u.bits[1] |= 0x7ff80000; |
106 |
|
|
#else |
107 |
|
|
u.bits[0] |= 0x7ff80000; |
108 |
|
|
#endif |
109 |
|
|
return (u.d); |
110 |
|
|
} |
111 |
|
|
DEF_STD(nan); |
112 |
|
|
LDBL_MAYBE_UNUSED_CLONE(nan); |
113 |
|
|
|
114 |
|
|
float |
115 |
|
|
nanf(const char *s) |
116 |
|
|
{ |
117 |
|
|
union { |
118 |
|
|
float f; |
119 |
|
|
uint32_t bits[1]; |
120 |
|
|
} u; |
121 |
|
|
|
122 |
|
|
_scan_nan(u.bits, 1, s); |
123 |
|
|
u.bits[0] |= 0x7fc00000; |
124 |
|
|
return (u.f); |
125 |
|
|
} |