aboutsummaryrefslogtreecommitdiff
path: root/newlib/libc/stdlib/strtold.c
diff options
context:
space:
mode:
authorZakaria Fadli <fadli@adacore.com>2025-09-22 19:11:33 +0200
committerJeff Johnston <jjohnstn@redhat.com>2025-09-22 14:54:00 -0400
commit63dc988ac7454b701ee923590f18df4103587994 (patch)
treecef15e41c706117180943e674a7ce8ec056b069b /newlib/libc/stdlib/strtold.c
parent8a5d39527f9a56d1a623e86d30af6b590fd1472d (diff)
downloadnewlib-main.zip
newlib-main.tar.gz
newlib-main.tar.bz2
newlib: strtold: Import strtorQ for 128-bit long double supportHEADmastermain
The implementation of strtorQ is imported from FreeBSD's gdtoa library (By David M. Gay) with some adaptations to fit with newlib. `strtorQ.c` enables `strtold` to perform correct parsing on targets where long double uses the IEEE754 binary128 format (113-bit mantissa), such as AArch64. Without this patch, strtold would wrongly fallback to `strtorx` which will parse into a 80-bit long double and give invalid result. * libc/stdlib/strtorQ.c: New file, adapted from FreeBSD gdtoa. * libc/stdlib/strtold.c (_strtold_impl): New helper selecting strtorx for 80-bit and strtorQ for 128-bit long double. (_strtold_r, strtold_l, strtold): Use _strtold_impl. * libc/stdlib/mprec.h (_strtorQ_l): Declare. * libc/stdlib/Makefile.inc (libc_a_SOURCES): Add strtorQ.c. * newlib/Makefile.in: Regenerate with automake Signed-off-by: Zakaria Fadli <fadli@adacore.com>
Diffstat (limited to 'newlib/libc/stdlib/strtold.c')
-rw-r--r--newlib/libc/stdlib/strtold.c56
1 files changed, 27 insertions, 29 deletions
diff --git a/newlib/libc/stdlib/strtold.c b/newlib/libc/stdlib/strtold.c
index 6bd1c2c..57cc38e 100644
--- a/newlib/libc/stdlib/strtold.c
+++ b/newlib/libc/stdlib/strtold.c
@@ -58,47 +58,45 @@ __flt_rounds(void)
#define FLT_ROUNDS 0
#endif
-long double
-_strtold_r (struct _reent *ptr, const char *__restrict s00,
- char **__restrict se)
-{
-#ifdef _LDBL_EQ_DBL
- /* On platforms where long double is as wide as double. */
- return _strtod_l (ptr, s00, se, __get_current_locale ());
-#else
+/*
+ * The core implementation for the strtold family of functions, handling
+ * different long double formats.
+ */
+static long double
+_strtold_impl(struct _reent *ptr, const char *__restrict s00,
+ char **__restrict se, locale_t loc) {
+#if defined(_LDBL_EQ_DBL)
+ /* On platforms where long double is as wide as double. */
+ return _strtod_l(ptr, s00, se, loc);
+#elif LDBL_MANT_DIG == 64 /* For 80 bit long doubles */
long double result;
-
- _strtorx_l (ptr, s00, se, FLT_ROUNDS, &result, __get_current_locale ());
+ _strtorx_l(ptr, s00, se, FLT_ROUNDS, &result, loc);
return result;
+#elif LDBL_MANT_DIG == 113 /* For 128bit long doubles */
+ long double result;
+ _strtorQ_l(ptr, s00, se, FLT_ROUNDS, &result, loc);
+ return result;
+#else
+#warning "strtold not implemented for this long double format"
+ return (long double)_strtod_l(ptr, s00, se, loc);
#endif
}
long double
-strtold_l (const char *__restrict s00, char **__restrict se, locale_t loc)
-{
-#ifdef _LDBL_EQ_DBL
- /* On platforms where long double is as wide as double. */
- return _strtod_l (_REENT, s00, se, loc);
-#else
- long double result;
+_strtold_r(struct _reent *ptr, const char *__restrict s00,
+ char **__restrict se) {
+ return _strtold_impl(ptr, s00, se, __get_current_locale());
+}
- _strtorx_l (_REENT, s00, se, FLT_ROUNDS, &result, loc);
- return result;
-#endif
+long double
+strtold_l(const char *__restrict s00, char **__restrict se, locale_t loc) {
+ return _strtold_impl(_REENT, s00, se, loc);
}
long double
strtold (const char *__restrict s00, char **__restrict se)
{
-#ifdef _LDBL_EQ_DBL
- /* On platforms where long double is as wide as double. */
- return _strtod_l (_REENT, s00, se, __get_current_locale ());
-#else
- long double result;
-
- _strtorx_l (_REENT, s00, se, FLT_ROUNDS, &result, __get_current_locale ());
- return result;
-#endif
+ return _strtold_impl(_REENT, s00, se, __get_current_locale());
}
#endif /* _HAVE_LONG_DOUBLE */