VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strtofloat.cpp

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 48.2 KB
Line 
1/* $Id: strtofloat.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - String To Floating Point Conversion.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/string.h>
42#include "internal/iprt.h"
43
44#include <iprt/asm.h>
45#include <iprt/assert.h>
46#include <iprt/ctype.h> /* needed for RT_C_IS_DIGIT */
47#include <iprt/err.h>
48
49#include <float.h>
50#include <math.h>
51#if !defined(_MSC_VER) || !defined(IPRT_NO_CRT) /** @todo fix*/
52# include <fenv.h>
53#endif
54#ifndef INFINITY /* Not defined on older Solaris (like the one in the add build VM). */
55# define INFINITY HUGE_VAL
56#endif
57
58#if defined(SOFTFLOAT_FAST_INT64) && !defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE) /** @todo better softfloat indicator? */
59# define USE_SOFTFLOAT /* for scaling by power of 10 */
60#endif
61#ifdef USE_SOFTFLOAT
62# include <softfloat.h>
63#endif
64
65
66/*********************************************************************************************************************************
67* Structures and Typedefs *
68*********************************************************************************************************************************/
69typedef union FLOATUNION
70{
71#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
72 RTFLOAT128U lrd;
73#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
74 RTFLOAT80U2 lrd;
75#else
76 RTFLOAT64U lrd;
77#endif
78 RTFLOAT64U rd;
79 RTFLOAT32U r;
80} FLOATUNION;
81
82#define RET_TYPE_FLOAT 0
83#define RET_TYPE_DOUBLE 1
84#define RET_TYPE_LONG_DOUBLE 2
85
86#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
87typedef RTFLOAT128U LONG_DOUBLE_U_T;
88typedef __uint128_t UINT_MANTISSA_T;
89# define UINT_MANTISSA_T_BITS 128
90#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
91typedef RTFLOAT80U2 LONG_DOUBLE_U_T;
92typedef uint64_t UINT_MANTISSA_T;
93# define UINT_MANTISSA_T_BITS 64
94#else
95typedef RTFLOAT64U LONG_DOUBLE_U_T;
96typedef uint64_t UINT_MANTISSA_T;
97# define UINT_MANTISSA_T_BITS 64
98#endif
99
100
101/*********************************************************************************************************************************
102* Global Variables *
103*********************************************************************************************************************************/
104/* in strtonum.cpp */
105extern const unsigned char g_auchDigits[256];
106
107#define DIGITS_ZERO_TERM 254
108#define DIGITS_COLON 253
109#define DIGITS_SPACE 252
110#define DIGITS_DOT 251
111
112/** Pair of default float quiet NaN values (indexed by fPositive). */
113static RTFLOAT32U const g_ar32QNan[2] = { RTFLOAT32U_INIT_QNAN(1), RTFLOAT32U_INIT_QNAN(0) };
114
115/** Pair of default double quiet NaN values (indexed by fPositive). */
116static RTFLOAT64U const g_ardQNan[2] = { RTFLOAT64U_INIT_QNAN(1), RTFLOAT64U_INIT_QNAN(0) };
117
118/** Pair of default double quiet NaN values (indexed by fPositive). */
119#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
120static RTFLOAT128U const g_alrdQNan[2] = { RTFLOAT128U_INIT_QNAN(1), RTFLOAT128U_INIT_QNAN(0) };
121#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
122static RTFLOAT80U2 const g_alrdQNan[2] = { RTFLOAT80U_INIT_QNAN(1), RTFLOAT80U_INIT_QNAN(0) };
123#else
124static RTFLOAT64U const g_alrdQNan[2] = { RTFLOAT64U_INIT_QNAN(1), RTFLOAT64U_INIT_QNAN(0) };
125#endif
126
127/** NaN fraction value masks. */
128static uint64_t const g_fNanMasks[3] =
129{
130 RT_BIT_64(RTFLOAT32U_FRACTION_BITS - 1) - 1, /* 22=quiet(1) / silent(0) */
131 RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1) - 1, /* 51=quiet(1) / silent(0) */
132#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
133 RT_BIT_64(RTFLOAT128U_FRACTION_BITS - 1 - 64) - 1, /* 111=quiet(1) / silent(0) */
134#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
135 RT_BIT_64(RTFLOAT80U_FRACTION_BITS - 1) - 1, /* bit 63=NaN; bit 62=quiet(1) / silent(0) */
136#else
137 RT_BIT_64(RTFLOAT64U_FRACTION_BITS - 1) - 1,
138#endif
139};
140
141#if 0
142/** Maximum exponent value in the binary representation for a RET_TYPE_XXX. */
143static const int32_t g_iMaxExp[3] =
144{
145 RTFLOAT32U_EXP_MAX - 1 - RTFLOAT32U_EXP_BIAS,
146 RTFLOAT64U_EXP_MAX - 1 - RTFLOAT64U_EXP_BIAS,
147#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
148 RTFLOAT128U_EXP_MAX - 1 - RTFLOAT128U_EXP_BIAS,
149#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
150 RTFLOAT80U_EXP_MAX - 1 - RTFLOAT80U_EXP_BIAS,
151#else
152 RTFLOAT64U_EXP_MAX - 1 - RTFLOAT64U_EXP_BIAS,
153#endif
154};
155
156/** Minimum exponent value in the binary representation for a RET_TYPE_XXX. */
157static const int32_t g_iMinExp[3] =
158{
159 1 - RTFLOAT32U_EXP_BIAS,
160 1 - RTFLOAT64U_EXP_BIAS,
161#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
162 1 - RTFLOAT128U_EXP_BIAS,
163#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
164 1 - RTFLOAT80U_EXP_BIAS,
165#else
166 1 - RTFLOAT64U_EXP_BIAS,
167#endif
168};
169#endif
170
171#if 0 /* unused */
172# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
173static const long double g_lrdPowerMin10 = 1e4931L;
174static const long double g_lrdPowerMax10 = 1e4932L;
175# else
176static const long double g_lrdPowerMin10 = 1e307L;
177static const long double g_lrdPowerMax10 = 1e308L;
178# endif
179#endif
180
181#ifdef USE_SOFTFLOAT
182/** SoftFloat: Power of 10 table using 128-bit floating point.
183 *
184 * @code
185 softfloat_state_t SoftState = SOFTFLOAT_STATE_INIT_DEFAULTS();
186 float128_t Power10;
187 ui32_to_f128M(10, &Power10, &SoftState);
188 for (unsigned iBit = 0; iBit < 13; iBit++)
189 {
190 RTAssertMsg2(" { { UINT64_C(%#018RX64), UINT64_C(%#018RX64) } }, %c* 1e%u (%RU64) *%c\n", Power10.v[0], Power10.v[1],
191 '/', RT_BIT_32(iBit), f128M_to_ui64(&Power10, softfloat_round_near_even, false, &SoftState), '/');
192 f128M_mul(&Power10, &Power10, &Power10, &SoftState);
193 }
194 @endcode */
195static const float128_t g_ar128Power10[] =
196{
197 { { UINT64_C(0x0000000000000000), UINT64_C(0x4002400000000000) } }, /* 1e1 (10) */
198 { { UINT64_C(0x0000000000000000), UINT64_C(0x4005900000000000) } }, /* 1e2 (100) */
199 { { UINT64_C(0x0000000000000000), UINT64_C(0x400c388000000000) } }, /* 1e4 (10000) */
200 { { UINT64_C(0x0000000000000000), UINT64_C(0x40197d7840000000) } }, /* 1e8 (100000000) */
201 { { UINT64_C(0x0000000000000000), UINT64_C(0x40341c37937e0800) } }, /* 1e16 (10000000000000000) */
202 { { UINT64_C(0x6b3be04000000000), UINT64_C(0x40693b8b5b5056e1) } }, /* 1e32 (18446744073709551615) */
203 { { UINT64_C(0x4daa797ed6e38ed6), UINT64_C(0x40d384f03e93ff9f) } }, /* 1e64 (18446744073709551615) */
204 { { UINT64_C(0x19bf8cde66d86d61), UINT64_C(0x41a827748f9301d3) } }, /* 1e128 (18446744073709551615) */
205 { { UINT64_C(0xbd1bbb77203731fb), UINT64_C(0x435154fdd7f73bf3) } }, /* 1e256 (18446744073709551615) */
206 { { UINT64_C(0x238d98cab8a97899), UINT64_C(0x46a3c633415d4c1d) } }, /* 1e512 (18446744073709551615) */
207 { { UINT64_C(0x182eca1a7a51e308), UINT64_C(0x4d4892eceb0d02ea) } }, /* 1e1024 (18446744073709551615) */
208 { { UINT64_C(0xbbc94e9a519c651e), UINT64_C(0x5a923d1676bb8a7a) } }, /* 1e2048 (18446744073709551615) */
209 { { UINT64_C(0x2f3592982a7f005a), UINT64_C(0x752588c0a4051441) } }, /* 1e4096 (18446744073709551615) */
210 /* INF */
211};
212
213/** SoftFloat: Initial value for power of 10 scaling.
214 * This deals with the first 32 powers of 10, covering the a full 64-bit
215 * mantissa and a small exponent w/o needing to make use of g_ar128Power10.
216 *
217 * @code
218 softfloat_state_t SoftState = SOFTFLOAT_STATE_INIT_DEFAULTS();
219 float128_t Num10;
220 ui32_to_f128M(10, &Num10, &SoftState);
221 float128_t Power10;
222 ui32_to_f128M(1, &Power10, &SoftState);
223 for (unsigned cTimes = 0; cTimes < 32; cTimes++)
224 {
225 RTAssertMsg2(" { { UINT64_C(%#018RX64), UINT64_C(%#018RX64) } }, %c* 1e%u (%RU64) *%c\n", Power10.v[0], Power10.v[1],
226 '/', cTimes, f128M_to_ui64(&Power10, softfloat_round_near_even, false, &SoftState), '/');
227 f128M_mul(&Power10, &Num10, &Power10, &SoftState);
228 }
229 @endcode */
230static const float128_t g_ar128Power10Initial[] =
231{
232 { { UINT64_C(0x0000000000000000), UINT64_C(0x3fff000000000000) } }, /* 1e0 (1) */
233 { { UINT64_C(0x0000000000000000), UINT64_C(0x4002400000000000) } }, /* 1e1 (10) */
234 { { UINT64_C(0x0000000000000000), UINT64_C(0x4005900000000000) } }, /* 1e2 (100) */
235 { { UINT64_C(0x0000000000000000), UINT64_C(0x4008f40000000000) } }, /* 1e3 (1000) */
236 { { UINT64_C(0x0000000000000000), UINT64_C(0x400c388000000000) } }, /* 1e4 (10000) */
237 { { UINT64_C(0x0000000000000000), UINT64_C(0x400f86a000000000) } }, /* 1e5 (100000) */
238 { { UINT64_C(0x0000000000000000), UINT64_C(0x4012e84800000000) } }, /* 1e6 (1000000) */
239 { { UINT64_C(0x0000000000000000), UINT64_C(0x4016312d00000000) } }, /* 1e7 (10000000) */
240 { { UINT64_C(0x0000000000000000), UINT64_C(0x40197d7840000000) } }, /* 1e8 (100000000) */
241 { { UINT64_C(0x0000000000000000), UINT64_C(0x401cdcd650000000) } }, /* 1e9 (1000000000) */
242 { { UINT64_C(0x0000000000000000), UINT64_C(0x40202a05f2000000) } }, /* 1e10 (10000000000) */
243 { { UINT64_C(0x0000000000000000), UINT64_C(0x402374876e800000) } }, /* 1e11 (100000000000) */
244 { { UINT64_C(0x0000000000000000), UINT64_C(0x4026d1a94a200000) } }, /* 1e12 (1000000000000) */
245 { { UINT64_C(0x0000000000000000), UINT64_C(0x402a2309ce540000) } }, /* 1e13 (10000000000000) */
246 { { UINT64_C(0x0000000000000000), UINT64_C(0x402d6bcc41e90000) } }, /* 1e14 (100000000000000) */
247 { { UINT64_C(0x0000000000000000), UINT64_C(0x4030c6bf52634000) } }, /* 1e15 (1000000000000000) */
248 { { UINT64_C(0x0000000000000000), UINT64_C(0x40341c37937e0800) } }, /* 1e16 (10000000000000000) */
249 { { UINT64_C(0x0000000000000000), UINT64_C(0x40376345785d8a00) } }, /* 1e17 (100000000000000000) */
250 { { UINT64_C(0x0000000000000000), UINT64_C(0x403abc16d674ec80) } }, /* 1e18 (1000000000000000000) */
251 { { UINT64_C(0x0000000000000000), UINT64_C(0x403e158e460913d0) } }, /* 1e19 (10000000000000000000) */
252 { { UINT64_C(0x0000000000000000), UINT64_C(0x40415af1d78b58c4) } }, /* 1e20 (18446744073709551615) */
253 { { UINT64_C(0x0000000000000000), UINT64_C(0x4044b1ae4d6e2ef5) } }, /* 1e21 (18446744073709551615) */
254 { { UINT64_C(0x2000000000000000), UINT64_C(0x40480f0cf064dd59) } }, /* 1e22 (18446744073709551615) */
255 { { UINT64_C(0x6800000000000000), UINT64_C(0x404b52d02c7e14af) } }, /* 1e23 (18446744073709551615) */
256 { { UINT64_C(0x4200000000000000), UINT64_C(0x404ea784379d99db) } }, /* 1e24 (18446744073709551615) */
257 { { UINT64_C(0x0940000000000000), UINT64_C(0x405208b2a2c28029) } }, /* 1e25 (18446744073709551615) */
258 { { UINT64_C(0x4b90000000000000), UINT64_C(0x40554adf4b732033) } }, /* 1e26 (18446744073709551615) */
259 { { UINT64_C(0x1e74000000000000), UINT64_C(0x40589d971e4fe840) } }, /* 1e27 (18446744073709551615) */
260 { { UINT64_C(0x1308800000000000), UINT64_C(0x405c027e72f1f128) } }, /* 1e28 (18446744073709551615) */
261 { { UINT64_C(0x17caa00000000000), UINT64_C(0x405f431e0fae6d72) } }, /* 1e29 (18446744073709551615) */
262 { { UINT64_C(0x9dbd480000000000), UINT64_C(0x406293e5939a08ce) } }, /* 1e30 (18446744073709551615) */
263 { { UINT64_C(0x452c9a0000000000), UINT64_C(0x4065f8def8808b02) } }, /* 1e31 (18446744073709551615) */
264};
265
266#else /* !USE_SOFTFLOAT */
267/** Long Double: Power of 10 table scaling table.
268 * @note LDBL_MAX_10_EXP is 4932 for 80-bit and 308 for 64-bit type. */
269static const long double a_lrdPower10[] =
270{
271 1e1L,
272 1e2L,
273 1e4L,
274 1e8L,
275 1e16L,
276 1e32L,
277 1e64L,
278 1e128L,
279 1e256L,
280# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
281 1e512L,
282 1e1024L,
283 1e2048L,
284 1e4096L,
285# endif
286};
287
288/** Long double: Initial value for power of 10 scaling.
289 * This deals with the first 32 powers of 10, covering the a full 64-bit
290 * mantissa and a small exponent w/o needing to make use of g_ar128Power10. */
291static const long double g_alrdPower10Initial[] =
292{
293 1e0L,
294 1e1L,
295 1e2L,
296 1e3L,
297 1e4L,
298 1e5L,
299 1e6L,
300 1e7L,
301 1e8L,
302 1e9L,
303 1e10L,
304 1e11L,
305 1e12L,
306 1e13L,
307 1e14L,
308 1e15L,
309 1e16L,
310 1e17L,
311 1e18L,
312 1e19L,
313 1e20L,
314 1e21L,
315 1e22L,
316 1e23L,
317 1e24L,
318 1e25L,
319 1e26L,
320 1e27L,
321 1e28L,
322 1e29L,
323 1e30L,
324 1e31L,
325};
326
327/* Tell the compiler that we'll mess with the FPU environment. */
328# ifdef _MSC_VER
329# pragma fenv_access(on)
330# endif
331#endif /*!USE_SOFTFLOAT */
332
333
334/**
335 * Multiply @a pVal by 10 to the power of @a iExponent10.
336 *
337 * This is currently a weak point where we might end up with rounding issues.
338 */
339static int rtStrToLongDoubleExp10(LONG_DOUBLE_U_T *pVal, int iExponent10)
340{
341 AssertReturn(iExponent10 != 0, VINF_SUCCESS);
342#ifdef USE_SOFTFLOAT
343 /* Use 128-bit precision floating point from softfloat to improve accuracy. */
344
345 softfloat_state_t SoftState = SOFTFLOAT_STATE_INIT_DEFAULTS();
346 float128_t Val;
347# ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
348 extFloat80M Tmp = EXTFLOAT80M_INIT(pVal->s2.uSignAndExponent, pVal->s2.uMantissa);
349 extF80M_to_f128M(&Tmp, &Val, &SoftState);
350# else
351 float64_t Tmp = { pVal->u };
352 f64_to_f128M(Tmp, &Val, &SoftState);
353# endif
354
355 /*
356 * Calculate the scaling factor. If we need to make use of the last table
357 * entry, we will do part of the scaling here to avoid overflowing Factor.
358 */
359 unsigned uAbsExp = (unsigned)RT_ABS(iExponent10);
360 AssertCompile(RT_ELEMENTS(g_ar128Power10Initial) == 32);
361 unsigned iBit = 5;
362 float128_t Factor = g_ar128Power10Initial[uAbsExp & 31];
363 uAbsExp >>= iBit;
364 while (uAbsExp != 0)
365 {
366 if (iBit < RT_ELEMENTS(g_ar128Power10))
367 {
368 if (uAbsExp & 1)
369 {
370 if (iBit < RT_ELEMENTS(g_ar128Power10) - 1)
371 f128M_mul(&Factor, &g_ar128Power10[iBit], &Factor, &SoftState);
372 else
373 {
374 /* Must do it in two steps to avoid prematurely overflowing the factor value. */
375 if (iExponent10 > 0)
376 f128M_mul(&Val, &Factor, &Val, &SoftState);
377 else
378 f128M_div(&Val, &Factor, &Val, &SoftState);
379 Factor = g_ar128Power10[iBit];
380 }
381 }
382 }
383 else if (iExponent10 < 0)
384 {
385 pVal->r = pVal->r < 0.0L ? -0.0L : +0.0L;
386 return VERR_FLOAT_UNDERFLOW;
387 }
388 else
389 {
390 pVal->r = pVal->r < 0.0L ? -INFINITY : +INFINITY;
391 return VERR_FLOAT_OVERFLOW;
392 }
393 iBit++;
394 uAbsExp >>= 1;
395 }
396
397 /*
398 * Do the scaling (or what remains).
399 */
400 if (iExponent10 > 0)
401 f128M_mul(&Val, &Factor, &Val, &SoftState);
402 else
403 f128M_div(&Val, &Factor, &Val, &SoftState);
404
405# ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
406 f128M_to_extF80M(&Val, &Tmp, &SoftState);
407 pVal->s2.uSignAndExponent = Tmp.signExp;
408 pVal->s2.uMantissa = Tmp.signif;
409# else
410 Tmp = f128M_to_f64(&Val, &SoftState);
411 pVal->u = Tmp.v;
412# endif
413
414 /*
415 * Check for under/overflow and return.
416 */
417 int rc;
418 if (!(SoftState.exceptionFlags & (softfloat_flag_underflow | softfloat_flag_overflow)))
419 rc = VINF_SUCCESS;
420 else if (SoftState.exceptionFlags & softfloat_flag_underflow)
421 rc = VERR_FLOAT_UNDERFLOW;
422 else
423 rc = VERR_FLOAT_OVERFLOW;
424
425#else /* !USE_SOFTFLOAT */
426# if 0
427 /*
428 * Use RTBigNum, falling back on the simple approach if we don't need the
429 * precision or run out of memory?
430 */
431 /** @todo implement RTBigNum approach */
432# endif
433
434 /*
435 * Simple approach.
436 */
437# if !defined(_MSC_VER) || !defined(IPRT_NO_CRT) /** @todo fix*/
438 fenv_t SavedFpuEnv;
439 feholdexcept(&SavedFpuEnv);
440# endif
441
442 /*
443 * Calculate the scaling factor. If we need to make use of the last table
444 * entry, we will do part of the scaling here to avoid overflowing lrdFactor.
445 */
446 AssertCompile(RT_ELEMENTS(g_alrdPower10Initial) == 32);
447 int rc = VINF_SUCCESS;
448 unsigned uAbsExp = (unsigned)RT_ABS(iExponent10);
449 long double lrdFactor = g_alrdPower10Initial[uAbsExp & 31];
450 unsigned iBit = 5;
451 uAbsExp >>= iBit;
452
453 while (uAbsExp != 0)
454 {
455 if (iBit < RT_ELEMENTS(a_lrdPower10))
456 {
457 if (uAbsExp & 1)
458 {
459 if (iBit < RT_ELEMENTS(a_lrdPower10) - 1)
460 lrdFactor *= a_lrdPower10[iBit];
461 else
462 {
463 /* Must do it in two steps to avoid prematurely overflowing the factor value. */
464 if (iExponent10 < 0)
465 pVal->r /= lrdFactor;
466 else
467 pVal->r *= lrdFactor;
468 lrdFactor = a_lrdPower10[iBit];
469 }
470 }
471 }
472 else if (iExponent10 < 0)
473 {
474 pVal->r = pVal->r < 0.0L ? -0.0L : +0.0L;
475 rc = VERR_FLOAT_UNDERFLOW;
476 break;
477 }
478 else
479 {
480 pVal->r = pVal->r < 0.0L ? -INFINITY : +INFINITY;
481 rc = VERR_FLOAT_OVERFLOW;
482 break;
483 }
484 iBit++;
485 uAbsExp >>= 1;
486 }
487
488 /*
489 * Do the scaling (or what remains).
490 */
491 if (iExponent10 < 0)
492 pVal->r /= lrdFactor;
493 else
494 pVal->r *= lrdFactor;
495
496# if !defined(_MSC_VER) || !defined(IPRT_NO_CRT) /** @todo fix*/
497 fesetenv(&SavedFpuEnv);
498# endif
499
500#endif /* !USE_SOFTFLOAT */
501 return rc;
502}
503
504
505
506/**
507 * Set @a ppszNext and check for trailing spaces & chars if @a rc is
508 * VINF_SUCCESS.
509 *
510 * @returns IPRT status code.
511 * @param psz The current input position.
512 * @param ppszNext Where to return the pointer to the end of the value.
513 * Optional.
514 * @param cchMax Number of bytes left in the string starting at @a psz.
515 * @param rc The status code to return.
516 */
517static int rtStrToLongDoubleReturnChecks(const char *psz, char **ppszNext, size_t cchMax, int rc)
518{
519 if (ppszNext)
520 *ppszNext = (char *)psz;
521
522 /* Trailing spaces/chars warning: */
523 if (rc == VINF_SUCCESS && cchMax > 0 && *psz)
524 {
525 do
526 {
527 char ch = *psz++;
528 if (ch == ' ' || ch == '\t')
529 cchMax--;
530 else
531 return ch == '\0' ? VWRN_TRAILING_SPACES : VWRN_TRAILING_CHARS;
532 } while (cchMax > 0);
533 rc = VWRN_TRAILING_SPACES;
534 }
535 return rc;
536}
537
538
539/**
540 * Set @a pRet to infinity, set @a ppszNext, and check for trailing spaces &
541 * chars if @a rc is VINF_SUCCESS.
542 *
543 * @returns IPRT status code.
544 * @param psz The current input position.
545 * @param ppszNext Where to return the pointer to the end of the value.
546 * Optional.
547 * @param cchMax Number of bytes left in the string starting at @a psz.
548 * @param fPositive Whether the infinity should be positive or negative.
549 * @param rc The status code to return.
550 * @param iRetType The target type.
551 * @param pRet Where to store the result.
552 */
553static int rtStrToLongDoubleReturnInf(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
554 int rc, unsigned iRetType, FLOATUNION *pRet)
555{
556 /*
557 * Skip to the end of long form?
558 */
559 char ch;
560 if ( cchMax >= 5
561 && ((ch = psz[0]) == 'i' || ch == 'I')
562 && ((ch = psz[1]) == 'n' || ch == 'N')
563 && ((ch = psz[2]) == 'i' || ch == 'I')
564 && ((ch = psz[3]) == 't' || ch == 'T')
565 && ((ch = psz[4]) == 'y' || ch == 'Y'))
566 {
567 psz += 5;
568 cchMax -= 5;
569 }
570
571 /*
572 * Set the return value:
573 */
574 switch (iRetType)
575 {
576 case RET_TYPE_FLOAT:
577 {
578 RTFLOAT32U const uRet = RTFLOAT32U_INIT_INF(!fPositive);
579 AssertCompile(sizeof(uRet) == sizeof(pRet->r.r));
580 pRet->r.r = uRet.r;
581 break;
582 }
583
584 case RET_TYPE_LONG_DOUBLE:
585#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
586 {
587# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
588 RTFLOAT80U2 const uRet = RTFLOAT80U_INIT_INF(!fPositive);
589# else
590 RTFLOAT128U const uRet = RTFLOAT128U_INIT_INF(!fPositive);
591# endif
592 pRet->lrd.lrd = uRet.lrd;
593 break;
594 }
595#else
596 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
597 RT_FALL_THRU();
598#endif
599 case RET_TYPE_DOUBLE:
600 {
601 RTFLOAT64U const uRet = RTFLOAT64U_INIT_INF(!fPositive);
602 AssertCompile(sizeof(uRet) == sizeof(pRet->rd.rd));
603 pRet->rd.rd = uRet.rd;
604 break;
605 }
606
607 default: AssertFailedBreak();
608 }
609
610 /*
611 * Deal with whatever follows and return:
612 */
613 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, rc);
614}
615
616
617/**
618 * Parses the tag of a "NaN(tag)" value.
619 *
620 * We take the tag to be a number to be put in the mantissa of the NaN, possibly
621 * suffixed by '[_]quiet' or '[_]signaling' (all or part) to indicate the type
622 * of NaN.
623 *
624 * @param pchTag The tag string to parse. Not zero terminated.
625 * @param cchTag The length of the tag string value.
626 * @param fPositive Whether the NaN should be positive or negative.
627 * @param iRetType The target type.
628 * @param pRet Where to store the result.
629 */
630static void rtStrParseNanTag(const char *pchTag, size_t cchTag, bool fPositive, unsigned iRetType, FLOATUNION *pRet)
631{
632 /*
633 * Skip 0x - content is hexadecimal, so this is not necessary.
634 */
635 if (cchTag > 2 && pchTag[0] == '0' && (pchTag[1] == 'x' || pchTag[1] == 'X'))
636 {
637 pchTag += 2;
638 cchTag -= 2;
639 }
640
641 /*
642 * Parse the number, ignoring overflows and stopping on non-xdigit.
643 */
644 uint64_t uHiNum = 0;
645 uint64_t uLoNum = 0;
646 unsigned iXDigit = 0;
647 while (cchTag > 0)
648 {
649 unsigned char uch = (unsigned char)*pchTag;
650 unsigned char uchDigit = g_auchDigits[uch];
651 if (uchDigit >= 16)
652 break;
653 iXDigit++;
654 if (iXDigit >= 16)
655 uHiNum = (uHiNum << 4) | (uLoNum >> 60);
656 uLoNum <<= 4;
657 uLoNum += uchDigit;
658 pchTag++;
659 cchTag--;
660 }
661
662 /*
663 * Check for special "non-standard" quiet / signalling indicator.
664 */
665 while (cchTag > 0 && *pchTag == '_')
666 pchTag++, cchTag--;
667 bool fQuiet = true;
668 if (cchTag > 0)
669 {
670 //const char *pszSkip = NULL;
671 char ch = pchTag[0];
672 if (ch == 'q' || ch == 'Q')
673 {
674 fQuiet = true;
675 //pszSkip = "qQuUiIeEtT\0"; /* cchTag stop before '\0', so we put two at the end to break out of the loop below. */
676 }
677 else if (ch == 's' || ch == 'S')
678 {
679 fQuiet = false;
680 //pszSkip = "sSiIgGnNaAlLiInNgG\0";
681 }
682 //if (pszSkip)
683 // do
684 // {
685 // pchTag++;
686 // cchTag--;
687 // pszSkip += 2;
688 // } while (cchTag > 0 && ((ch = *pchTag) == pszSkip[0] || ch == pszSkip[1]));
689 }
690
691 /*
692 * Adjust the number according to the type.
693 */
694 Assert(iRetType < RT_ELEMENTS(g_fNanMasks));
695#if defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
696 if (iRetType == RET_TYPE_LONG_DOUBLE)
697 uHiNum &= g_fNanMasks[RET_TYPE_LONG_DOUBLE];
698 else
699#endif
700 {
701 uHiNum = 0;
702 uLoNum &= g_fNanMasks[iRetType];
703 }
704 if (!uLoNum && !uHiNum && !fQuiet)
705 uLoNum = 1; /* must not be zero, or it'll turn into an infinity */
706
707 /*
708 * Set the return value.
709 */
710 switch (iRetType)
711 {
712 case RET_TYPE_FLOAT:
713 {
714 RTFLOAT32U const uRet = RTFLOAT32U_INIT_NAN_EX(fQuiet, !fPositive, (uint32_t)uLoNum);
715 pRet->r = uRet;
716 break;
717 }
718
719 case RET_TYPE_LONG_DOUBLE:
720#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
721 {
722# if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
723 RTFLOAT80U2 const uRet = RTFLOAT80U_INIT_NAN_EX(fQuiet, !fPositive, uLoNum);
724# else
725 RTFLOAT128U const uRet = RTFLOAT128U_INIT_NAN_EX(fQuiet, !fPositive, uHiNum, uLoNum);
726# endif
727 pRet->lrd = uRet;
728 break;
729 }
730#else
731 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
732 RT_FALL_THRU();
733#endif
734 case RET_TYPE_DOUBLE:
735 {
736 RTFLOAT64U const uRet = RTFLOAT64U_INIT_NAN_EX(fQuiet, !fPositive, uLoNum);
737 pRet->rd = uRet;
738 break;
739 }
740
741 default: AssertFailedBreak();
742 }
743
744 //return cchTag == 0;
745}
746
747
748/**
749 * Finish parsing NaN, set @a pRet to NaN, set @a ppszNext, and check for
750 * trailing spaces & chars if @a rc is VINF_SUCCESS.
751 *
752 * @returns IPRT status code.
753 * @param psz The current input position.
754 * @param ppszNext Where to return the pointer to the end of the value.
755 * Optional.
756 * @param cchMax Number of bytes left in the string starting at @a psz.
757 * @param fPositive Whether the NaN should be positive or negative.
758 * @param iRetType The target type.
759 * @param pRet Where to store the result.
760 */
761static int rtStrToLongDoubleReturnNan(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
762 unsigned iRetType, FLOATUNION *pRet)
763{
764 /*
765 * Any NaN sub-number? E.g. NaN(1) or Nan(0x42). We'll require a closing
766 * parenthesis or we'll just ignore it.
767 */
768 if (cchMax >= 2 && *psz == '(')
769 {
770 unsigned cchTag = 1;
771 char ch = '\0';
772 while (cchTag < cchMax && (RT_C_IS_ALNUM((ch = psz[cchTag])) || ch == '_'))
773 cchTag++;
774 if (ch == ')')
775 {
776 rtStrParseNanTag(psz + 1, cchTag - 1, fPositive, iRetType, pRet);
777 psz += cchTag + 1;
778 cchMax -= cchTag + 1;
779 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
780 }
781 }
782
783 /*
784 * Set the return value to the default NaN value.
785 */
786 switch (iRetType)
787 {
788 case RET_TYPE_FLOAT:
789 pRet->r = g_ar32QNan[fPositive];
790 break;
791
792 case RET_TYPE_DOUBLE:
793 pRet->rd = g_ardQNan[fPositive];
794 break;
795
796 case RET_TYPE_LONG_DOUBLE:
797 pRet->lrd = g_alrdQNan[fPositive];
798 break;
799
800 default: AssertFailedBreak();
801 }
802
803 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
804}
805
806
807RTDECL(long double) RTStrNanLongDouble(const char *pszTag, bool fPositive)
808{
809 if (pszTag)
810 {
811 size_t cchTag = strlen(pszTag);
812 if (cchTag > 0)
813 {
814 FLOATUNION u;
815 rtStrParseNanTag(pszTag, cchTag, fPositive, RET_TYPE_LONG_DOUBLE, &u);
816 return u.lrd.r;
817 }
818 }
819 return g_alrdQNan[fPositive].r;
820}
821
822
823RTDECL(double) RTStrNanDouble(const char *pszTag, bool fPositive)
824{
825 if (pszTag)
826 {
827 size_t cchTag = strlen(pszTag);
828 if (cchTag > 0)
829 {
830 FLOATUNION u;
831 rtStrParseNanTag(pszTag, cchTag, fPositive, RET_TYPE_DOUBLE, &u);
832 return u.rd.r;
833 }
834 }
835 return g_ardQNan[fPositive].r;
836}
837
838
839RTDECL(float) RTStrNanFloat(const char *pszTag, bool fPositive)
840{
841 if (pszTag)
842 {
843 size_t cchTag = strlen(pszTag);
844 if (cchTag > 0)
845 {
846 FLOATUNION u;
847 rtStrParseNanTag(pszTag, cchTag, fPositive, RET_TYPE_FLOAT, &u);
848 return u.r.r;
849 }
850 }
851 return g_ar32QNan[fPositive].r;
852}
853
854
855/**
856 * Set @a pRet to zero, set @a ppszNext, and check for trailing spaces &
857 * chars if @a rc is VINF_SUCCESS.
858 *
859 * @returns IPRT status code.
860 * @param psz The current input position.
861 * @param ppszNext Where to return the pointer to the end of the value.
862 * Optional.
863 * @param cchMax Number of bytes left in the string starting at @a psz.
864 * @param fPositive Whether the value should be positive or negative.
865 * @param rc The status code to return.
866 * @param iRetType The target type.
867 * @param pRet Where to store the result.
868 */
869static int rtStrToLongDoubleReturnZero(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
870 int rc, unsigned iRetType, FLOATUNION *pRet)
871{
872 switch (iRetType)
873 {
874 case RET_TYPE_FLOAT:
875 pRet->r.r = fPositive ? +0.0F : -0.0F;
876 break;
877
878 case RET_TYPE_LONG_DOUBLE:
879#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
880 pRet->lrd.lrd = fPositive ? +0.0L : -0.0L;
881 break;
882#else
883 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
884 RT_FALL_THRU();
885#endif
886 case RET_TYPE_DOUBLE:
887 pRet->rd.rd = fPositive ? +0.0 : -0.0;
888 break;
889
890 default: AssertFailedBreak();
891 }
892
893 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, rc);
894}
895
896
897/**
898 * Return overflow or underflow - setting @a pRet and @a ppszNext accordingly.
899 *
900 * @returns IPRT status code.
901 * @param psz The current input position.
902 * @param ppszNext Where to return the pointer to the end of the value.
903 * Optional.
904 * @param cchMax Number of bytes left in the string starting at @a psz.
905 * @param fPositive Whether the value should be positive or negative.
906 * @param iExponent Overflow/underflow indicator.
907 * @param iRetType The target type.
908 * @param pRet Where to store the result.
909 */
910static int rtStrToLongDoubleReturnOverflow(const char *psz, char **ppszNext, size_t cchMax, bool fPositive,
911 int32_t iExponent, unsigned iRetType, FLOATUNION *pRet)
912{
913 if (iExponent > 0)
914 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
915 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
916}
917
918
919/**
920 * Returns a denormal/subnormal value.
921 *
922 * This implies that iRetType is long double, or double if they are the same,
923 * and that we should warn about underflowing.
924 */
925static int rtStrToLongDoubleReturnSubnormal(const char *psz, char **ppszNext, size_t cchMax, LONG_DOUBLE_U_T const *pVal,
926 unsigned iRetType, FLOATUNION *pRet)
927{
928#if defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE) || defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
929 Assert(iRetType == RET_TYPE_LONG_DOUBLE);
930 pRet->lrd = *pVal;
931#else
932 Assert(iRetType == RET_TYPE_LONG_DOUBLE || iRetType == RET_TYPE_DOUBLE);
933 pRet->rd = *pVal;
934#endif
935 RT_NOREF(iRetType);
936 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VWRN_FLOAT_UNDERFLOW);
937}
938
939
940/**
941 * Packs the given sign, mantissa, and (power of 2) exponent into the
942 * return value.
943 */
944static int rtStrToLongDoubleReturnValue(const char *psz, char **ppszNext, size_t cchMax,
945 bool fPositive, UINT_MANTISSA_T uMantissa, int32_t iExponent,
946 unsigned iRetType, FLOATUNION *pRet)
947{
948 int rc = VINF_SUCCESS;
949 switch (iRetType)
950 {
951 case RET_TYPE_FLOAT:
952 iExponent += RTFLOAT32U_EXP_BIAS;
953 if (iExponent <= 0)
954 {
955 /* Produce a subnormal value if it's within range, otherwise return zero. */
956 if (iExponent < -RTFLOAT32U_FRACTION_BITS)
957 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
958 rc = VWRN_FLOAT_UNDERFLOW;
959 uMantissa >>= -iExponent + 1;
960 iExponent = 0;
961 }
962 else if (iExponent >= RTFLOAT32U_EXP_MAX)
963 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
964
965 pRet->r.s.uFraction = (uMantissa >> (UINT_MANTISSA_T_BITS - 1 - RTFLOAT32U_FRACTION_BITS))
966 & (RT_BIT_32(RTFLOAT32U_FRACTION_BITS) - 1);
967 pRet->r.s.uExponent = iExponent;
968 pRet->r.s.fSign = !fPositive;
969 break;
970
971 case RET_TYPE_LONG_DOUBLE:
972#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
973# if UINT_MANTISSA_T_BITS != 64
974# error Unsupported UINT_MANTISSA_T_BITS count.
975# endif
976 iExponent += RTFLOAT80U_EXP_BIAS;
977 if (iExponent <= 0)
978 {
979 /* Produce a subnormal value if it's within range, otherwise return zero. */
980 if (iExponent < -RTFLOAT80U_FRACTION_BITS)
981 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
982 rc = VWRN_FLOAT_UNDERFLOW;
983 uMantissa >>= -iExponent + 1;
984 iExponent = 0;
985 }
986 else if (iExponent >= RTFLOAT80U_EXP_MAX)
987 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
988
989 pRet->lrd.s.uMantissa = uMantissa;
990 pRet->lrd.s.uExponent = iExponent;
991 pRet->lrd.s.fSign = !fPositive;
992 break;
993#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
994 iExponent += RTFLOAT128U_EXP_BIAS;
995 uMantissa >>= 128 - RTFLOAT128U_FRACTION_BITS;
996 if (iExponent <= 0)
997 {
998 /* Produce a subnormal value if it's within range, otherwise return zero. */
999 if (iExponent < -RTFLOAT128U_FRACTION_BITS)
1000 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
1001 rc = VWRN_FLOAT_UNDERFLOW;
1002 uMantissa >>= -iExponent + 1;
1003 iExponent = 0;
1004 }
1005 else if (iExponent >= RTFLOAT80U_EXP_MAX)
1006 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
1007 pRet->lrd.s64.uFractionHi = (uint64_t)(uMantissa >> 64) & (RT_BIT_64(RTFLOAT128U_FRACTION_BITS - 64) - 1);
1008 pRet->lrd.s64.uFractionLo = (uint64_t)uMantissa;
1009 pRet->lrd.s64.uExponent = iExponent;
1010 pRet->lrd.s64.fSign = !fPositive;
1011 break;
1012#else
1013 AssertCompile(sizeof(long double) == sizeof(pRet->rd.rd));
1014 RT_FALL_THRU();
1015#endif
1016 case RET_TYPE_DOUBLE:
1017 iExponent += RTFLOAT64U_EXP_BIAS;
1018 if (iExponent <= 0)
1019 {
1020 /* Produce a subnormal value if it's within range, otherwise return zero. */
1021 if (iExponent < -RTFLOAT64U_FRACTION_BITS)
1022 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_UNDERFLOW, iRetType, pRet);
1023 rc = VWRN_FLOAT_UNDERFLOW;
1024 uMantissa >>= -iExponent + 1;
1025 iExponent = 0;
1026 }
1027 else if (iExponent >= RTFLOAT64U_EXP_MAX)
1028 return rtStrToLongDoubleReturnInf(psz, ppszNext, cchMax, fPositive, VERR_FLOAT_OVERFLOW, iRetType, pRet);
1029
1030 pRet->rd.s64.uFraction = (uMantissa >> (UINT_MANTISSA_T_BITS - 1 - RTFLOAT64U_FRACTION_BITS))
1031 & (RT_BIT_64(RTFLOAT64U_FRACTION_BITS) - 1);
1032 pRet->rd.s64.uExponent = iExponent;
1033 pRet->rd.s64.fSign = !fPositive;
1034 break;
1035
1036 default:
1037 AssertFailedReturn(VERR_INTERNAL_ERROR_3);
1038 }
1039 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, rc);
1040}
1041
1042
1043/**
1044 * Worker for RTStrToLongDoubleEx, RTStrToDoubleEx and RTStrToFloatEx.
1045 *
1046 * @returns IPRT status code
1047 * @param pszValue The string value to convert.
1048 * @param ppszNext Where to return the pointer to the end of the value.
1049 * Optional.
1050 * @param cchMax Number of bytes left in the string starting at @a psz.
1051 * @param iRetType The return type: float, double or long double.
1052 * @param pRet The return value union.
1053 */
1054static int rtStrToLongDoubleWorker(const char *pszValue, char **ppszNext, size_t cchMax, unsigned iRetType, FLOATUNION *pRet)
1055{
1056 const char *psz = pszValue;
1057 if (!cchMax)
1058 cchMax = ~(size_t)cchMax;
1059
1060 /*
1061 * Sign.
1062 */
1063 bool fPositive = true;
1064 while (cchMax > 0)
1065 {
1066 if (*psz == '+')
1067 fPositive = true;
1068 else if (*psz == '-')
1069 fPositive = !fPositive;
1070 else
1071 break;
1072 psz++;
1073 cchMax--;
1074 }
1075
1076 /*
1077 * Constant like "Inf", "Infinity", "NaN" or "NaN(hexstr)"?
1078 */
1079 /* "Inf" or "Infinity"? */
1080 if (cchMax == 0)
1081 return rtStrToLongDoubleReturnZero(pszValue, ppszNext, cchMax, fPositive, VERR_NO_DIGITS, iRetType, pRet);
1082 if (cchMax >= 3)
1083 {
1084 char ch = *psz;
1085 /* Inf: */
1086 if (ch == 'i' || ch == 'I')
1087 {
1088 if ( ((ch = psz[1]) == 'n' || ch == 'N')
1089 && ((ch = psz[2]) == 'f' || ch == 'F'))
1090 return rtStrToLongDoubleReturnInf(psz + 3, ppszNext, cchMax - 3, fPositive, VINF_SUCCESS, iRetType, pRet);
1091 }
1092 /* Nan: */
1093 else if (ch == 'n' || ch == 'N')
1094 {
1095 if ( ((ch = psz[1]) == 'a' || ch == 'A')
1096 && ((ch = psz[2]) == 'n' || ch == 'N'))
1097 return rtStrToLongDoubleReturnNan(psz + 3, ppszNext, cchMax - 3, fPositive, iRetType, pRet);
1098 }
1099 }
1100
1101 /*
1102 * Check for hex prefix.
1103 */
1104#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
1105 unsigned cMaxDigits = 33;
1106#elif defined(RT_COMPILER_WITH_80BIT_LONG_DOUBLE)
1107 unsigned cMaxDigits = 19;
1108#else
1109 unsigned cMaxDigits = 18;
1110#endif
1111 unsigned uBase = 10;
1112 unsigned uExpDigitFactor = 1;
1113 if (cchMax >= 2 && psz[0] == '0' && (psz[1] == 'x' || psz[1] == 'X'))
1114 {
1115 cMaxDigits = 16;
1116 uBase = 16;
1117 uExpDigitFactor = 4;
1118 cchMax -= 2;
1119 psz += 2;
1120 }
1121
1122 /*
1123 * Now, parse the mantissa.
1124 */
1125#ifdef RT_COMPILER_WITH_128BIT_LONG_DOUBLE
1126 uint8_t abDigits[36];
1127#else
1128 uint8_t abDigits[20];
1129#endif
1130 unsigned cDigits = 0;
1131 unsigned cFractionDigits = 0;
1132 uint8_t fSeenNonZeroDigit = 0;
1133 bool fInFraction = false;
1134 bool fSeenDigits = false;
1135 while (cchMax > 0)
1136 {
1137 uint8_t b = g_auchDigits[(unsigned char)*psz];
1138 if (b < uBase)
1139 {
1140 fSeenDigits = true;
1141 fSeenNonZeroDigit |= b;
1142 if (fSeenNonZeroDigit)
1143 {
1144 if (cDigits < RT_ELEMENTS(abDigits))
1145 abDigits[cDigits] = b;
1146 cDigits++;
1147 cFractionDigits += fInFraction;
1148 }
1149 }
1150 else if (b == DIGITS_DOT && !fInFraction)
1151 fInFraction = true;
1152 else
1153 break;
1154 psz++;
1155 cchMax--;
1156 }
1157
1158 /* If we've seen no digits, or just a dot, return zero already. */
1159 if (!fSeenDigits)
1160 {
1161 if (fInFraction) /* '+.' => 0.0 ? */
1162 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VINF_SUCCESS, iRetType, pRet);
1163 if (uBase == 16) /* '+0x' => 0.0 & *=pszNext="x..." */
1164 return rtStrToLongDoubleReturnZero(psz - 1, ppszNext, cchMax, fPositive, VINF_SUCCESS, iRetType, pRet);
1165 /* '' and '+' -> no digits + 0.0. */
1166 return rtStrToLongDoubleReturnZero(pszValue, ppszNext, cchMax, fPositive, VERR_NO_DIGITS, iRetType, pRet);
1167 }
1168
1169 /*
1170 * Parse the exponent.
1171 * This is optional and we ignore incomplete ones like "e+".
1172 */
1173 int32_t iExponent = 0;
1174 if (cchMax >= 2) /* min "e0" */
1175 {
1176 char ch = *psz;
1177 if (uBase == 10 ? ch == 'e' || ch == 'E' : ch == 'p' || ch == 'P')
1178 {
1179 bool fExpOverflow = false;
1180 bool fPositiveExp = true;
1181 size_t off = 1;
1182 ch = psz[off];
1183 if (ch == '+' || ch == '-')
1184 {
1185 fPositiveExp = ch == '+';
1186 off++;
1187 }
1188 uint8_t b;
1189 if ( off < cchMax
1190 && (b = g_auchDigits[(unsigned char)psz[off]]) < 10)
1191 {
1192 do
1193 {
1194 int32_t const iPreviousExponent = iExponent;
1195 iExponent *= 10;
1196 iExponent += b;
1197 if (iExponent < iPreviousExponent)
1198 fExpOverflow = true;
1199 off++;
1200 } while (off < cchMax && (b = g_auchDigits[(unsigned char)psz[off]]) < 10);
1201 if (!fPositiveExp)
1202 iExponent = -iExponent;
1203 cchMax -= off;
1204 psz += off;
1205 }
1206 if (fExpOverflow || iExponent <= -65536 || iExponent >= 65536)
1207 return rtStrToLongDoubleReturnOverflow(pszValue, ppszNext, cchMax, fPositive, iExponent, iRetType, pRet);
1208 }
1209 }
1210
1211 /* If the mantissa was all zeros, we can return zero now that we're past the exponent. */
1212 if (!fSeenNonZeroDigit)
1213 return rtStrToLongDoubleReturnZero(psz, ppszNext, cchMax, fPositive, VINF_SUCCESS, iRetType, pRet);
1214
1215 /*
1216 * Adjust the expontent so we've got all digits to the left of the decimal point.
1217 */
1218 iExponent -= cFractionDigits * uExpDigitFactor;
1219
1220 /*
1221 * Drop digits we won't translate.
1222 */
1223 if (cDigits > cMaxDigits)
1224 {
1225 iExponent += (cDigits - cMaxDigits) * uExpDigitFactor;
1226 cDigits = cMaxDigits;
1227 }
1228
1229 /*
1230 * Strip least significant zero digits.
1231 */
1232 while (cDigits > 0 && abDigits[cDigits - 1] == 0)
1233 {
1234 cDigits--;
1235 iExponent += uExpDigitFactor;
1236 }
1237
1238 /*
1239 * The hexadecimal is relatively straight forward.
1240 */
1241 if (uBase == 16)
1242 {
1243 UINT_MANTISSA_T uMantissa = 0;
1244 for (unsigned iDigit = 0; iDigit < cDigits; iDigit++)
1245 {
1246 uMantissa |= (UINT_MANTISSA_T)abDigits[iDigit] << (UINT_MANTISSA_T_BITS - 4 - iDigit * 4);
1247 iExponent += 4;
1248 }
1249 Assert(uMantissa != 0);
1250
1251 /* Shift to the left till the most significant bit is 1. */
1252 if (!((uMantissa >> (UINT_MANTISSA_T_BITS - 1)) & 1))
1253 {
1254#if UINT_MANTISSA_T_BITS == 64
1255 unsigned cShift = 64 - ASMBitLastSetU64(uMantissa);
1256 uMantissa <<= cShift;
1257 iExponent -= cShift;
1258 Assert(uMantissa & RT_BIT_64(63));
1259#else
1260 do
1261 {
1262 uMantissa <<= 1;
1263 iExponent -= 1;
1264 } while (!((uMantissa >> (UINT_MANTISSA_T_BITS - 1)) & 1));
1265#endif
1266 }
1267
1268 /* Account for the 1 left of the decimal point. */
1269 iExponent--;
1270
1271 /*
1272 * Produce the return value.
1273 */
1274 return rtStrToLongDoubleReturnValue(psz, ppszNext, cchMax, fPositive, uMantissa, iExponent, iRetType, pRet);
1275 }
1276
1277 /*
1278 * For the decimal format, we'll rely on the floating point conversion of
1279 * the compiler/CPU for the mantissa.
1280 */
1281 UINT_MANTISSA_T uMantissa = 0;
1282 for (unsigned iDigit = 0; iDigit < cDigits; iDigit++)
1283 {
1284 uMantissa *= 10;
1285 uMantissa += abDigits[iDigit];
1286 }
1287 Assert(uMantissa != 0);
1288
1289 LONG_DOUBLE_U_T uTmp;
1290 uTmp.r = fPositive ? (long double)uMantissa : -(long double)uMantissa;
1291
1292 /*
1293 * Here comes the fun part, scaling it according to the power of 10 exponent.
1294 * We only need to consider overflows and underflows when scaling, when
1295 * iExponent is zero we can be sure the target type can handle the result.
1296 */
1297 if (iExponent != 0)
1298 {
1299 rtStrToLongDoubleExp10(&uTmp, iExponent);
1300#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1301 if (!RTFLOAT80U_IS_NORMAL(&uTmp))
1302#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
1303 if (!RTFLOAT128U_IS_NORMAL(&uTmp))
1304#else
1305 if (!RTFLOAT64U_IS_NORMAL(&uTmp))
1306#endif
1307 {
1308#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1309 if (RTFLOAT80U_IS_DENORMAL(&uTmp) && iRetType == RET_TYPE_LONG_DOUBLE)
1310#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
1311 if (RTFLOAT128U_IS_SUBNORMAL(&uTmp) && iRetType == RET_TYPE_LONG_DOUBLE)
1312#else
1313 if (RTFLOAT64U_IS_SUBNORMAL(&uTmp) && iRetType != RET_TYPE_FLOAT)
1314#endif
1315 return rtStrToLongDoubleReturnSubnormal(psz, ppszNext, cchMax, &uTmp, iRetType, pRet);
1316 return rtStrToLongDoubleReturnOverflow(psz, ppszNext, cchMax, fPositive, iExponent, iRetType, pRet);
1317 }
1318 }
1319
1320 /*
1321 * We've got a normal value in uTmp when we get here, just repack it in the
1322 * target format and return.
1323 */
1324#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1325 Assert(RTFLOAT80U_IS_NORMAL(&uTmp));
1326 if (iRetType == RET_TYPE_LONG_DOUBLE)
1327 {
1328 pRet->lrd = uTmp;
1329 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
1330 }
1331 fPositive = uTmp.s.fSign;
1332 iExponent = uTmp.s.uExponent - RTFLOAT80U_EXP_BIAS;
1333 uMantissa = uTmp.s.uMantissa;
1334# if UINT_MANTISSA_T_BITS > 64
1335 uMantissa <<= UINT_MANTISSA_T_BITS - 64;
1336# endif
1337#elif defined(RT_COMPILER_WITH_128BIT_LONG_DOUBLE)
1338 Assert(RTFLOAT128U_IS_NORMAL(&uTmp));
1339 if (iRetType == RET_TYPE_LONG_DOUBLE)
1340 {
1341 pRet->lrd = uTmp;
1342 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
1343 }
1344 fPositive = uTmp.s64.fSign;
1345 iExponent = uTmp.s64.uExponent - RTFLOAT128U_EXP_BIAS;
1346 uMantissa = (UINT_MANTISSA_T)uTmp.s64.uFractionHi << (UINT_MANTISSA_T_BITS - RTFLOAT128U_FRACTION_BITS - 1 + 64);
1347 uMantissa |= (UINT_MANTISSA_T)uTmp.s64.uFractionLo << (UINT_MANTISSA_T_BITS - RTFLOAT128U_FRACTION_BITS - 1);
1348 uMantissa |= (UINT_MANTISSA_T)1 << (UINT_MANTISSA_T_BITS - 1);
1349#else
1350 Assert(RTFLOAT64U_IS_NORMAL(&uTmp));
1351 if ( iRetType == RET_TYPE_DOUBLE
1352 || iRetType == RET_TYPE_LONG_DOUBLE)
1353 {
1354 pRet->rd = uTmp;
1355 return rtStrToLongDoubleReturnChecks(psz, ppszNext, cchMax, VINF_SUCCESS);
1356 }
1357 fPositive = uTmp.s64.fSign;
1358 iExponent = uTmp.s64.uExponent - RTFLOAT64U_EXP_BIAS;
1359 uMantissa = uTmp.s64.uFraction | RT_BIT_64(RTFLOAT64U_FRACTION_BITS);
1360# if UINT_MANTISSA_T_BITS > 64
1361 uMantissa <<= UINT_MANTISSA_T_BITS - 64;
1362# endif
1363#endif
1364 return rtStrToLongDoubleReturnValue(psz, ppszNext, cchMax, fPositive, uMantissa, iExponent, iRetType, pRet);
1365}
1366
1367
1368RTDECL(int) RTStrToLongDoubleEx(const char *pszValue, char **ppszNext, size_t cchMax, long double *plrd)
1369{
1370 FLOATUNION u;
1371 int rc = rtStrToLongDoubleWorker(pszValue, ppszNext, cchMax, RET_TYPE_LONG_DOUBLE, &u);
1372 if (plrd)
1373#ifdef RT_COMPILER_WITH_80BIT_LONG_DOUBLE
1374 *plrd = u.lrd.lrd;
1375#else
1376 *plrd = u.rd.rd;
1377#endif
1378 return rc;
1379}
1380
1381
1382RTDECL(int) RTStrToDoubleEx(const char *pszValue, char **ppszNext, size_t cchMax, double *prd)
1383{
1384 FLOATUNION u;
1385 int rc = rtStrToLongDoubleWorker(pszValue, ppszNext, cchMax, RET_TYPE_DOUBLE, &u);
1386 if (prd)
1387 *prd = u.rd.rd;
1388 return rc;
1389}
1390
1391
1392RTDECL(int) RTStrToFloatEx(const char *pszValue, char **ppszNext, size_t cchMax, float *pr)
1393{
1394 FLOATUNION u;
1395 int rc = rtStrToLongDoubleWorker(pszValue, ppszNext, cchMax, RET_TYPE_FLOAT, &u);
1396 if (pr)
1397 *pr = u.r.r;
1398 return rc;
1399}
1400
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use