Commit 05abb346 by Tobias Burnus Committed by Tobias Burnus

quadmath-rounding-mode.h: New.

2012-11-23  Tobias Burnus  <burnus@net-b.de>
            Joseph Myers  <joseph@codesourcery.com>

        * quadmath-rounding-mode.h: New.
        * printf/fpioconst.c: Update from GLIBC. Fix strtod rounding.
        * printf/fpioconst.h: Ditto.
        * printf/printf_fp.c (__quadmath_printf_fp): Update from GLIBC.
        Make printf respect the rounding mode for decimal output.
        * printf/printf_fphex.c (__quadmath_printf_fphex): Update from
        GLIBC.  Make printf respect the rounding mode for hex output.
        * strtod/strtod_l.c: Update from GLIBC. Make strtod respect the
        rounding mode. Fix strtod handling of underflow.


Co-Authored-By: Joseph Myers <joseph@codesourcery.com>

From-SVN: r193770
parent aa66b299
2012-11-23 Tobias Burnus <burnus@net-b.de>
Joseph Myers <joseph@codesourcery.com>
* quadmath-rounding-mode.h: New.
* printf/fpioconst.c: Update from GLIBC. Fix strtod rounding.
* printf/fpioconst.h: Ditto.
* printf/printf_fp.c (__quadmath_printf_fp): Update from GLIBC.
Make printf respect the rounding mode for decimal output.
* printf/printf_fphex.c (__quadmath_printf_fphex): Update from
GLIBC. Make printf respect the rounding mode for hex output.
* strtod/strtod_l.c: Update from GLIBC. Make strtod respect the
rounding mode. Fix strtod handling of underflow.
2012-11-22 David S. Miller <davem@davemloft.net>
Tobias Burnus <burnus@net-b.de>
Joseph Myers <joseph@codesourcery.com>
......
......@@ -35,6 +35,14 @@
#define FLT128_MAX_10_EXP_LOG 12 /* = floor(log_2(FLT128_MAX_10_EXP)) */
/* For strtoq, we need powers of 10 up to floor (log_2 (FLT128_MANT_DIG
- FLT128_MIN_EXP + 2)). */
#if !defined __NO_LONG_DOUBLE_MATH && FLT128_MAX_EXP > 1024
# define FPIOCONST_POW10_ARRAY_SIZE 15
#else
# define FPIOCONST_POW10_ARRAY_SIZE 11
#endif
/* The array with the number representation. */
#define __tens __quadmath_tens
......@@ -50,7 +58,7 @@ struct mp_power
int m_expo; /* Exponent of the number 10^-(2^i-1). */
};
#define _fpioconst_pow10 __quadmath_fpioconst_pow10
extern const struct mp_power _fpioconst_pow10[FLT128_MAX_10_EXP_LOG + 1]
extern const struct mp_power _fpioconst_pow10[FPIOCONST_POW10_ARRAY_SIZE]
attribute_hidden;
/* The constants in the array `_fpioconst_pow10' have an offset. */
......
/* Floating point output for `printf'.
Copyright (C) 1995-2003, 2006-2008, 2011 Free Software Foundation, Inc.
Copyright (C) 1995-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
......@@ -15,16 +15,17 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <config.h>
#include <float.h>
#include <limits.h>
#include <math.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#define NDEBUG
#include <assert.h>
#ifdef HAVE_ERRNO_H
......@@ -32,6 +33,9 @@
#endif
#include <stdio.h>
#include <stdarg.h>
#ifdef HAVE_FENV_H
#include "quadmath-rounding-mode.h"
#endif
#include "quadmath-printf.h"
#include "fpioconst.h"
......@@ -162,7 +166,8 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp,
MPN_VAR(tmp);
/* Digit which is result of last hack_digit() call. */
wchar_t digit;
wchar_t last_digit, next_digit;
bool more_bits;
/* The type of output format that will be used: 'e'/'E' or 'f'. */
int type;
......@@ -370,11 +375,11 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp,
special = "NAN";
wspecial = L_("NAN");
}
else
{
special = "nan";
else
{
special = "nan";
wspecial = L_("nan");
}
}
}
else if (isinfq (fpnum))
{
......@@ -935,33 +940,32 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp,
}
/* Do rounding. */
digit = hack_digit ();
if (digit > L_('4'))
last_digit = wcp[-1] != decimalwc ? wcp[-1] : wcp[-2];
next_digit =hack_digit ();
if (next_digit != L_('0') && next_digit != L_('5'))
more_bits = true;
else if (fracsize == 1 && frac[0] == 0)
/* Rest of the number is zero. */
more_bits = false;
else if (scalesize == 0)
{
wchar_t *wtp = wcp;
/* Here we have to see whether all limbs are zero since no
normalization happened. */
size_t lcnt = fracsize;
while (lcnt >= 1 && frac[lcnt - 1] == 0)
--lcnt;
more_bits = lcnt > 0;
}
else
more_bits = true;
if (digit == L_('5')
&& ((*(wcp - 1) != decimalwc && (*(wcp - 1) & 1) == 0)
|| ((*(wcp - 1) == decimalwc && (*(wcp - 2) & 1) == 0))))
{
/* This is the critical case. */
if (fracsize == 1 && frac[0] == 0)
/* Rest of the number is zero -> round to even.
(IEEE 754-1985 4.1 says this is the default rounding.) */
goto do_expo;
else if (scalesize == 0)
{
/* Here we have to see whether all limbs are zero since no
normalization happened. */
size_t lcnt = fracsize;
while (lcnt >= 1 && frac[lcnt - 1] == 0)
--lcnt;
if (lcnt == 0)
/* Rest of the number is zero -> round to even.
(IEEE 754-1985 4.1 says this is the default rounding.) */
goto do_expo;
}
}
#ifdef HAVE_FENV_H
int rounding_mode = get_rounding_mode ();
if (round_away (is_neg, (last_digit - L_('0')) & 1, next_digit >= L_('5'),
more_bits, rounding_mode))
{
wchar_t *wtp = wcp;
if (fracdig_no > 0)
{
......@@ -1055,8 +1059,8 @@ __quadmath_printf_fp (struct __quadmath_printf_file *fp,
}
}
}
#endif
do_expo:
/* Now remove unnecessary '0' at the end of the string. */
while (fracdig_no > fracdig_min + added_zeros && *(wcp - 1) == L_('0'))
{
......@@ -1249,15 +1253,19 @@ guess_grouping (unsigned int intdig_max, const char *grouping)
++groups;
intdig_max -= *grouping++;
if (*grouping == 0)
if (*grouping == CHAR_MAX
#if CHAR_MIN < 0
|| *grouping < 0
#endif
)
/* No more grouping should be done. */
break;
else if (*grouping == 0)
{
/* Same grouping repeats. */
groups += (intdig_max - 1) / grouping[-1];
break;
}
else if (*grouping == CHAR_MAX || *grouping <= 0)
/* No more grouping should be done. */
break;
}
return groups;
......@@ -1289,12 +1297,16 @@ group_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no,
while (--len > 0);
*p-- = thousands_sep;
if (*grouping == 0)
/* Same grouping repeats. */
--grouping;
else if (*grouping == CHAR_MAX || *grouping <= 0)
if (*grouping == CHAR_MAX
#if CHAR_MIN < 0
|| *grouping < 0
#endif
)
/* No more grouping should be done. */
break;
else if (*grouping == 0)
/* Same grouping repeats. */
--grouping;
} while (intdig_no > (unsigned int) *grouping);
/* Copy the remaining ungrouped digits. */
......
/* Print floating point number in hexadecimal notation according to ISO C99.
Copyright (C) 1997-2002,2004,2006 Free Software Foundation, Inc.
Copyright (C) 1997-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
......@@ -14,17 +14,18 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
#include <config.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define NDEBUG
#include <assert.h>
#include "quadmath-rounding-mode.h"
#include "quadmath-printf.h"
#include "_itoa.h"
#include "_itowa.h"
......@@ -116,6 +117,8 @@ __quadmath_printf_fphex (struct __quadmath_printf_file *fp,
/* Nonzero if this is output on a wide character stream. */
int wide = info->wide;
bool do_round_away;
/* Figure out the decimal point character. */
#ifdef USE_NL_LANGINFO
if (info->extra == 0)
......@@ -274,8 +277,8 @@ __quadmath_printf_fphex (struct __quadmath_printf_file *fp,
/* Fill with zeroes. */
while (numstr > numbuf + (sizeof numbuf - 112 / 4))
{
*--numstr = '0';
*--wnumstr = L_('0');
*--numstr = '0';
}
leading = fpnum.ieee.exponent == 0 ? '0' : '1';
......@@ -316,21 +319,35 @@ __quadmath_printf_fphex (struct __quadmath_printf_file *fp,
--numend;
}
do_round_away = false;
if (precision != -1 && precision < numend - numstr)
{
char last_digit = precision > 0 ? numstr[precision - 1] : leading;
char next_digit = numstr[precision];
int last_digit_value = (last_digit >= 'A' && last_digit <= 'F'
? last_digit - 'A' + 10
: (last_digit >= 'a' && last_digit <= 'f'
? last_digit - 'a' + 10
: last_digit - '0'));
int next_digit_value = (next_digit >= 'A' && next_digit <= 'F'
? next_digit - 'A' + 10
: (next_digit >= 'a' && next_digit <= 'f'
? next_digit - 'a' + 10
: next_digit - '0'));
bool more_bits = ((next_digit_value & 7) != 0
|| precision + 1 < numend - numstr);
#ifdef HAVE_FENV_H
int rounding_mode = get_rounding_mode ();
do_round_away = round_away (negative, last_digit_value & 1,
next_digit_value >= 8, more_bits,
rounding_mode);
#endif
}
if (precision == -1)
precision = numend - numstr;
else if (precision < numend - numstr
&& (numstr[precision] > '8'
|| (('A' < '0' || 'a' < '0')
&& numstr[precision] < '0')
|| (numstr[precision] == '8'
&& (precision + 1 < numend - numstr
/* Round to even. */
|| (precision > 0
&& ((numstr[precision - 1] & 1)
^ (isdigit (numstr[precision - 1]) == 0)))
|| (precision == 0
&& ((leading & 1)
^ (isdigit (leading) == 0)))))))
else if (do_round_away)
{
/* Round up. */
int cnt = precision;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment