diff options
author | Tobias Burnus <burnus@net-b.de> | 2013-07-21 13:54:27 +0200 |
---|---|---|
committer | Tobias Burnus <burnus@gcc.gnu.org> | 2013-07-21 13:54:27 +0200 |
commit | 82a4f54cc5ff37df751528d1a30e9b573d2496ee (patch) | |
tree | eb32a590b892e8caf501e4b6d7803bb72a37b2fc /libgfortran/io | |
parent | 3b833dcda53c814695ce250f91ae769d20962d75 (diff) | |
download | gcc-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.h | 10 | ||||
-rw-r--r-- | libgfortran/io/read.c | 20 |
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, |