VirtualBox

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

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

IPRT/strttofloat.cpp: Some fixes and blind attempt at making it build on sparc. bugref:10261

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