diff options
Diffstat (limited to 'libgfortran/io')
-rw-r--r-- | libgfortran/io/io.h | 6 | ||||
-rw-r--r-- | libgfortran/io/read.c | 41 | ||||
-rw-r--r-- | libgfortran/io/size_from_kind.c | 8 | ||||
-rw-r--r-- | libgfortran/io/transfer128.c | 4 | ||||
-rw-r--r-- | libgfortran/io/write.c | 19 | ||||
-rw-r--r-- | libgfortran/io/write_float.def | 37 |
6 files changed, 105 insertions, 10 deletions
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h index b2267d5..23f63d4 100644 --- a/libgfortran/io/io.h +++ b/libgfortran/io/io.h @@ -1063,7 +1063,8 @@ default_width_for_float (int kind) { case 4: return 15; case 8: return 25; - case 16: return 42; + case 16: + case 17: return 42; default: return 0; } } @@ -1075,7 +1076,8 @@ default_precision_for_float (int kind) { case 4: return 7; case 8: return 16; - case 16: return 33; + case 16: + case 17: return 33; default: return 0; } } diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c index 52e98fb..49d7983a 100644 --- a/libgfortran/io/read.c +++ b/libgfortran/io/read.c @@ -46,6 +46,14 @@ set_integer (void *dest, GFC_INTEGER_LARGEST value, int length) switch (length) { #ifdef HAVE_GFC_INTEGER_16 +#ifdef HAVE_GFC_REAL_17 + case 17: + { + GFC_INTEGER_16 tmp = value; + memcpy (dest, (void *) &tmp, 16); + } + break; +#endif /* length=10 comes about for kind=10 real/complex BOZ, cf. PR41711. */ case 10: case 16: @@ -95,7 +103,14 @@ si_max (int length) #endif switch (length) - { + { +#if defined HAVE_GFC_REAL_17 + case 17: + value = 1; + for (int n = 1; n < 4 * 16; n++) + value = (value << 2) + 3; + return value; +#endif #if defined HAVE_GFC_REAL_16 || defined HAVE_GFC_REAL_10 case 16: case 10: @@ -180,6 +195,15 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length) # endif #endif +#if defined(HAVE_GFC_REAL_17) + case 17: +# if defined(POWER_IEEE128) + *((GFC_REAL_17*) dest) = __strtoieee128 (buffer, &endptr); +# else + *((GFC_REAL_17*) dest) = __qmath_(strtoflt128) (buffer, &endptr); +# endif +#endif + default: internal_error (&dtp->common, "Unsupported real kind during IO"); } @@ -259,6 +283,15 @@ convert_infnan (st_parameter_dt *dtp, void *dest, const char *buffer, # endif #endif +#if defined(HAVE_GFC_REAL_17) + case 17: + if (is_inf) + *((GFC_REAL_17*) dest) = plus ? __builtin_infl () : -__builtin_infl (); + else + *((GFC_REAL_17*) dest) = plus ? __builtin_nanl ("") : -__builtin_nanl (""); + break; +#endif + default: internal_error (&dtp->common, "Unsupported real kind during IO"); } @@ -1224,6 +1257,12 @@ zero: break; #endif +#ifdef HAVE_GFC_REAL_17 + case 17: + *((GFC_REAL_17 *) dest) = 0.0; + break; +#endif + default: internal_error (&dtp->common, "Unsupported real kind during IO"); } diff --git a/libgfortran/io/size_from_kind.c b/libgfortran/io/size_from_kind.c index 6601a0f..f09e340 100644 --- a/libgfortran/io/size_from_kind.c +++ b/libgfortran/io/size_from_kind.c @@ -49,6 +49,10 @@ size_from_real_kind (int kind) case 16: return sizeof (GFC_REAL_16); #endif +#ifdef HAVE_GFC_REAL_17 + case 17: + return sizeof (GFC_REAL_17); +#endif default: return kind; } @@ -76,6 +80,10 @@ size_from_complex_kind (int kind) case 16: return sizeof (GFC_COMPLEX_16); #endif +#ifdef HAVE_GFC_COMPLEX_17 + case 17: + return sizeof (GFC_COMPLEX_17); +#endif default: return 2 * kind; } diff --git a/libgfortran/io/transfer128.c b/libgfortran/io/transfer128.c index cb1a2bc..7372ad7 100644 --- a/libgfortran/io/transfer128.c +++ b/libgfortran/io/transfer128.c @@ -28,7 +28,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include "io.h" -#if defined(GFC_REAL_16_IS_FLOAT128) +#if defined(GFC_REAL_16_IS_FLOAT128) || defined(HAVE_GFC_REAL_17) /* The prototypes for the called procedures in transfer.c. */ @@ -65,8 +65,10 @@ 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) static void __attribute__((used)) *tmp1 = strtoflt128; static void __attribute__((used)) *tmp2 = quadmath_snprintf; +# endif void transfer_real128 (st_parameter_dt *dtp, void *p, int kind) diff --git a/libgfortran/io/write.c b/libgfortran/io/write.c index ce5da0b..5e025a1 100644 --- a/libgfortran/io/write.c +++ b/libgfortran/io/write.c @@ -648,6 +648,15 @@ extract_uint (const void *p, int len) i = (GFC_UINTEGER_16) tmp; } break; +# ifdef HAVE_GFC_REAL_17 + case 17: + { + GFC_INTEGER_16 tmp = 0; + memcpy ((void *) &tmp, p, 16); + i = (GFC_UINTEGER_16) tmp; + } + break; +# endif #endif default: internal_error (NULL, "bad integer kind"); @@ -1543,6 +1552,9 @@ size_from_kind (st_parameter_dt *dtp, const fnode *f, int kind) size = 4932 + 3; break; case 16: +#ifdef HAVE_GFC_REAL_17 + case 17: +#endif size = 4932 + 3; break; default: @@ -1699,6 +1711,13 @@ set_fnode_default (st_parameter_dt *dtp, fnode *f, int length) f->u.real.e = 4; #endif break; +#ifdef HAVE_GFC_REAL_17 + case 17: + f->u.real.w = 45; + f->u.real.d = 36; + f->u.real.e = 4; + break; +#endif default: internal_error (&dtp->common, "bad real kind"); break; diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def index c2ba6fc..5dadf7b 100644 --- a/libgfortran/io/write_float.def +++ b/libgfortran/io/write_float.def @@ -834,8 +834,16 @@ snprintf (buffer, size, "%+-#.*e", (prec), (val)) snprintf (buffer, size, "%+-#.*Le", (prec), (val)) -#if defined(GFC_REAL_16_IS_FLOAT128) -#define DTOA2Q(prec,val) \ +#if defined(HAVE_GFC_REAL_17) +# if defined(POWER_IEEE128) +# define DTOA2Q(prec,val) \ +__snprintfieee128 (buffer, size, "%+-#.*Le", (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) \ quadmath_snprintf (buffer, size, "%+-#.*Qe", (prec), (val)) #endif @@ -849,10 +857,17 @@ snprintf (buffer, size, "%+-#.*f", (prec), (val)) snprintf (buffer, size, "%+-#.*Lf", (prec), (val)) -#if defined(GFC_REAL_16_IS_FLOAT128) -#define FDTOA2Q(prec,val) \ -quadmath_snprintf (buffer, size, "%+-#.*Qf", \ - (prec), (val)) +#if defined(HAVE_GFC_REAL_17) +# if defined(POWER_IEEE128) +# define FDTOA2Q(prec,val) \ +__snprintfieee128 (buffer, size, "%+-#.*Lf", (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) \ +quadmath_snprintf (buffer, size, "%+-#.*Qf", (prec), (val)) #endif @@ -925,6 +940,11 @@ determine_en_precision (st_parameter_dt *dtp, const fnode *f, # endif break; #endif +#ifdef HAVE_GFC_REAL_17 + case 17: + EN_PREC(16,Q) +#endif + break; default: internal_error (NULL, "bad real kind"); } @@ -1128,6 +1148,11 @@ get_float_string (st_parameter_dt *dtp, const fnode *f, const char *source, # endif break; #endif +#ifdef HAVE_GFC_REAL_17 + case 17: + FORMAT_FLOAT(16,Q) + break; +#endif default: internal_error (NULL, "bad real kind"); } |