diff options
Diffstat (limited to 'libgfortran/io')
-rw-r--r-- | libgfortran/io/read.c | 13 | ||||
-rw-r--r-- | libgfortran/io/transfer128.c | 4 | ||||
-rw-r--r-- | libgfortran/io/write_float.def | 54 |
3 files changed, 68 insertions, 3 deletions
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c index 21e7851..8e9d50d 100644 --- a/libgfortran/io/read.c +++ b/libgfortran/io/read.c @@ -186,7 +186,11 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length) #if defined(HAVE_GFC_REAL_16) # if defined(GFC_REAL_16_IS_FLOAT128) case 16: +# if defined(GFC_REAL_16_USE_IEC_60559) + *((GFC_REAL_16*) dest) = strtof128 (buffer, &endptr); +# else *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, &endptr); +# endif break; # elif defined(HAVE_STRTOLD) case 16: @@ -199,6 +203,8 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length) case 17: # if defined(POWER_IEEE128) *((GFC_REAL_17*) dest) = __strtoieee128 (buffer, &endptr); +# elif defined(GFC_REAL_17_USE_IEC_60559) + *((GFC_REAL_17*) dest) = strtof128 (buffer, &endptr); # else *((GFC_REAL_17*) dest) = __qmath_(strtoflt128) (buffer, &endptr); # endif @@ -272,7 +278,14 @@ convert_infnan (st_parameter_dt *dtp, void *dest, const char *buffer, #if defined(HAVE_GFC_REAL_16) # if defined(GFC_REAL_16_IS_FLOAT128) case 16: +# if defined(GFC_REAL_16_USE_IEC_60559) + if (is_inf) + *((GFC_REAL_16*) dest) = plus ? __builtin_inff128 () : -__builtin_inff128 (); + else + *((GFC_REAL_16*) dest) = plus ? __builtin_nanf128 ("") : -__builtin_nanf128 (""); +# else *((GFC_REAL_16*) dest) = __qmath_(strtoflt128) (buffer, NULL); +# endif break; # else case 16: diff --git a/libgfortran/io/transfer128.c b/libgfortran/io/transfer128.c index 7372ad7..8f30730 100644 --- a/libgfortran/io/transfer128.c +++ b/libgfortran/io/transfer128.c @@ -65,7 +65,9 @@ export_proto(transfer_complex128_write); write_float; the pointer assignment with USED attribute make sure that there is a non-weakref dependence if the quadmath functions are used. That avoids segfault when libquadmath is statically linked. */ -# if !defined(HAVE_GFC_REAL_17) || !defined(POWER_IEEE128) +# if (defined(HAVE_GFC_REAL_17) && !defined(POWER_IEEE128) \ + && !defined(GFC_REAL_17_USE_IEC_60559)) \ + || (!defined(HAVE_GFC_REAL_17) && !defined(GFC_REAL_16_USE_IEC_60559)) static void __attribute__((used)) *tmp1 = strtoflt128; static void __attribute__((used)) *tmp2 = quadmath_snprintf; # endif diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def index 1f4be0d..a4d8493 100644 --- a/libgfortran/io/write_float.def +++ b/libgfortran/io/write_float.def @@ -837,18 +837,60 @@ snprintf (buffer, size, "%+-#.*e", (prec), (val)) #define DTOA2L(prec,val) \ snprintf (buffer, size, "%+-#.*Le", (prec), (val)) +#if defined(GFC_REAL_16_USE_IEC_60559) || defined(GFC_REAL_17_USE_IEC_60559) +/* strfromf128 unfortunately doesn't allow +, - and # modifiers + nor .* (only allows .number). For +, work around it by adding + leading + manually for !signbit values. For - I don't see why + we need it, when we don't specify field minimum width. + For #, add . if it is missing. Assume size is at least 2. */ +static int +gfor_strfromf128 (char *buffer, size_t size, int kind, int prec, _Float128 val) +{ + int ret, n = 0; + char fmt[sizeof (int) * 3 + 5]; + snprintf (fmt, sizeof fmt, "%%.%d%c", prec, kind); + if (!__builtin_signbit (val)) + { + n = 1; + buffer[0] = '+'; + } + ret = strfromf128 (buffer + n, size - n, fmt, val) + n; + if ((size_t) ret < size - 1) + { + size_t s = strcspn (buffer, ".e"); + if (buffer[s] != '.') + { + if (buffer[s] == '\0') + buffer[s + 1] = '\0'; + else + memmove (buffer + s + 1, buffer + s, ret + 1 - s); + buffer[s] = '.'; + ++ret; + } + } + return ret; +} +#endif #if defined(HAVE_GFC_REAL_17) # if defined(POWER_IEEE128) # define DTOA2Q(prec,val) \ __snprintfieee128 (buffer, size, "%+-#.*Le", (prec), (val)) +# elif defined(GFC_REAL_17_USE_IEC_60559) +# define DTOA2Q(prec,val) \ +gfor_strfromf128 (buffer, size, 'e', (prec), (val)) # else # define DTOA2Q(prec,val) \ quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val)) # endif #elif defined(GFC_REAL_16_IS_FLOAT128) -# define DTOA2Q(prec,val) \ +# if defined(GFC_REAL_16_USE_IEC_60559) +# define DTOA2Q(prec,val) \ +gfor_strfromf128 (buffer, size, 'e', (prec), (val)) +# else +# define DTOA2Q(prec,val) \ quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val)) +# endif #endif #define FDTOA(suff,prec,val) TOKENPASTE(FDTOA2,suff)(prec,val) @@ -865,13 +907,21 @@ snprintf (buffer, size, "%+-#.*Lf", (prec), (val)) # if defined(POWER_IEEE128) # define FDTOA2Q(prec,val) \ __snprintfieee128 (buffer, size, "%+-#.*Lf", (prec), (val)) +# elif defined(GFC_REAL_17_USE_IEC_60559) +# define FDTOA2Q(prec,val) \ +gfor_strfromf128 (buffer, size, 'f', (prec), (val)) # else # define FDTOA2Q(prec,val) \ quadmath_snprintf (buffer, size, "%+-#.*Qf", (prec), (val)) # endif #elif defined(GFC_REAL_16_IS_FLOAT128) -# define FDTOA2Q(prec,val) \ +# if defined(GFC_REAL_16_USE_IEC_60559) +# define FDTOA2Q(prec,val) \ +gfor_strfromf128 (buffer, size, 'f', (prec), (val)) +# else +# define FDTOA2Q(prec,val) \ quadmath_snprintf (buffer, size, "%+-#.*Qf", (prec), (val)) +# endif #endif |