VirtualBox

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

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

IPRT/strtofloat.cpp: Addditions build fix attempt. bugref:10261

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