this repo has no description
1/* This module provides declarations and definitions common to the
2 implementations of C standard math functions nanf, nan, and nanl in nan.c
3 and nanl.c.
4
5 $Revision: 1.4 $, $Date: 2006/02/01 18:36:35 $
6*/
7
8
9/*
10 * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
11 *
12 * @APPLE_LICENSE_HEADER_START@
13 *
14 * The contents of this file constitute Original Code as defined in and
15 * are subject to the Apple Public Source License Version 1.1 (the
16 * "License"). You may not use this file except in compliance with the
17 * License. Please obtain a copy of the License at
18 * http://www.apple.com/publicsource and read it before using this file.
19 *
20 * This Original Code and all software distributed under the License are
21 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
25 * License for the specific language governing rights and limitations
26 * under the License.
27 *
28 * @APPLE_LICENSE_HEADER_END@
29 */
30
31
32/* These definitions and the implementations of nanf, nan, and nanl rely on:
33
34 The C 1999 standard, ISO/IEC 9899:1999(E), Programming Languages--C.
35
36 IEEE Std 754-1985, IEEE Standard for Binary Floating-Point Arithmetic.
37 (Later designated IEC 60559 and IEC 559.)
38
39 GCC behavior:
40
41 __BIG_ENDIAN__ is defined iff the most significant bytes of an
42 object appear at lower addresses.
43
44 Data may be written to one member of a union and read with a new
45 interpretation from another member.
46
47 In the run-time character set, the digits 0 through 9 must be
48 consecutive characters, the letters A through F must be consecutive
49 characters, and the letters a through f must be consecutive
50 characters.
51
52 __POWERPC__ and __i386__ are defined when compiling for the
53 corresponding architectures.
54
55 __LONG_DOUBLE_128__ is defined iff long double is implemented as
56 pair of doubles.
57
58 PowerPC and Intel IA-32 architecture:
59
60 The floating-point format, including that the most significant bit
61 of the significand of a NaN is true iff the NaN is quiet.
62
63 Motorola (later separated into Freescale), Programming
64 Environments Manual for 32-Bit Implementations of the PowerPC
65 Architecture, MPCFPE32B/AD 12/2002 Revision 2, section 3.3,
66 "Floating-Point Execution Models--UISA."
67
68 Intel, IA-32 Intel Architecture Software Developer's Manual,
69 Volume 1: Basic Architecture, 2002, 245470-007, section 4.8,
70 "Real Numbers and Floating-Point Formats."
71*/
72
73
74#include "math.h"
75#include <stdint.h>
76#include <stdlib.h>
77#include <machine/endian.h>
78
79
80// Define the type Float to access the representation of a float.
81typedef union
82{
83 float f;
84 struct
85 {
86 #if defined __BIG_ENDIAN__
87 unsigned int sign : 1;
88 unsigned int exponent : 8;
89 unsigned int quiet : 1;
90 unsigned int significand : 22;
91 #else
92 unsigned int significand : 22;
93 unsigned int quiet : 1;
94 unsigned int exponent : 8;
95 unsigned int sign : 1;
96 #endif
97 } s;
98} Float;
99
100
101// Define the type Double to access the representation of a double.
102typedef union
103{
104 double d;
105 struct
106 {
107 #if defined __BIG_ENDIAN__
108 unsigned int sign : 1;
109 unsigned int exponent : 11;
110 unsigned int quiet : 1;
111 uint64_t significand : 51;
112 #else
113 uint64_t significand : 51;
114 unsigned int quiet : 1;
115 unsigned int exponent : 11;
116 unsigned int sign : 1;
117 #endif
118 } s;
119} Double;
120
121
122// Long double and double are the same in cLibm
123typedef Double LongDouble;
124
125/* ConstructSignificand parses the tagp argument of nanf, nan, or nanl and
126 returns a 64-bit number that should be placed into the significand of the
127 NaN being returned.
128
129 (This returns the low 64 bits of the number represented by the numeral in
130 tagp, and the appropriate number of low bits should be copied into the
131 NaN.)
132
133 If tagp does not consist of a recognized numeral, zero is returned.
134*/
135static uint_least64_t ConstructSignificand(const char *tagp)
136{
137 if (tagp == NULL)
138 return 0;
139
140 // Determine the numeral base from the leading characters.
141 if (*tagp == '0')
142 {
143 ++tagp; // Consume the zero.
144 if (*tagp == 'x' || *tagp == 'X')
145 {
146 ++tagp; // Consume the x.
147
148 /* "0x" or "0X" indicates hexadecimal.
149
150 For each hexadecimal digit, shift the significand left and
151 insert the new digit on the right. If any character other
152 than a hexadecimal digit is encountered, return zero.
153
154 Observe that "0x" is accepted as a hexadecimal numeral, but it
155 returns 0, the same value we use for rejected strings. If the
156 value returned for rejected strings changes, the code here has
157 to check whether there is at least one digit.
158 */
159 char c;
160 uint_least64_t significand = 0;
161 while (0 != (c = *tagp++))
162 {
163 if ('0' <= c && c <= '9')
164 significand = (significand<<4) | (c - '0');
165 else if ('a' <= c && c <= 'f')
166 significand = (significand<<4) | (c - 'a' + 0xa);
167 else if ('A' <= c && c <= 'F')
168 significand = (significand<<4) | (c - 'A' + 0xa);
169 else
170 return 0;
171 }
172 return significand;
173 }
174 else
175 {
176 /* "0" without "x" or "X" indicates octal.
177
178 For each octal digit, shift the significand left and insert the
179 new digit on the right. If any character other than an octal
180 digit is encountered, return zero.
181 */
182 char c;
183 uint_least64_t significand = 0;
184 while (0 != (c = *tagp++))
185 if ('0' <= c && c <= '7')
186 significand = (significand<<3) | (c - '0');
187 else
188 return 0;
189 return significand;
190 }
191 }
192 else
193 {
194 /* For each decimal digit, multiply the value by ten and add the
195 new digit. If any character other than a decimal digit is
196 encountered, return zero.
197 */
198 char c;
199 uint_least64_t significand = 0;
200 while (0 != (c = *tagp++))
201 if ('0' <= c && c <= '9')
202 significand = significand*10 + c - '0';
203 else
204 return 0;
205 return significand;
206 }
207}