aboutsummaryrefslogtreecommitdiff
path: root/libgfortran/io
diff options
context:
space:
mode:
authorTobias Burnus <burnus@net-b.de>2013-07-21 13:54:27 +0200
committerTobias Burnus <burnus@gcc.gnu.org>2013-07-21 13:54:27 +0200
commit82a4f54cc5ff37df751528d1a30e9b573d2496ee (patch)
treeeb32a590b892e8caf501e4b6d7803bb72a37b2fc /libgfortran/io
parent3b833dcda53c814695ce250f91ae769d20962d75 (diff)
downloadgcc-82a4f54cc5ff37df751528d1a30e9b573d2496ee.zip
gcc-82a4f54cc5ff37df751528d1a30e9b573d2496ee.tar.gz
gcc-82a4f54cc5ff37df751528d1a30e9b573d2496ee.tar.bz2
re PR libfortran/35862 ([F2003] Implement new rounding modes for run time)
2013-07-21 Tobias Burnus <burnus@net-b.de> PR fortran/35862 * libgfortran.h (GFC_FPE_DOWNWARD, GFC_FPE_TONEAREST, GFC_FPE_TOWARDZERO, GFC_FPE_UPWARD): New defines. 2013-07-21 Tobias Burnus <burnus@net-b.de> PR fortran/35862 * libgfortran.h (set_fpu_rounding_mode, get_fpu_rounding_mode): New prototypes. * config/fpu-387.h (set_fpu_rounding_mode, get_fpu_rounding_mode): New functions. * config/fpu-aix.h (set_fpu_rounding_mode, get_fpu_rounding_mode): Ditto. * config/fpu-generic.h (set_fpu_rounding_mode, get_fpu_rounding_mode): Ditto. * config/fpu-glibc.h (set_fpu_rounding_mode, get_fpu_rounding_mode): Ditto. * config/fpu-sysv.h (set_fpu_rounding_mode, get_fpu_rounding_mode): Ditto. * configure.ac: Check for fp_rnd and fp_rnd_t. * io/io.h (enum unit_round): Use GFC_FPE_* for the value. * io/read.c (convert_real): Set FP ronding mode. * Makefile.in: Regenerate. * aclocal.m4: Regenerate. * config.h.in: Regenerate. * configure: Regenerate. 2013-07-21 Tobias Burnus <burnus@net-b.de> PR fortran/35862 * gfortran.dg/round_4.f90: New. Co-Authored-By: Uros Bizjak <ubizjak@gmail.com> From-SVN: r201093
Diffstat (limited to 'libgfortran/io')
-rw-r--r--libgfortran/io/io.h10
-rw-r--r--libgfortran/io/read.c20
2 files changed, 28 insertions, 2 deletions
diff --git a/libgfortran/io/io.h b/libgfortran/io/io.h
index 8ea9326..1dcf72e 100644
--- a/libgfortran/io/io.h
+++ b/libgfortran/io/io.h
@@ -186,8 +186,14 @@ typedef enum
unit_encoding;
typedef enum
-{ ROUND_UP, ROUND_DOWN, ROUND_ZERO, ROUND_NEAREST, ROUND_COMPATIBLE,
- ROUND_PROCDEFINED, ROUND_UNSPECIFIED }
+{ ROUND_UP = GFC_FPE_UPWARD,
+ ROUND_DOWN = GFC_FPE_DOWNWARD,
+ ROUND_ZERO = GFC_FPE_TOWARDZERO,
+ ROUND_NEAREST = GFC_FPE_TONEAREST,
+ ROUND_COMPATIBLE = 10, /* round away from zero. */
+ ROUND_PROCDEFINED, /* Here as ROUND_NEAREST. */
+ ROUND_UNSPECIFIED /* Should never occur. */
+}
unit_round;
/* NOTE: unit_sign must correspond with the sign_status enumerator in
diff --git a/libgfortran/io/read.c b/libgfortran/io/read.c
index d7d5c41..e35b1a0 100644
--- a/libgfortran/io/read.c
+++ b/libgfortran/io/read.c
@@ -129,6 +129,24 @@ int
convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
{
char *endptr = NULL;
+ int round_mode, old_round_mode;
+
+ switch (dtp->u.p.current_unit->round_status)
+ {
+ case ROUND_COMPATIBLE:
+ /* FIXME: As NEAREST but round away from zero for a tie. */
+ case ROUND_UNSPECIFIED:
+ /* Should not occur. */
+ case ROUND_PROCDEFINED:
+ round_mode = ROUND_NEAREST;
+ break;
+ default:
+ round_mode = dtp->u.p.current_unit->round_status;
+ break;
+ }
+
+ old_round_mode = get_fpu_rounding_mode();
+ set_fpu_rounding_mode (round_mode);
switch (length)
{
@@ -167,6 +185,8 @@ convert_real (st_parameter_dt *dtp, void *dest, const char *buffer, int length)
internal_error (&dtp->common, "Unsupported real kind during IO");
}
+ set_fpu_rounding_mode (old_round_mode);
+
if (buffer == endptr)
{
generate_error (&dtp->common, LIBERROR_READ_VALUE,