[PATCH/gfortran] Fix rounding in constant folding
Steve Kargl
sgk@troutmask.apl.washington.edu
Sat Apr 9 16:23:00 GMT 2005
The attached patch fixes a rounding problem in
nint, anint, and dnint during gfortran's constant
folding. This patch does not address the problem
noticed by Geert Bosch gfortran's build_round_expr.
Bubblestrapped and regression tested on i386-*-freebsd
and amd64-*-freebsd.
Ok to commit to mainline and 4.0?
2005-04-09 Steven G. Kargl <kargls@comcast.net>
* simplify.c (gfc_simplify_anint): Use mpfr_round()
(gfc_simplify_dnint): ditto.
(gfc_simplify_nint): ditto.
2005-04-09 Steven G. Kargl <kargls@comcast.net>
* gfortran.dg/nint_1.f90: New test.
* gfortran.dg/anint_1.f90: ditto.
--
Steve
-------------- next part --------------
Index: simplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fortran/simplify.c,v
retrieving revision 1.21
diff -c -p -r1.21 simplify.c
*** simplify.c 7 Apr 2005 18:26:37 -0000 1.21
--- simplify.c 9 Apr 2005 15:25:58 -0000
*************** gfc_simplify_dint (gfc_expr * e)
*** 409,417 ****
gfc_expr *
gfc_simplify_anint (gfc_expr * e, gfc_expr * k)
{
! gfc_expr *rtrunc, *result;
! int kind, cmp;
! mpfr_t half;
kind = get_kind (BT_REAL, k, "ANINT", e->ts.kind);
if (kind == -1)
--- 409,416 ----
gfc_expr *
gfc_simplify_anint (gfc_expr * e, gfc_expr * k)
{
! gfc_expr *result;
! int kind;
kind = get_kind (BT_REAL, k, "ANINT", e->ts.kind);
if (kind == -1)
*************** gfc_simplify_anint (gfc_expr * e, gfc_ex
*** 422,450 ****
result = gfc_constant_result (e->ts.type, kind, &e->where);
! rtrunc = gfc_copy_expr (e);
!
! cmp = mpfr_cmp_ui (e->value.real, 0);
!
! gfc_set_model_kind (kind);
! mpfr_init (half);
! mpfr_set_str (half, "0.5", 10, GFC_RND_MODE);
!
! if (cmp > 0)
! {
! mpfr_add (rtrunc->value.real, e->value.real, half, GFC_RND_MODE);
! mpfr_trunc (result->value.real, rtrunc->value.real);
! }
! else if (cmp < 0)
! {
! mpfr_sub (rtrunc->value.real, e->value.real, half, GFC_RND_MODE);
! mpfr_trunc (result->value.real, rtrunc->value.real);
! }
! else
! mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
!
! gfc_free_expr (rtrunc);
! mpfr_clear (half);
return range_check (result, "ANINT");
}
--- 421,427 ----
result = gfc_constant_result (e->ts.type, kind, &e->where);
! mpfr_round (result->value.real, e->value.real);
return range_check (result, "ANINT");
}
*************** gfc_simplify_anint (gfc_expr * e, gfc_ex
*** 453,491 ****
gfc_expr *
gfc_simplify_dnint (gfc_expr * e)
{
! gfc_expr *rtrunc, *result;
! int cmp;
! mpfr_t half;
if (e->expr_type != EXPR_CONSTANT)
return NULL;
! result =
! gfc_constant_result (BT_REAL, gfc_default_double_kind, &e->where);
!
! rtrunc = gfc_copy_expr (e);
! cmp = mpfr_cmp_ui (e->value.real, 0);
!
! gfc_set_model_kind (gfc_default_double_kind);
! mpfr_init (half);
! mpfr_set_str (half, "0.5", 10, GFC_RND_MODE);
!
! if (cmp > 0)
! {
! mpfr_add (rtrunc->value.real, e->value.real, half, GFC_RND_MODE);
! mpfr_trunc (result->value.real, rtrunc->value.real);
! }
! else if (cmp < 0)
! {
! mpfr_sub (rtrunc->value.real, e->value.real, half, GFC_RND_MODE);
! mpfr_trunc (result->value.real, rtrunc->value.real);
! }
! else
! mpfr_set_ui (result->value.real, 0, GFC_RND_MODE);
!
! gfc_free_expr (rtrunc);
! mpfr_clear (half);
return range_check (result, "DNINT");
}
--- 430,443 ----
gfc_expr *
gfc_simplify_dnint (gfc_expr * e)
{
! gfc_expr *result;
if (e->expr_type != EXPR_CONSTANT)
return NULL;
! result = gfc_constant_result (BT_REAL, gfc_default_double_kind, &e->where);
! mpfr_round (result->value.real, e->value.real);
return range_check (result, "DNINT");
}
*************** gfc_simplify_nearest (gfc_expr * x, gfc_
*** 2378,2386 ****
static gfc_expr *
simplify_nint (const char *name, gfc_expr * e, gfc_expr * k)
{
! gfc_expr *rtrunc, *itrunc, *result;
! int kind, cmp;
! mpfr_t half;
kind = get_kind (BT_INTEGER, k, name, gfc_default_integer_kind);
if (kind == -1)
--- 2330,2337 ----
static gfc_expr *
simplify_nint (const char *name, gfc_expr * e, gfc_expr * k)
{
! gfc_expr *itrunc, *result;
! int kind;
kind = get_kind (BT_INTEGER, k, name, gfc_default_integer_kind);
if (kind == -1)
*************** simplify_nint (const char *name, gfc_exp
*** 2391,2423 ****
result = gfc_constant_result (BT_INTEGER, kind, &e->where);
- rtrunc = gfc_copy_expr (e);
itrunc = gfc_copy_expr (e);
! cmp = mpfr_cmp_ui (e->value.real, 0);
!
! gfc_set_model (e->value.real);
! mpfr_init (half);
! mpfr_set_str (half, "0.5", 10, GFC_RND_MODE);
!
! if (cmp > 0)
! {
! mpfr_add (rtrunc->value.real, e->value.real, half, GFC_RND_MODE);
! mpfr_trunc (itrunc->value.real, rtrunc->value.real);
! }
! else if (cmp < 0)
! {
! mpfr_sub (rtrunc->value.real, e->value.real, half, GFC_RND_MODE);
! mpfr_trunc (itrunc->value.real, rtrunc->value.real);
! }
! else
! mpfr_set_ui (itrunc->value.real, 0, GFC_RND_MODE);
gfc_mpfr_to_mpz (result->value.integer, itrunc->value.real);
gfc_free_expr (itrunc);
- gfc_free_expr (rtrunc);
- mpfr_clear (half);
return range_check (result, name);
}
--- 2342,2354 ----
result = gfc_constant_result (BT_INTEGER, kind, &e->where);
itrunc = gfc_copy_expr (e);
! mpfr_round(itrunc->value.real, e->value.real);
gfc_mpfr_to_mpz (result->value.integer, itrunc->value.real);
gfc_free_expr (itrunc);
return range_check (result, name);
}
-------------- next part --------------
program nint_1
if (nint(8388609.0) /= 8388609) call abort
if (nint(0.49999997) /= 0) call abort
end program nint_1
-------------- next part --------------
program anint_1
print *,anint(8388609.0)
print *,anint(0.49999997)
if (int(anint(8388609.0)) /= 8388609) call abort
if (int(anint(0.49999997)) /= 0) call abort
end program anint_1
More information about the Gcc-patches
mailing list