From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7803 invoked by alias); 31 Jul 2007 21:31:43 -0000 Received: (qmail 7753 invoked by uid 22791); 31 Jul 2007 21:31:27 -0000 X-Spam-Check-By: sourceware.org Received: from fk-out-0910.google.com (HELO fk-out-0910.google.com) (209.85.128.184) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 31 Jul 2007 21:31:21 +0000 Received: by fk-out-0910.google.com with SMTP id 26so6777fkx for ; Tue, 31 Jul 2007 14:31:18 -0700 (PDT) Received: by 10.82.151.14 with SMTP id y14mr33905bud.1185917478280; Tue, 31 Jul 2007 14:31:18 -0700 (PDT) Received: from ?144.82.208.57? ( [144.82.208.57]) by mx.google.com with ESMTPS id i4sm38769nfh.2007.07.31.14.31.15 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 31 Jul 2007 14:31:16 -0700 (PDT) Mime-Version: 1.0 (Apple Message framework v752.3) To: GFORTRAN list , GCC-patches list Message-Id: <1EFD0FF2-E8B1-42F8-9A15-9928DAA7BAF7@gmail.com> Content-Type: multipart/mixed; boundary=Apple-Mail-6--695641153 From: FX Coudert Subject: [gfortran,patch] Fix code generated for NINT Date: Tue, 31 Jul 2007 21:39:00 -0000 X-Mailer: Apple Mail (2.752.3) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2007-07/txt/msg02208.txt.bz2 --Apple-Mail-6--695641153 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII; delsp=yes; format=flowed Content-length: 589 Attached patch fixes PR31202 by correcting the code generated for calls to the intrinsic NINT (and ANINT). Instead of adding 0.5 and rounding by casting into an integer, we simply call the lround (or llround) functions. A fallback implementation of these functions is provided for libgfortran. I've bootstrapped and regtested on x86_64-linux, but I'd be glad if someone with a platform without full C99 support, and especiall lround, could test it. I once had access to a sparc-solaris2.9, which fulfilled these criteria, but not more. OK for mainline? :ADDPATCH 31202: --Apple-Mail-6--695641153 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name=nint.ChangeLog Content-Disposition: attachment; filename=nint.ChangeLog Content-length: 834 2007-07-31 Francois-Xavier Coudert 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-07-31 Francois-Xavier Coudert 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-31 Francois-Xavier Coudert PR fortran/31202 * gfortran.dg/nint_2.f90: New test. --Apple-Mail-6--695641153 Content-Transfer-Encoding: 7bit Content-Type: application/octet-stream; x-unix-mode=0644; name=nint.diff Content-Disposition: attachment; filename=nint.diff Content-length: 27705 Index: gcc/fortran/f95-lang.c =================================================================== --- gcc/fortran/f95-lang.c (revision 127059) +++ gcc/fortran/f95-lang.c (working copy) @@ -853,7 +853,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); @@ -943,6 +943,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); Index: gcc/fortran/trans-intrinsic.c =================================================================== --- gcc/fortran/trans-intrinsic.c (revision 127059) +++ gcc/fortran/trans-intrinsic.c (working copy) @@ -26,6 +26,7 @@ Software Foundation, 51 Franklin Street, #include "config.h" #include "system.h" #include "coretypes.h" +#include "tm.h" #include "tree.h" #include "ggc.h" #include "toplev.h" @@ -309,34 +310,57 @@ build_fixbound_expr (stmtblock_t * pbloc } -/* 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; } @@ -359,11 +383,15 @@ build_fix_expr (stmtblock_t * pblock, tr 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 (); } } Index: libgfortran/configure =================================================================== --- libgfortran/configure (revision 127059) +++ libgfortran/configure (working copy) @@ -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 Index: libgfortran/Makefile.in =================================================================== --- libgfortran/Makefile.in (revision 127059) +++ libgfortran/Makefile.in (working copy) @@ -50,8 +50,8 @@ am__aclocal_m4_deps = $(top_srcdir)/../c $(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@ Index: libgfortran/intrinsics/c99_functions.c =================================================================== --- libgfortran/intrinsics/c99_functions.c (revision 127059) +++ libgfortran/intrinsics/c99_functions.c (working copy) @@ -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 Index: libgfortran/config.h.in =================================================================== --- libgfortran/config.h.in (revision 127059) +++ libgfortran/config.h.in (working copy) @@ -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 Index: libgfortran/c99_protos.h =================================================================== --- libgfortran/c99_protos.h (revision 127059) +++ libgfortran/c99_protos.h (working copy) @@ -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. */ Index: libgfortran/configure.ac =================================================================== --- libgfortran/configure.ac (revision 127059) +++ libgfortran/configure.ac (working copy) @@ -301,6 +301,12 @@ AC_CHECK_LIB([m],[cpowl],[AC_DEFINE([HAV 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])]) Index: gcc/testsuite/gfortran.dg/nint_2.f90 =================================================================== --- gcc/testsuite/gfortran.dg/nint_2.f90 (revision 0) +++ gcc/testsuite/gfortran.dg/nint_2.f90 (revision 0) @@ -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 --Apple-Mail-6--695641153--