diff options
author | Gabriel F. T. Gomes <gftg@linux.vnet.ibm.com> | 2016-11-03 12:37:08 -0200 |
---|---|---|
committer | Gabriel F. T. Gomes <gftg@linux.vnet.ibm.com> | 2017-06-07 17:08:21 -0300 |
commit | cf2046ec7dd4b233180377cc5b8debcf551d1fc9 (patch) | |
tree | 40f45dc6bb3c49eadff4653c2a9ab0775f2f9cf7 /stdio-common | |
parent | 2bc646c9e95b7c0005b2bc09c06671ffbb509629 (diff) | |
download | glibc-cf2046ec7dd4b233180377cc5b8debcf551d1fc9.tar.gz glibc-cf2046ec7dd4b233180377cc5b8debcf551d1fc9.tar.xz glibc-cf2046ec7dd4b233180377cc5b8debcf551d1fc9.zip |
float128: Add strfromf128
Add strfromf128 to stdlib when _Float128 support is enabled. * stdio-common/printf-parsemb.c (__parse_one_specmb): Initialize spec->info.is_binary128 to zero. * stdio-common/printf.h (printf_info): Add new member is_binary128 to indicate that the number being converted to string is compatible with the IEC 60559 binary128 format. * stdio-common/printf_fp.c (__printf_fp_l): Add code to deal with _Float128 numbers. * stdio-common/printf_fphex.c: Include ieee754_float128.h and ldbl-128/printf_fphex_macros.h (__printf_fphex): Add code to deal with _Float128 numbers. * stdio-common/printf_size.c (__printf_size): Likewise. * stdio-common/vfprintf.c (process_arg): Initialize member info.is_binary128 to zero. * stdlib/fpioconst.h (FLT128_MAX_10_EXP_LOG): New macro. * stdlib/stdlib.h: Include bits/floatn.h for _Float128 support. (strfromf128): New declaration. * stdlib/strfrom-skeleton.c (STRFROM): Set member info.is_binary128 to one. * sysdeps/ieee754/float128/Makefile: Add strfromf128. * sysdeps/ieee754/float128/Versions: Likewise. * sysdeps/ieee754/float128/strfromf128.c: New file.
Diffstat (limited to 'stdio-common')
-rw-r--r-- | stdio-common/printf-parsemb.c | 1 | ||||
-rw-r--r-- | stdio-common/printf.h | 4 | ||||
-rw-r--r-- | stdio-common/printf_fp.c | 62 | ||||
-rw-r--r-- | stdio-common/printf_fphex.c | 21 | ||||
-rw-r--r-- | stdio-common/printf_size.c | 8 | ||||
-rw-r--r-- | stdio-common/vfprintf.c | 10 |
6 files changed, 99 insertions, 7 deletions
diff --git a/stdio-common/printf-parsemb.c b/stdio-common/printf-parsemb.c index edb066edf6..a42336c538 100644 --- a/stdio-common/printf-parsemb.c +++ b/stdio-common/printf-parsemb.c @@ -79,6 +79,7 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn, spec->info.extra = 0; spec->info.pad = ' '; spec->info.wide = sizeof (UCHAR_T) > 1; + spec->info.is_binary128 = 0; /* Test for positional argument. */ if (ISDIGIT (*format)) diff --git a/stdio-common/printf.h b/stdio-common/printf.h index 5d82e8d01e..6b207d2db7 100644 --- a/stdio-common/printf.h +++ b/stdio-common/printf.h @@ -47,7 +47,9 @@ struct printf_info unsigned int is_char:1; /* hh flag. */ unsigned int wide:1; /* Nonzero for wide character streams. */ unsigned int i18n:1; /* I flag. */ - unsigned int __pad:4; /* Unused so far. */ + unsigned int is_binary128:1; /* Floating-point argument is ABI-compatible + with IEC 60559 binary128. */ + unsigned int __pad:3; /* Unused so far. */ unsigned short int user; /* Bits for user-installed modifiers. */ wchar_t pad; /* Padding character. */ }; diff --git a/stdio-common/printf_fp.c b/stdio-common/printf_fp.c index 65ee9a7937..514b698d27 100644 --- a/stdio-common/printf_fp.c +++ b/stdio-common/printf_fp.c @@ -218,6 +218,9 @@ __printf_fp_l (FILE *fp, locale_t loc, { double dbl; __long_double_t ldbl; +#if __HAVE_DISTINCT_FLOAT128 + _Float128 f128; +#endif } fpnum; @@ -234,9 +237,17 @@ __printf_fp_l (FILE *fp, locale_t loc, const char *special = NULL; const wchar_t *wspecial = NULL; + /* When _Float128 is enabled in the library and ABI-distinct from long + double, we need mp_limbs enough for any of them. */ +#if __HAVE_DISTINCT_FLOAT128 +# define GREATER_MANT_DIG FLT128_MANT_DIG +#else +# define GREATER_MANT_DIG LDBL_MANT_DIG +#endif /* We need just a few limbs for the input before shifting to the right position. */ - mp_limb_t fp_input[(LDBL_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB]; + mp_limb_t fp_input[(GREATER_MANT_DIG + BITS_PER_MP_LIMB - 1) + / BITS_PER_MP_LIMB]; /* We need to shift the contents of fp_input by this amount of bits. */ int to_shift = 0; @@ -371,6 +382,11 @@ __printf_fp_l (FILE *fp, locale_t loc, } /* Fetch the argument value. */ +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINTF_FP_FETCH (_Float128, fpnum.f128, float128, FLT128_MANT_DIG) + else +#endif #ifndef __NO_LONG_DOUBLE_MATH if (info->is_long_double && sizeof (long double) > sizeof (double)) PRINTF_FP_FETCH (long double, fpnum.ldbl, long_double, LDBL_MANT_DIG) @@ -414,7 +430,8 @@ __printf_fp_l (FILE *fp, locale_t loc, { mp_size_t bignum_size = ((abs (p.exponent) + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB - + (LDBL_MANT_DIG / BITS_PER_MP_LIMB > 2 ? 8 : 4)) + + (GREATER_MANT_DIG / BITS_PER_MP_LIMB > 2 + ? 8 : 4)) * sizeof (mp_limb_t); p.frac = (mp_limb_t *) alloca (bignum_size); p.tmp = (mp_limb_t *) alloca (bignum_size); @@ -429,7 +446,15 @@ __printf_fp_l (FILE *fp, locale_t loc, { /* |FP| >= 8.0. */ int scaleexpo = 0; - int explog = LDBL_MAX_10_EXP_LOG; + int explog; +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + explog = FLT128_MAX_10_EXP_LOG; + else + explog = LDBL_MAX_10_EXP_LOG; +#else + explog = LDBL_MAX_10_EXP_LOG; +#endif int exp10 = 0; const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; int cnt_h, cnt_l, i; @@ -463,6 +488,27 @@ __printf_fp_l (FILE *fp, locale_t loc, { if (p.scalesize == 0) { +#if __HAVE_DISTINCT_FLOAT128 + if ((FLT128_MANT_DIG + > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB) + && info->is_binary128) + { +#define _FLT128_FPIO_CONST_SHIFT \ + (((FLT128_MANT_DIG + BITS_PER_MP_LIMB - 1) / BITS_PER_MP_LIMB) \ + - _FPIO_CONST_OFFSET) + /* 64bit const offset is not enough for + IEEE 854 quad long double (_Float128). */ + p.tmpsize = powers->arraysize + _FLT128_FPIO_CONST_SHIFT; + memcpy (p.tmp + _FLT128_FPIO_CONST_SHIFT, + &__tens[powers->arrayoff], + p.tmpsize * sizeof (mp_limb_t)); + MPN_ZERO (p.tmp, _FLT128_FPIO_CONST_SHIFT); + /* Adjust p.exponent, as scaleexpo will be this much + bigger too. */ + p.exponent += _FLT128_FPIO_CONST_SHIFT * BITS_PER_MP_LIMB; + } + else +#endif /* __HAVE_DISTINCT_FLOAT128 */ #ifndef __NO_LONG_DOUBLE_MATH if (LDBL_MANT_DIG > _FPIO_CONST_OFFSET * BITS_PER_MP_LIMB && info->is_long_double) @@ -603,7 +649,15 @@ __printf_fp_l (FILE *fp, locale_t loc, { /* |FP| < 1.0. */ int exp10 = 0; - int explog = LDBL_MAX_10_EXP_LOG; + int explog; +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + explog = FLT128_MAX_10_EXP_LOG; + else + explog = LDBL_MAX_10_EXP_LOG; +#else + explog = LDBL_MAX_10_EXP_LOG; +#endif const struct mp_power *powers = &_fpioconst_pow10[explog + 1]; /* Now shift the input value to its right place. */ diff --git a/stdio-common/printf_fphex.c b/stdio-common/printf_fphex.c index 7b469c047e..004d2aa716 100644 --- a/stdio-common/printf_fphex.c +++ b/stdio-common/printf_fphex.c @@ -31,6 +31,14 @@ #include <stdbool.h> #include <rounding-mode.h> +#if __HAVE_DISTINCT_FLOAT128 +# include "ieee754_float128.h" +# include <ldbl-128/printf_fphex_macros.h> +# define PRINT_FPHEX_FLOAT128 \ + PRINT_FPHEX (_Float128, fpnum.flt128, ieee854_float128, \ + IEEE854_FLOAT128_BIAS) +#endif + /* #define NDEBUG 1*/ /* Undefine this for debugging assertions. */ #include <assert.h> @@ -94,6 +102,9 @@ __printf_fphex (FILE *fp, { union ieee754_double dbl; long double ldbl; +#if __HAVE_DISTINCT_FLOAT128 + _Float128 flt128; +#endif } fpnum; @@ -195,6 +206,11 @@ __printf_fphex (FILE *fp, } /* Fetch the argument value. */ +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINTF_FPHEX_FETCH (_Float128, fpnum.flt128) + else +#endif #ifndef __NO_LONG_DOUBLE_MATH if (info->is_long_double && sizeof (long double) > sizeof (double)) PRINTF_FPHEX_FETCH (long double, fpnum.ldbl) @@ -230,6 +246,11 @@ __printf_fphex (FILE *fp, return done; } +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINT_FPHEX_FLOAT128; + else +#endif if (info->is_long_double == 0 || sizeof (double) == sizeof (long double)) { /* We have 52 bits of mantissa plus one implicit digit. Since diff --git a/stdio-common/printf_size.c b/stdio-common/printf_size.c index bc953dc53c..e20b76cf91 100644 --- a/stdio-common/printf_size.c +++ b/stdio-common/printf_size.c @@ -104,6 +104,9 @@ __printf_size (FILE *fp, const struct printf_info *info, { union ieee754_double dbl; long double ldbl; +#if __HAVE_DISTINCT_FLOAT128 + _Float128 f128; +#endif } fpnum; const void *ptr = &fpnum; @@ -144,6 +147,11 @@ __printf_size (FILE *fp, const struct printf_info *info, } /* Fetch the argument value. */ +#if __HAVE_DISTINCT_FLOAT128 + if (info->is_binary128) + PRINTF_SIZE_FETCH (_Float128, fpnum.f128) + else +#endif #ifndef __NO_LONG_DOUBLE_MATH if (info->is_long_double && sizeof (long double) > sizeof (double)) PRINTF_SIZE_FETCH (long double, fpnum.ldbl) diff --git a/stdio-common/vfprintf.c b/stdio-common/vfprintf.c index 2cf7c8aa0b..b8c87a539f 100644 --- a/stdio-common/vfprintf.c +++ b/stdio-common/vfprintf.c @@ -770,7 +770,8 @@ static const uint8_t jump_table[] = .pad = pad, \ .extra = 0, \ .i18n = use_outdigits, \ - .wide = sizeof (CHAR_T) != 1 }; \ + .wide = sizeof (CHAR_T) != 1, \ + .is_binary128 = 0}; \ \ if (is_long_double) \ the_arg.pa_long_double = va_arg (ap, long double); \ @@ -788,6 +789,8 @@ static const uint8_t jump_table[] = fspec->data_arg_type = PA_DOUBLE; \ fspec->info.is_long_double = 0; \ } \ + /* Not supported by *printf functions. */ \ + fspec->info.is_binary128 = 0; \ \ function_done = __printf_fp (s, &fspec->info, &ptr); \ } \ @@ -827,7 +830,8 @@ static const uint8_t jump_table[] = .group = group, \ .pad = pad, \ .extra = 0, \ - .wide = sizeof (CHAR_T) != 1 }; \ + .wide = sizeof (CHAR_T) != 1, \ + .is_binary128 = 0}; \ \ if (is_long_double) \ the_arg.pa_long_double = va_arg (ap, long double); \ @@ -842,6 +846,8 @@ static const uint8_t jump_table[] = ptr = (const void *) &args_value[fspec->data_arg]; \ if (__ldbl_is_dbl) \ fspec->info.is_long_double = 0; \ + /* Not supported by *printf functions. */ \ + fspec->info.is_binary128 = 0; \ \ function_done = __printf_fphex (s, &fspec->info, &ptr); \ } \ |