diff options
author | Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2007-08-03 21:26:10 +0000 |
---|---|---|
committer | François-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2007-08-03 21:26:10 +0000 |
commit | 94f548c244426f45bab1ae19d3359aa2b651dce0 (patch) | |
tree | b3c3360111641d52b502bddd36c0a4ce24d565cf | |
parent | 8db6f5454c392b098080e297de645be106d621af (diff) | |
download | gcc-94f548c244426f45bab1ae19d3359aa2b651dce0.zip gcc-94f548c244426f45bab1ae19d3359aa2b651dce0.tar.gz gcc-94f548c244426f45bab1ae19d3359aa2b651dce0.tar.bz2 |
re PR fortran/31202 (Incorrect rounding generated for NINT)
PR fortran/31202
* f95-lang.c (gfc_init_builtin_functions): Defin builtins for
lround{f,,l} and llround{f,,l}.
* trans-intrinsic.c (build_fix_expr): Generate calls to the
{l,}round{f,,l} functions.
* intrinsics/c99_functions.c (roundl,lroundf,lround,lroundl,
llroundf,llround,llroundl): New functions.
* c99_protos.h (roundl,lroundf,lround,lroundl,llroundf,llround,
llroundl): New prototypes.
* configure.ac: Check for lroundf, lround, lroundl, llroundf,
llround and llroundl.
* configure: Regenerate.
* Makefile.in: Regenerate.
* config.h.in: Regenerate.
* gfortran.dg/nint_2.f90: New test.
From-SVN: r127185
-rw-r--r-- | gcc/fortran/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fortran/f95-lang.c | 27 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 70 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/nint_2.f90 | 51 | ||||
-rw-r--r-- | libgfortran/ChangeLog | 13 | ||||
-rw-r--r-- | libgfortran/Makefile.in | 15 | ||||
-rw-r--r-- | libgfortran/c99_protos.h | 37 | ||||
-rw-r--r-- | libgfortran/config.h.in | 18 | ||||
-rwxr-xr-x | libgfortran/configure | 462 | ||||
-rw-r--r-- | libgfortran/configure.ac | 6 | ||||
-rw-r--r-- | libgfortran/intrinsics/c99_functions.c | 87 |
12 files changed, 768 insertions, 31 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index c8e4a3c..5d1695b 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,11 @@ +2007-08-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31202 + * f95-lang.c (gfc_init_builtin_functions): Defin builtins for + lround{f,,l} and llround{f,,l}. + * trans-intrinsic.c (build_fix_expr): Generate calls to the + {l,}round{f,,l} functions. + 2007-08-01 Thomas Koenig <tkoenig@gcc.gnu.org> PR libfortran/32954 diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index 0cecac0..425f4d3 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -852,7 +852,7 @@ gfc_init_builtin_functions (void) tree func_double_doublep_doublep; tree func_longdouble_longdoublep_longdoublep; tree ftype, ptype; - tree tmp; + tree tmp, type; tree builtin_types[(int) BT_LAST + 1]; build_builtin_fntypes (mfunc_float, float_type_node); @@ -942,6 +942,31 @@ gfc_init_builtin_functions (void) gfc_define_builtin ("__builtin_fmodf", mfunc_float[1], BUILT_IN_FMODF, "fmodf", true); + /* lround{f,,l} and llround{f,,l} */ + type = tree_cons (NULL_TREE, float_type_node, void_list_node); + tmp = build_function_type (long_integer_type_node, type); + gfc_define_builtin ("__builtin_lroundf", tmp, BUILT_IN_LROUNDF, + "lroundf", true); + tmp = build_function_type (long_long_integer_type_node, type); + gfc_define_builtin ("__builtin_llroundf", tmp, BUILT_IN_LLROUNDF, + "llroundf", true); + + type = tree_cons (NULL_TREE, double_type_node, void_list_node); + tmp = build_function_type (long_integer_type_node, type); + gfc_define_builtin ("__builtin_lround", tmp, BUILT_IN_LROUND, + "lround", true); + tmp = build_function_type (long_long_integer_type_node, type); + gfc_define_builtin ("__builtin_llround", tmp, BUILT_IN_LLROUND, + "llround", true); + + type = tree_cons (NULL_TREE, long_double_type_node, void_list_node); + tmp = build_function_type (long_integer_type_node, type); + gfc_define_builtin ("__builtin_lroundl", tmp, BUILT_IN_LROUNDL, + "lroundl", true); + tmp = build_function_type (long_long_integer_type_node, type); + gfc_define_builtin ("__builtin_llroundl", tmp, BUILT_IN_LLROUNDL, + "llroundl", true); + /* These are used to implement the ** operator. */ gfc_define_builtin ("__builtin_powl", mfunc_longdouble[1], BUILT_IN_POWL, "powl", true); diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 39deadb..dc67240 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -25,6 +25,7 @@ along with GCC; see the file COPYING3. If not see #include "config.h" #include "system.h" #include "coretypes.h" +#include "tm.h" #include "tree.h" #include "ggc.h" #include "toplev.h" @@ -308,34 +309,57 @@ build_fixbound_expr (stmtblock_t * pblock, tree arg, tree type, int up) } -/* This is needed because the gcc backend only implements FIX_TRUNC_EXPR - NINT(x) = INT(x + ((x > 0) ? 0.5 : -0.5)). */ +/* Round to nearest integer, away from zero. */ static tree -build_round_expr (stmtblock_t * pblock, tree arg, tree type) +build_round_expr (tree arg, tree restype) { tree tmp; - tree cond; - tree neg; - tree pos; tree argtype; - REAL_VALUE_TYPE r; + tree fn; + bool longlong, convert; + int argprec, resprec; argtype = TREE_TYPE (arg); - arg = gfc_evaluate_now (arg, pblock); + argprec = TYPE_PRECISION (argtype); + resprec = TYPE_PRECISION (restype); - real_from_string (&r, "0.5"); - pos = build_real (argtype, r); - - real_from_string (&r, "-0.5"); - neg = build_real (argtype, r); + /* Depending on the type of the result, choose the long int intrinsic + (lround family) or long long intrinsic (llround). We might also + need to convert the result afterwards. */ + if (resprec <= LONG_TYPE_SIZE) + { + longlong = false; + if (resprec != LONG_TYPE_SIZE) + convert = true; + else + convert = false; + } + else if (resprec <= LONG_LONG_TYPE_SIZE) + { + longlong = true; + if (resprec != LONG_LONG_TYPE_SIZE) + convert = true; + else + convert = false; + } + else + gcc_unreachable (); - tmp = gfc_build_const (argtype, integer_zero_node); - cond = fold_build2 (GT_EXPR, boolean_type_node, arg, tmp); + /* Now, depending on the argument type, we choose between intrinsics. */ + if (argprec == TYPE_PRECISION (float_type_node)) + fn = built_in_decls[longlong ? BUILT_IN_LLROUNDF : BUILT_IN_LROUNDF]; + else if (argprec == TYPE_PRECISION (double_type_node)) + fn = built_in_decls[longlong ? BUILT_IN_LLROUND : BUILT_IN_LROUND]; + else if (argprec == TYPE_PRECISION (long_double_type_node)) + fn = built_in_decls[longlong ? BUILT_IN_LLROUNDL : BUILT_IN_LROUNDL]; + else + gcc_unreachable (); - tmp = fold_build3 (COND_EXPR, argtype, cond, pos, neg); - tmp = fold_build2 (PLUS_EXPR, argtype, arg, tmp); - return fold_build1 (FIX_TRUNC_EXPR, type, tmp); + tmp = build_call_expr (fn, 1, arg); + if (convert) + tmp = fold_convert (restype, tmp); + return tmp; } @@ -358,11 +382,15 @@ build_fix_expr (stmtblock_t * pblock, tree arg, tree type, break; case RND_ROUND: - return build_round_expr (pblock, arg, type); + return build_round_expr (arg, type); + break; - default: - gcc_assert (op == RND_TRUNC); + case RND_TRUNC: return build1 (FIX_TRUNC_EXPR, type, arg); + break; + + default: + gcc_unreachable (); } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 892eb9c..e548278 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-08-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31202 + * gfortran.dg/nint_2.f90: New test. + 2007-08-03 Nathan Froyd <froydnj@codesourcery.com> * gcc.dg/tree-ssa/loop-1.c: Skip on powerpc targets if -mlongcall. diff --git a/gcc/testsuite/gfortran.dg/nint_2.f90 b/gcc/testsuite/gfortran.dg/nint_2.f90 new file mode 100644 index 0000000..b993cb4 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nint_2.f90 @@ -0,0 +1,51 @@ +! Test that NINT gives right results even in corner cases +! +! PR 31202 +! http://gcc.gnu.org/ml/fortran/2005-04/msg00139.html +! +! { dg-do run } + real(kind=8) :: a + integer(kind=8) :: i1, i2 + real :: b + integer :: j1, j2 + + a = nearest(0.5_8,-1.0_8) + i2 = nint(nearest(0.5_8,-1.0_8)) + i1 = nint(a) + if (i1 /= 0 .or. i2 /= 0) call abort + + a = 0.5_8 + i2 = nint(0.5_8) + i1 = nint(a) + if (i1 /= 1 .or. i2 /= 1) call abort + + a = nearest(0.5_8,1.0_8) + i2 = nint(nearest(0.5_8,1.0_8)) + i1 = nint(a) + if (i1 /= 1 .or. i2 /= 1) call abort + + b = nearest(0.5,-1.0) + j2 = nint(nearest(0.5,-1.0)) + j1 = nint(b) + if (j1 /= 0 .or. j2 /= 0) call abort + + b = 0.5 + j2 = nint(0.5) + j1 = nint(b) + if (j1 /= 1 .or. j2 /= 1) call abort + + b = nearest(0.5,1.0) + j2 = nint(nearest(0.5,1.0)) + j1 = nint(b) + if (j1 /= 1 .or. j2 /= 1) call abort + + a = 4503599627370497.0_8 + i1 = nint(a,kind=8) + i2 = nint(4503599627370497.0_8,kind=8) + if (i1 /= i2 .or. i1 /= 4503599627370497_8) call abort + + a = -4503599627370497.0_8 + i1 = nint(a,kind=8) + i2 = nint(-4503599627370497.0_8,kind=8) + if (i1 /= i2 .or. i1 /= -4503599627370497_8) call abort + end diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog index 7642d96..eb03d0a 100644 --- a/libgfortran/ChangeLog +++ b/libgfortran/ChangeLog @@ -1,3 +1,16 @@ +2007-08-03 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> + + PR fortran/31202 + * intrinsics/c99_functions.c (roundl,lroundf,lround,lroundl, + llroundf,llround,llroundl): New functions. + * c99_protos.h (roundl,lroundf,lround,lroundl,llroundf,llround, + llroundl): New prototypes. + * configure.ac: Check for lroundf, lround, lroundl, llroundf, + llround and llroundl. + * configure: Regenerate. + * Makefile.in: Regenerate. + * config.h.in: Regenerate. + 2007-07-30 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> * libgfortran.h: Include <stdarg.h>. diff --git a/libgfortran/Makefile.in b/libgfortran/Makefile.in index 90715d4..9d78ad2 100644 --- a/libgfortran/Makefile.in +++ b/libgfortran/Makefile.in @@ -50,8 +50,8 @@ am__aclocal_m4_deps = $(top_srcdir)/../config/depstand.m4 \ $(top_srcdir)/../config/multi.m4 \ $(top_srcdir)/../config/stdint.m4 \ $(top_srcdir)/../ltoptions.m4 $(top_srcdir)/../ltsugar.m4 \ - $(top_srcdir)/../ltversion.m4 $(top_srcdir)/acinclude.m4 \ - $(top_srcdir)/../config/acx.m4 \ + $(top_srcdir)/../ltversion.m4 $(top_srcdir)/../lt~obsolete.m4 \ + $(top_srcdir)/acinclude.m4 $(top_srcdir)/../config/acx.m4 \ $(top_srcdir)/../config/no-executables.m4 \ $(top_srcdir)/../libtool.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -343,9 +343,13 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ STRIP = @STRIP@ VERSION = @VERSION@ +ac_ct_AR = @ac_ct_AR@ +ac_ct_AS = @ac_ct_AS@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ ac_ct_FC = @ac_ct_FC@ +ac_ct_RANLIB = @ac_ct_RANLIB@ +ac_ct_STRIP = @ac_ct_STRIP@ am__fastdepCC_FALSE = @am__fastdepCC_FALSE@ am__fastdepCC_TRUE = @am__fastdepCC_TRUE@ am__include = @am__include@ @@ -362,9 +366,6 @@ build_os = @build_os@ build_subdir = @build_subdir@ build_vendor = @build_vendor@ datadir = @datadir@ -datarootdir = @datarootdir@ -docdir = @docdir@ -dvidir = @dvidir@ enable_shared = @enable_shared@ enable_static = @enable_static@ exec_prefix = @exec_prefix@ @@ -375,23 +376,19 @@ host_cpu = @host_cpu@ host_os = @host_os@ host_subdir = @host_subdir@ host_vendor = @host_vendor@ -htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ -localedir = @localedir@ localstatedir = @localstatedir@ lt_ECHO = @lt_ECHO@ mandir = @mandir@ mkdir_p = @mkdir_p@ multi_basedir = @multi_basedir@ oldincludedir = @oldincludedir@ -pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ -psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ sysconfdir = @sysconfdir@ diff --git a/libgfortran/c99_protos.h b/libgfortran/c99_protos.h index 369299d..c4738db 100644 --- a/libgfortran/c99_protos.h +++ b/libgfortran/c99_protos.h @@ -200,6 +200,43 @@ extern double round(double); extern float roundf(float); #endif +#if !defined(HAVE_ROUNDL) && defined(HAVE_CEILL) +#define HAVE_ROUNDL 1 +extern long double roundl(long double); +#endif + + + +#if !defined(HAVE_LROUNDF) && defined(HAVE_ROUNDF) +#define HAVE_LROUNDF 1 +long int lroundf (float); +#endif + +#if !defined(HAVE_LROUND) && defined(HAVE_ROUND) +#define HAVE_LROUND 1 +long int lround (double); +#endif + +#if !defined(HAVE_LROUNDL) && defined(HAVE_ROUNDL) +#define HAVE_LROUNDL 1 +long int lroundl (long double); +#endif + +#if !defined(HAVE_LLROUNDF) && defined(HAVE_ROUNDF) +#define HAVE_LLROUNDF 1 +long long int llroundf (float); +#endif + +#if !defined(HAVE_LLROUND) && defined(HAVE_ROUND) +#define HAVE_LLROUND 1 +long long int llround (double); +#endif + +#if !defined(HAVE_LLROUNDL) && defined(HAVE_ROUNDL) +#define HAVE_LLROUNDL 1 +long long int llroundl (long double); +#endif + /* Wrappers for systems without the various C99 single precision Bessel functions. */ diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in index 0779149..4099c39 100644 --- a/libgfortran/config.h.in +++ b/libgfortran/config.h.in @@ -480,6 +480,15 @@ /* Define to 1 if you have the `link' function. */ #undef HAVE_LINK +/* libm includes llround */ +#undef HAVE_LLROUND + +/* libm includes llroundf */ +#undef HAVE_LLROUNDF + +/* libm includes llroundl */ +#undef HAVE_LLROUNDL + /* libm includes log */ #undef HAVE_LOG @@ -498,6 +507,15 @@ /* libm includes logl */ #undef HAVE_LOGL +/* libm includes lround */ +#undef HAVE_LROUND + +/* libm includes lroundf */ +#undef HAVE_LROUNDF + +/* libm includes lroundl */ +#undef HAVE_LROUNDL + /* Define to 1 if you have the `lstat' function. */ #undef HAVE_LSTAT diff --git a/libgfortran/configure b/libgfortran/configure index 7e568a3..b9a0cf5 100755 --- a/libgfortran/configure +++ b/libgfortran/configure @@ -26314,6 +26314,468 @@ _ACEOF fi +echo "$as_me:$LINENO: checking for lroundf in -lm" >&5 +echo $ECHO_N "checking for lroundf in -lm... $ECHO_C" >&6 +if test "${ac_cv_lib_m_lroundf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5 +echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;} + { (exit 1); exit 1; }; } +fi +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lroundf (); +int +main () +{ +lroundf (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_lroundf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_m_lroundf=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_m_lroundf" >&5 +echo "${ECHO_T}$ac_cv_lib_m_lroundf" >&6 +if test $ac_cv_lib_m_lroundf = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LROUNDF 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for lround in -lm" >&5 +echo $ECHO_N "checking for lround in -lm... $ECHO_C" >&6 +if test "${ac_cv_lib_m_lround+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5 +echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;} + { (exit 1); exit 1; }; } +fi +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lround (); +int +main () +{ +lround (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_lround=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_m_lround=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_m_lround" >&5 +echo "${ECHO_T}$ac_cv_lib_m_lround" >&6 +if test $ac_cv_lib_m_lround = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LROUND 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for lroundl in -lm" >&5 +echo $ECHO_N "checking for lroundl in -lm... $ECHO_C" >&6 +if test "${ac_cv_lib_m_lroundl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5 +echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;} + { (exit 1); exit 1; }; } +fi +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char lroundl (); +int +main () +{ +lroundl (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_lroundl=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_m_lroundl=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_m_lroundl" >&5 +echo "${ECHO_T}$ac_cv_lib_m_lroundl" >&6 +if test $ac_cv_lib_m_lroundl = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LROUNDL 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for llroundf in -lm" >&5 +echo $ECHO_N "checking for llroundf in -lm... $ECHO_C" >&6 +if test "${ac_cv_lib_m_llroundf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5 +echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;} + { (exit 1); exit 1; }; } +fi +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char llroundf (); +int +main () +{ +llroundf (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_llroundf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_m_llroundf=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_m_llroundf" >&5 +echo "${ECHO_T}$ac_cv_lib_m_llroundf" >&6 +if test $ac_cv_lib_m_llroundf = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LLROUNDF 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for llround in -lm" >&5 +echo $ECHO_N "checking for llround in -lm... $ECHO_C" >&6 +if test "${ac_cv_lib_m_llround+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5 +echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;} + { (exit 1); exit 1; }; } +fi +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char llround (); +int +main () +{ +llround (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_llround=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_m_llround=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_m_llround" >&5 +echo "${ECHO_T}$ac_cv_lib_m_llround" >&6 +if test $ac_cv_lib_m_llround = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LLROUND 1 +_ACEOF + +fi + +echo "$as_me:$LINENO: checking for llroundl in -lm" >&5 +echo $ECHO_N "checking for llroundl in -lm... $ECHO_C" >&6 +if test "${ac_cv_lib_m_llroundl+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +if test x$gcc_no_link = xyes; then + { { echo "$as_me:$LINENO: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&5 +echo "$as_me: error: Link tests are not allowed after GCC_NO_EXECUTABLES." >&2;} + { (exit 1); exit 1; }; } +fi +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char llroundl (); +int +main () +{ +llroundl (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_m_llroundl=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_m_llroundl=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_m_llroundl" >&5 +echo "${ECHO_T}$ac_cv_lib_m_llroundl" >&6 +if test $ac_cv_lib_m_llroundl = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LLROUNDL 1 +_ACEOF + +fi + echo "$as_me:$LINENO: checking for scalbnf in -lm" >&5 echo $ECHO_N "checking for scalbnf in -lm... $ECHO_C" >&6 if test "${ac_cv_lib_m_scalbnf+set}" = set; then diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac index 0c85326..8709e16 100644 --- a/libgfortran/configure.ac +++ b/libgfortran/configure.ac @@ -301,6 +301,12 @@ AC_CHECK_LIB([m],[cpowl],[AC_DEFINE([HAVE_CPOWL],[1],[libm includes cpowl])]) AC_CHECK_LIB([m],[roundf],[AC_DEFINE([HAVE_ROUNDF],[1],[libm includes roundf])]) AC_CHECK_LIB([m],[round],[AC_DEFINE([HAVE_ROUND],[1],[libm includes round])]) AC_CHECK_LIB([m],[roundl],[AC_DEFINE([HAVE_ROUNDL],[1],[libm includes roundl])]) +AC_CHECK_LIB([m],[lroundf],[AC_DEFINE([HAVE_LROUNDF],[1],[libm includes lroundf])]) +AC_CHECK_LIB([m],[lround],[AC_DEFINE([HAVE_LROUND],[1],[libm includes lround])]) +AC_CHECK_LIB([m],[lroundl],[AC_DEFINE([HAVE_LROUNDL],[1],[libm includes lroundl])]) +AC_CHECK_LIB([m],[llroundf],[AC_DEFINE([HAVE_LLROUNDF],[1],[libm includes llroundf])]) +AC_CHECK_LIB([m],[llround],[AC_DEFINE([HAVE_LLROUND],[1],[libm includes llround])]) +AC_CHECK_LIB([m],[llroundl],[AC_DEFINE([HAVE_LLROUNDL],[1],[libm includes llroundl])]) AC_CHECK_LIB([m],[scalbnf],[AC_DEFINE([HAVE_SCALBNF],[1],[libm includes scalbnf])]) AC_CHECK_LIB([m],[scalbn],[AC_DEFINE([HAVE_SCALBN],[1],[libm includes scalbn])]) AC_CHECK_LIB([m],[scalbnl],[AC_DEFINE([HAVE_SCALBNL],[1],[libm includes scalbnl])]) diff --git a/libgfortran/intrinsics/c99_functions.c b/libgfortran/intrinsics/c99_functions.c index 8b82ae3..e36c5ba 100644 --- a/libgfortran/intrinsics/c99_functions.c +++ b/libgfortran/intrinsics/c99_functions.c @@ -500,6 +500,35 @@ powf(float x, float y) /* Algorithm by Steven G. Kargl. */ +#if !defined(HAVE_ROUNDL) && defined(HAVE_CEILL) +#define HAVE_ROUNDL 1 +/* Round to nearest integral value. If the argument is halfway between two + integral values then round away from zero. */ + +long double +roundl(long double x) +{ + long double t; + if (!isfinite (x)) + return (x); + + if (x >= 0.0) + { + t = ceill(x); + if (t - x > 0.5) + t -= 1.0; + return (t); + } + else + { + t = ceill(-x); + if (t + x > 0.5) + t -= 1.0; + return (-t); + } +} +#endif + #ifndef HAVE_ROUND #define HAVE_ROUND 1 /* Round to nearest integral value. If the argument is halfway between two @@ -558,6 +587,64 @@ roundf(float x) } #endif + +/* lround{f,,l} and llround{f,,l} functions. */ + +#if !defined(HAVE_LROUNDF) && defined(HAVE_ROUNDF) +#define HAVE_LROUNDF 1 +long int +lroundf (float x) +{ + return (long int) roundf (x); +} +#endif + +#if !defined(HAVE_LROUND) && defined(HAVE_ROUND) +#define HAVE_LROUND 1 +long int +lround (double x) +{ + return (long int) round (x); +} +#endif + +#if !defined(HAVE_LROUNDL) && defined(HAVE_ROUNDL) +#define HAVE_LROUNDL 1 +long int +lroundl (long double x) +{ + return (long long int) roundl (x); +} +#endif + +#if !defined(HAVE_LLROUNDF) && defined(HAVE_ROUNDF) +#define HAVE_LLROUNDF 1 +long long int +llroundf (float x) +{ + return (long long int) roundf (x); +} +#endif + +#if !defined(HAVE_LLROUND) && defined(HAVE_ROUND) +#define HAVE_LLROUND 1 +long long int +llround (double x) +{ + return (long long int) round (x); +} +#endif + +#if !defined(HAVE_LLROUNDL) && defined(HAVE_ROUNDL) +#define HAVE_LLROUNDL 1 +long long int +llroundl (long double x) +{ + return (long long int) roundl (x); +} +#endif + + #ifndef HAVE_LOG10L #define HAVE_LOG10L 1 /* log10 function for long double variables. The version provided here |