VirtualBox

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

Last change on this file since 96181 was 96181, checked in by vboxsync, 3 years ago

IPRT: Added RTStrNanLongDouble, RTStrNanDouble and RTStrNanFloat (they are RTStr as they share code with RTStrToLongDouble and friends handling NaN tags). [build fix] bugref:10261

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette