diff --git a/libgcobol/Makefile.am b/libgcobol/Makefile.am index 89d0519ed06..0a17d2077f1 100644 --- a/libgcobol/Makefile.am +++ b/libgcobol/Makefile.am @@ -46,7 +46,7 @@ libgcobol_la_SOURCES = \ WARN_CFLAGS = -W -Wall -Wwrite-strings -AM_CPPFLAGS = -I. -I$(srcdir) +AM_CPPFLAGS = -I. -I$(srcdir) $(LIBQUADINCLUDE) AM_CFLAGS = $(XCFLAGS) AM_CXXFLAGS = $(XCFLAGS) AM_CXXFLAGS += $(WARN_CFLAGS) @@ -62,9 +62,8 @@ endif # We want to link with the c++ runtime. libgcobol_la_LINK = $(CXXLINK) $(libgcobol_la_LDFLAGS) version_arg = -version-info $(LIBGCOBOL_VERSION) -libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LTLIBICONV) \ - $(extra_ldflags_libgcobol) $(LIBS) \ - $(version_arg) -libgcobol_la_DEPENDENCIES = libgcobol.spec +libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LIBQUADLIB) $(LTLIBICONV) \ + $(extra_ldflags_libgcobol) $(LIBS) $(version_arg) +libgcobol_la_DEPENDENCIES = libgcobol.spec $(LIBQUADLIB_DEP) endif BUILD_LIBGCOBOL diff --git a/libgcobol/Makefile.in b/libgcobol/Makefile.in index 88158cbf377..5fdc42c2a20 100644 --- a/libgcobol/Makefile.in +++ b/libgcobol/Makefile.in @@ -288,6 +288,10 @@ LIBGCOBOL_VERSION = @LIBGCOBOL_VERSION@ LIBICONV = @LIBICONV@ LIBM = @LIBM@ LIBOBJS = @LIBOBJS@ +LIBQUADINCLUDE = @LIBQUADINCLUDE@ +LIBQUADLIB = @LIBQUADLIB@ +LIBQUADLIB_DEP = @LIBQUADLIB_DEP@ +LIBQUADSPEC = @LIBQUADSPEC@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ @@ -317,6 +321,7 @@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPEC_LIBGCOBOL_DEPS = @SPEC_LIBGCOBOL_DEPS@ STRIP = @STRIP@ +USE_IEC_60559 = @USE_IEC_60559@ VERSION = @VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ @@ -402,7 +407,7 @@ gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) @BUILD_LIBGCOBOL_TRUE@ valconv.cc @BUILD_LIBGCOBOL_TRUE@WARN_CFLAGS = -W -Wall -Wwrite-strings -@BUILD_LIBGCOBOL_TRUE@AM_CPPFLAGS = -I. -I$(srcdir) +@BUILD_LIBGCOBOL_TRUE@AM_CPPFLAGS = -I. -I$(srcdir) $(LIBQUADINCLUDE) @BUILD_LIBGCOBOL_TRUE@AM_CFLAGS = $(XCFLAGS) @BUILD_LIBGCOBOL_TRUE@AM_CXXFLAGS = $(XCFLAGS) $(WARN_CFLAGS) \ @BUILD_LIBGCOBOL_TRUE@ -DIN_TARGET_LIBS -fno-strict-aliasing @@ -410,11 +415,10 @@ gcc_version := $(shell @get_gcc_base_ver@ $(top_srcdir)/../gcc/BASE-VER) # We want to link with the c++ runtime. @BUILD_LIBGCOBOL_TRUE@libgcobol_la_LINK = $(CXXLINK) $(libgcobol_la_LDFLAGS) @BUILD_LIBGCOBOL_TRUE@version_arg = -version-info $(LIBGCOBOL_VERSION) -@BUILD_LIBGCOBOL_TRUE@libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LTLIBICONV) \ -@BUILD_LIBGCOBOL_TRUE@ $(extra_ldflags_libgcobol) $(LIBS) \ -@BUILD_LIBGCOBOL_TRUE@ $(version_arg) +@BUILD_LIBGCOBOL_TRUE@libgcobol_la_LDFLAGS = $(LTLDFLAGS) $(LIBQUADLIB) $(LTLIBICONV) \ +@BUILD_LIBGCOBOL_TRUE@ $(extra_ldflags_libgcobol) $(LIBS) $(version_arg) -@BUILD_LIBGCOBOL_TRUE@libgcobol_la_DEPENDENCIES = libgcobol.spec +@BUILD_LIBGCOBOL_TRUE@libgcobol_la_DEPENDENCIES = libgcobol.spec $(LIBQUADLIB_DEP) all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am diff --git a/libgcobol/acinclude.m4 b/libgcobol/acinclude.m4 index ed340c7977a..aab0895146b 100644 --- a/libgcobol/acinclude.m4 +++ b/libgcobol/acinclude.m4 @@ -24,3 +24,165 @@ AC_DEFUN([AC_LIBTOOL_DLOPEN],) AC_DEFUN([AC_LIBLTDL_CONVENIENCE],) AC_SUBST(LIBTOOL) ]) + +dnl Check whether we have a __float128 and _Float128 type +dnl Unashamedly plagiarized from libgfortran. + +AC_DEFUN([LIBGCOBOL_CHECK_FLOAT128], [ + LIBQUADSPEC= + LIBQUADLIB= + LIBQUADLIB_DEP= + LIBQUADINCLUDE= + USE_IEC_60559=no + + if test "x$enable_libquadmath_support" = "xno"; then + if test "x$have_iec_60559_libc_support" = "xyes"; then + AC_DEFINE(USE_IEC_60559, 1, [Define if IEC 60559 *f128 APIs should be used for _Float128.]) + fi + else + + AC_CACHE_CHECK([whether we have a usable _Float128 type], + libgcob_cv_have_float128, [ + GCC_TRY_COMPILE_OR_LINK([ + _Float128 foo (_Float128 x) + { + _Complex _Float128 z1, z2; + + z1 = x; + z2 = x / 7.F128; + z2 /= z1; + + return __real__ z2; + } + + _Float128 bar (_Float128 x) + { + return x * __builtin_huge_valf128 (); + } + + __float128 baz (__float128 x) + { + return x * __builtin_huge_valf128 (); + } + ],[ + foo (1.2F128); + bar (1.2F128); + baz (1.2F128); + foo (1.2Q); + bar (1.2Q); + baz (1.2Q); + ],[ + libgcob_cv_have_float128=yes + ],[ + libgcob_cv_have_float128=no +])]) + + if test "x$have_iec_60559_libc_support$enable_libquadmath_support$libgcob_cv_have_float128" = xyesdefaultyes; then + USE_IEC_60559=yes + fi + + if test "x$libgcob_cv_have_float128" = xyes; then + + if test "x$USE_IEC_60559" = xyes; then + AC_DEFINE(USE_IEC_60559, 1, [Define if IEC 60559 *f128 APIs should be used for _Float128.]) + else + AC_DEFINE(USE_QUADMATH, 1, [Define if *q APIs should be used for __float128.]) + fi + AC_DEFINE(HAVE_FLOAT128, 1, [Define if target has usable _Float128 and __float128 types.]) + + dnl Check whether -Wl,--as-needed resp. -Wl,-zignore is supported + dnl + dnl Turn warnings into error to avoid testsuite breakage. So enable + dnl AC_LANG_WERROR, but there's currently (autoconf 2.64) no way to turn + dnl it off again. As a workaround, save and restore werror flag like + dnl AC_PATH_XTRA. + dnl Cf. http://gcc.gnu.org/ml/gcc-patches/2010-05/msg01889.html + ac_xsave_[]_AC_LANG_ABBREV[]_werror_flag=$ac_[]_AC_LANG_ABBREV[]_werror_flag + AC_CACHE_CHECK([whether --as-needed/-z ignore works], + [libgcob_cv_have_as_needed], + [ + # Test for native Solaris options first. + # No whitespace after -z to pass it through -Wl. + libgcob_cv_as_needed_option="-zignore" + libgcob_cv_no_as_needed_option="-zrecord" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no + AC_LANG_WERROR + AC_LINK_IFELSE([AC_LANG_PROGRAM([])], + [libgcob_cv_have_as_needed=yes], + [libgcob_cv_have_as_needed=no]) + LDFLAGS="$save_LDFLAGS" + if test "x$libgcob_cv_have_as_needed" = xno; then + libgcob_cv_as_needed_option="--as-needed" + libgcob_cv_no_as_needed_option="--no-as-needed" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no + AC_LANG_WERROR + AC_LINK_IFELSE([AC_LANG_PROGRAM([])], + [libgcob_cv_have_as_needed=yes], + [libgcob_cv_have_as_needed=no]) + LDFLAGS="$save_LDFLAGS" + fi + ac_[]_AC_LANG_ABBREV[]_werror_flag=$ac_xsave_[]_AC_LANG_ABBREV[]_werror_flag + ]) + + dnl Determine -Bstatic ... -Bdynamic etc. support from gfortran -### stderr. + touch conftest1.$ac_objext conftest2.$ac_objext + LQUADMATH=-lquadmath + $CXX -static-libgcobol -### -o conftest \ + conftest1.$ac_objext -lgcobol conftest2.$ac_objext 2>&1 >/dev/null \ + | grep "conftest1.$ac_objext.*conftest2.$ac_objext" > conftest.cmd + if grep "conftest1.$ac_objext.* -Bstatic -lgcobol -Bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-Bstatic} -lquadmath %{static-libquadmath:-Bdynamic}" + elif grep "conftest1.$ac_objext.* -bstatic -lgcobol -bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-bstatic} -lquadmath %{static-libquadmath:-bdynamic}" + elif grep "conftest1.$ac_objext.* -aarchive_shared -lgcobol -adefault .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-aarchive_shared} -lquadmath %{static-libquadmath:-adefault}" + elif grep "conftest1.$ac_objext.*libgcobol.a .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:libquadmath.a%s;:-lquadmath}" + fi + rm -f conftest1.$ac_objext conftest2.$ac_objext conftest conftest.cmd + + dnl For static libgcobol linkage, depend on libquadmath only if needed. + dnl If using *f128 APIs from libc/libm, depend on libquadmath only if needed + dnl even for dynamic libgcobol linkage, and don't link libgcobol against + dnl -lquadmath. + if test "x$libgcob_cv_have_as_needed" = xyes; then + if test "x$USE_IEC_60559" = xyes; then + LIBQUADSPEC="$libgcob_cv_as_needed_option $LQUADMATH $libgcob_cv_no_as_needed_option" + else + LIBQUADSPEC="%{static-libgcobol:$libgcob_cv_as_needed_option} $LQUADMATH %{static-libgcobol:$libgcob_cv_no_as_needed_option}" + fi + else + LIBQUADSPEC="$LQUADMATH" + fi + if test "x$USE_IEC_60559" != xyes; then + if test -f ../libquadmath/libquadmath.la; then + LIBQUADLIB=../libquadmath/libquadmath.la + LIBQUADLIB_DEP=../libquadmath/libquadmath.la + LIBQUADINCLUDE='-I$(srcdir)/../libquadmath' + else + LIBQUADLIB="-lquadmath" + fi + fi + else + if test "x$USE_IEC_60559" = xyes; then + AC_DEFINE(USE_IEC_60559, 1, [Define if IEC 60559 *f128 APIs should be used for _Float128.]) + fi + fi + + fi + + dnl For the spec file + AC_SUBST(LIBQUADSPEC) + AC_SUBST(LIBQUADLIB) + AC_SUBST(LIBQUADLIB_DEP) + AC_SUBST(LIBQUADINCLUDE) + AC_SUBST(USE_IEC_60559) +]) diff --git a/libgcobol/config.h.in b/libgcobol/config.h.in index d61ff7ad497..6a532799616 100644 --- a/libgcobol/config.h.in +++ b/libgcobol/config.h.in @@ -3,12 +3,30 @@ /* Define to 1 if the target assembler supports thread-local storage. */ #undef HAVE_CC_TLS +/* Define to 1 if you have the header file. */ +#undef HAVE_COMPLEX_H + /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the header file. */ +#undef HAVE_FENV_H + +/* Define if target has usable _Float128 and __float128 types. */ +#undef HAVE_FLOAT128 + +/* Define to 1 if you have the header file. */ +#undef HAVE_FLOATINGPOINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_FPTRAP_H + /* Define if you have the iconv() function and it works. */ #undef HAVE_ICONV +/* Define to 1 if you have the header file. */ +#undef HAVE_IEEEFP_H + /* Define to 1 if you have the `initstate_r' function. */ #undef HAVE_INITSTATE_R @@ -36,6 +54,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H +/* Define to 1 if you have the `strfromf128' function. */ +#undef HAVE_STRFROMF128 + /* Define to 1 if you have the `strfromf32' function. */ #undef HAVE_STRFROMF32 @@ -48,6 +69,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H +/* Define to 1 if you have the `strtof128' function. */ +#undef HAVE_STRTOF128 + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H @@ -88,6 +112,12 @@ /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS +/* Define if IEC 60559 *f128 APIs should be used for _Float128. */ +#undef USE_IEC_60559 + +/* Define if *q APIs should be used for __float128. */ +#undef USE_QUADMATH + /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE diff --git a/libgcobol/configure b/libgcobol/configure index 1715b986b9e..6c2747c275b 100755 --- a/libgcobol/configure +++ b/libgcobol/configure @@ -629,13 +629,21 @@ ac_includes_default="\ # include #endif" +ac_header_list= ac_func_list= +ac_cxx_werror_flag= +ac_cxx_werror_flag= ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS SPEC_LIBGCOBOL_DEPS get_gcc_base_ver +USE_IEC_60559 +LIBQUADINCLUDE +LIBQUADLIB_DEP +LIBQUADLIB +LIBQUADSPEC extra_ldflags_libgcobol LIBGCOBOL_VERSION BUILD_LIBGCOBOL_FALSE @@ -793,6 +801,7 @@ with_toolexeclibdir enable_rpath with_libiconv_prefix with_libiconv_type +enable_libquadmath with_gcc_major_version_only ' ac_precious_vars='build_alias @@ -1445,6 +1454,7 @@ Optional Features: install libraries with @rpath/library-name, requires rpaths to be added to executables --disable-rpath do not hardcode runtime library paths + --disable-libquadmath disable libquadmath support for libgcobol Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -2339,6 +2349,37 @@ rm -f conftest.val } # ac_fn_cxx_compute_int +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_compile + # ac_fn_cxx_check_func LINENO FUNC VAR # ------------------------------------ # Tests whether FUNC exists, setting the cache variable VAR accordingly @@ -2692,12 +2733,20 @@ $as_echo "$as_me: creating cache $cache_file" >&6;} >$cache_file fi +as_fn_append ac_header_list " floatingpoint.h" +as_fn_append ac_header_list " ieeefp.h" +as_fn_append ac_header_list " fenv.h" +as_fn_append ac_header_list " fptrap.h" +as_fn_append ac_header_list " complex.h" +as_fn_append ac_header_list " stdlib.h" as_fn_append ac_func_list " random_r" as_fn_append ac_func_list " srandom_r" as_fn_append ac_func_list " initstate_r" as_fn_append ac_func_list " setstate_r" as_fn_append ac_func_list " strfromf32" as_fn_append ac_func_list " strfromf64" +as_fn_append ac_func_list " strtof128" +as_fn_append ac_func_list " strfromf128" # Check that the precious variables saved in the cache have kept the same # value. ac_cache_corrupted=false @@ -11644,7 +11693,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11647 "configure" +#line 11696 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -11750,7 +11799,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 11753 "configure" +#line 11802 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -16861,65 +16910,6 @@ if test "$ac_res" != no; then : fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cosf128" >&5 -$as_echo_n "checking for library containing cosf128... " >&6; } -if ${ac_cv_search_cosf128+:} false; then : - $as_echo_n "(cached) " >&6 -else - ac_func_search_save_LIBS=$LIBS -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char cosf128 (); -int -main () -{ -return cosf128 (); - ; - return 0; -} -_ACEOF -for ac_lib in '' c m; do - if test -z "$ac_lib"; then - ac_res="none required" - else - ac_res=-l$ac_lib - LIBS="-l$ac_lib $ac_func_search_save_LIBS" - fi - if test x$gcc_no_link = xyes; then - as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 -fi -if ac_fn_cxx_try_link "$LINENO"; then : - ac_cv_search_cosf128=$ac_res -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext - if ${ac_cv_search_cosf128+:} false; then : - break -fi -done -if ${ac_cv_search_cosf128+:} false; then : - -else - ac_cv_search_cosf128=no -fi -rm conftest.$ac_ext -LIBS=$ac_func_search_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cosf128" >&5 -$as_echo "$ac_cv_search_cosf128" >&6; } -ac_res=$ac_cv_search_cosf128 -if test "$ac_res" != no; then : - test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - -fi - # libgcobol soname version LIBGCOBOL_VERSION=1:0:0 @@ -16938,6 +16928,37 @@ case $host in esac + + + + for ac_header in $ac_header_list +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + + + + + + + + + + + + + # These are GLIBC @@ -16964,7 +16985,441 @@ done -# These are C23, and might not be available in libc. +# Some functions we check to figure out if the libc Float128 support +# is adequate. + +# These are C23. + + + + + + +# These are GLIBC. + + + + + +# We need to make sure to check libc before adding libm. +libgcobol_have_sinf128=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sinf128" >&5 +$as_echo_n "checking for library containing sinf128... " >&6; } +if ${ac_cv_search_sinf128+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sinf128 (); +int +main () +{ +return sinf128 (); + ; + return 0; +} +_ACEOF +for ac_lib in '' c m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_sinf128=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_sinf128+:} false; then : + break +fi +done +if ${ac_cv_search_sinf128+:} false; then : + +else + ac_cv_search_sinf128=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sinf128" >&5 +$as_echo "$ac_cv_search_sinf128" >&6; } +ac_res=$ac_cv_search_sinf128 +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + libgcobol_have_sinf128=yes +fi + +libgcobol_have_cacosf128=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing cacosf128" >&5 +$as_echo_n "checking for library containing cacosf128... " >&6; } +if ${ac_cv_search_cacosf128+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char cacosf128 (); +int +main () +{ +return cacosf128 (); + ; + return 0; +} +_ACEOF +for ac_lib in '' c m; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_search_cacosf128=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_cacosf128+:} false; then : + break +fi +done +if ${ac_cv_search_cacosf128+:} false; then : + +else + ac_cv_search_cacosf128=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_cacosf128" >&5 +$as_echo "$ac_cv_search_cacosf128" >&6; } +ac_res=$ac_cv_search_cacosf128 +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + libgcobol_have_cacosf128=yes +fi + + +have_iec_60559_libc_support=no +if test "x$ac_cv_func_strtof128$ac_cv_func_strfromf128" = xyesyes \ + && test "x$libgcobol_have_sinf128$libgcobol_have_cacosf128" = xyesyes; then + have_iec_60559_libc_support=yes +fi + +# Check whether libquadmath should be used +# Check whether --enable-libquadmath was given. +if test "${enable_libquadmath+set}" = set; then : + enableval=$enable_libquadmath; ENABLE_LIBQUADMATH_SUPPORT=$enableval +else + if test "x$have_iec_60559_libc_support" = xyes; then + ENABLE_LIBQUADMATH_SUPPORT=default +else + ENABLE_LIBQUADMATH_SUPPORT=yes +fi +fi + +enable_libquadmath_support= +if test "${ENABLE_LIBQUADMATH_SUPPORT}" = "no" ; then + enable_libquadmath_support=no +elif test "${ENABLE_LIBQUADMATH_SUPPORT}" = "default" ; then + enable_libquadmath_support=default +fi + + LIBQUADSPEC= + LIBQUADLIB= + LIBQUADLIB_DEP= + LIBQUADINCLUDE= + USE_IEC_60559=no + + if test "x$enable_libquadmath_support" = "xno"; then + if test "x$have_iec_60559_libc_support" = "xyes"; then + +$as_echo "#define USE_IEC_60559 1" >>confdefs.h + + fi + else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have a usable _Float128 type" >&5 +$as_echo_n "checking whether we have a usable _Float128 type... " >&6; } +if ${libgcob_cv_have_float128+:} false; then : + $as_echo_n "(cached) " >&6 +else + + if test x$gcc_no_link = xyes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + _Float128 foo (_Float128 x) + { + _Complex _Float128 z1, z2; + + z1 = x; + z2 = x / 7.F128; + z2 /= z1; + + return __real__ z2; + } + + _Float128 bar (_Float128 x) + { + return x * __builtin_huge_valf128 (); + } + + __float128 baz (__float128 x) + { + return x * __builtin_huge_valf128 (); + } + +int +main () +{ + + foo (1.2F128); + bar (1.2F128); + baz (1.2F128); + foo (1.2Q); + bar (1.2Q); + baz (1.2Q); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + + libgcob_cv_have_float128=yes + +else + + libgcob_cv_have_float128=no + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +else + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + _Float128 foo (_Float128 x) + { + _Complex _Float128 z1, z2; + + z1 = x; + z2 = x / 7.F128; + z2 /= z1; + + return __real__ z2; + } + + _Float128 bar (_Float128 x) + { + return x * __builtin_huge_valf128 (); + } + + __float128 baz (__float128 x) + { + return x * __builtin_huge_valf128 (); + } + +int +main () +{ + + foo (1.2F128); + bar (1.2F128); + baz (1.2F128); + foo (1.2Q); + bar (1.2Q); + baz (1.2Q); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + libgcob_cv_have_float128=yes + +else + + libgcob_cv_have_float128=no + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcob_cv_have_float128" >&5 +$as_echo "$libgcob_cv_have_float128" >&6; } + + if test "x$have_iec_60559_libc_support$enable_libquadmath_support$libgcob_cv_have_float128" = xyesdefaultyes; then + USE_IEC_60559=yes + fi + + if test "x$libgcob_cv_have_float128" = xyes; then + + if test "x$USE_IEC_60559" = xyes; then + +$as_echo "#define USE_IEC_60559 1" >>confdefs.h + + else + +$as_echo "#define USE_QUADMATH 1" >>confdefs.h + + fi + +$as_echo "#define HAVE_FLOAT128 1" >>confdefs.h + + + ac_xsave_cxx_werror_flag=$ac_cxx_werror_flag + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether --as-needed/-z ignore works" >&5 +$as_echo_n "checking whether --as-needed/-z ignore works... " >&6; } +if ${libgcob_cv_have_as_needed+:} false; then : + $as_echo_n "(cached) " >&6 +else + + # Test for native Solaris options first. + # No whitespace after -z to pass it through -Wl. + libgcob_cv_as_needed_option="-zignore" + libgcob_cv_no_as_needed_option="-zrecord" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no + +ac_cxx_werror_flag=yes + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + libgcob_cv_have_as_needed=yes +else + libgcob_cv_have_as_needed=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + if test "x$libgcob_cv_have_as_needed" = xno; then + libgcob_cv_as_needed_option="--as-needed" + libgcob_cv_no_as_needed_option="--no-as-needed" + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -Wl,$libgcob_cv_as_needed_option -lm -Wl,$libgcob_cv_no_as_needed_option" + libgcob_cv_have_as_needed=no + +ac_cxx_werror_flag=yes + if test x$gcc_no_link = xyes; then + as_fn_error $? "Link tests are not allowed after GCC_NO_EXECUTABLES." "$LINENO" 5 +fi +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + libgcob_cv_have_as_needed=yes +else + libgcob_cv_have_as_needed=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + fi + ac_cxx_werror_flag=$ac_xsave_cxx_werror_flag + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgcob_cv_have_as_needed" >&5 +$as_echo "$libgcob_cv_have_as_needed" >&6; } + + touch conftest1.$ac_objext conftest2.$ac_objext + LQUADMATH=-lquadmath + $CXX -static-libgcobol -### -o conftest \ + conftest1.$ac_objext -lgcobol conftest2.$ac_objext 2>&1 >/dev/null \ + | grep "conftest1.$ac_objext.*conftest2.$ac_objext" > conftest.cmd + if grep "conftest1.$ac_objext.* -Bstatic -lgcobol -Bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-Bstatic} -lquadmath %{static-libquadmath:-Bdynamic}" + elif grep "conftest1.$ac_objext.* -bstatic -lgcobol -bdynamic .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-bstatic} -lquadmath %{static-libquadmath:-bdynamic}" + elif grep "conftest1.$ac_objext.* -aarchive_shared -lgcobol -adefault .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:-aarchive_shared} -lquadmath %{static-libquadmath:-adefault}" + elif grep "conftest1.$ac_objext.*libgcobol.a .*conftest2.$ac_objext" \ + conftest.cmd >/dev/null 2>&1; then + LQUADMATH="%{static-libquadmath:libquadmath.a%s;:-lquadmath}" + fi + rm -f conftest1.$ac_objext conftest2.$ac_objext conftest conftest.cmd + + if test "x$libgcob_cv_have_as_needed" = xyes; then + if test "x$USE_IEC_60559" = xyes; then + LIBQUADSPEC="$libgcob_cv_as_needed_option $LQUADMATH $libgcob_cv_no_as_needed_option" + else + LIBQUADSPEC="%{static-libgcobol:$libgcob_cv_as_needed_option} $LQUADMATH %{static-libgcobol:$libgcob_cv_no_as_needed_option}" + fi + else + LIBQUADSPEC="$LQUADMATH" + fi + if test "x$USE_IEC_60559" != xyes; then + if test -f ../libquadmath/libquadmath.la; then + LIBQUADLIB=../libquadmath/libquadmath.la + LIBQUADLIB_DEP=../libquadmath/libquadmath.la + LIBQUADINCLUDE='-I$(srcdir)/../libquadmath' + else + LIBQUADLIB="-lquadmath" + fi + fi + else + if test "x$USE_IEC_60559" = xyes; then + +$as_echo "#define USE_IEC_60559 1" >>confdefs.h + + fi + fi + + fi + + diff --git a/libgcobol/configure.ac b/libgcobol/configure.ac index ca56997ae0e..a1e95139299 100644 --- a/libgcobol/configure.ac +++ b/libgcobol/configure.ac @@ -169,7 +169,6 @@ AM_CONDITIONAL(BUILD_LIBGCOBOL, [test "x$LIBGCOBOL_SUPPORTED" = xyes && test "x$ # Check if functions are available in libc before adding extra libs. AC_SEARCH_LIBS([malloc], [c]) AC_SEARCH_LIBS([clock_gettime], [c rt]) -AC_SEARCH_LIBS([cosf128], [c m]) # libgcobol soname version LIBGCOBOL_VERSION=1:0:0 @@ -188,12 +187,50 @@ case $host in esac AC_SUBST(extra_ldflags_libgcobol) +AC_CHECK_HEADERS_ONCE(floatingpoint.h ieeefp.h fenv.h fptrap.h \ +complex.h stdlib.h) + # These are GLIBC AC_CHECK_FUNCS_ONCE(random_r srandom_r initstate_r setstate_r) -# These are C23, and might not be available in libc. +# Some functions we check to figure out if the libc Float128 support +# is adequate. + +# These are C23. AC_CHECK_FUNCS_ONCE(strfromf32 strfromf64) +# These are GLIBC. +AC_CHECK_FUNCS_ONCE(strtof128 strfromf128) +# We need to make sure to check libc before adding libm. +libgcobol_have_sinf128=no +AC_SEARCH_LIBS([sinf128], [c m], libgcobol_have_sinf128=yes) +libgcobol_have_cacosf128=no +AC_SEARCH_LIBS([cacosf128], [c m], libgcobol_have_cacosf128=yes) + +have_iec_60559_libc_support=no +if test "x$ac_cv_func_strtof128$ac_cv_func_strfromf128" = xyesyes \ + && test "x$libgcobol_have_sinf128$libgcobol_have_cacosf128" = xyesyes; then + have_iec_60559_libc_support=yes +fi + +# Check whether libquadmath should be used +AC_ARG_ENABLE(libquadmath, +AS_HELP_STRING([--disable-libquadmath], + [disable libquadmath support for libgcobol]), +ENABLE_LIBQUADMATH_SUPPORT=$enableval, +if test "x$have_iec_60559_libc_support" = xyes; then + ENABLE_LIBQUADMATH_SUPPORT=default +else + ENABLE_LIBQUADMATH_SUPPORT=yes +fi) +enable_libquadmath_support= +if test "${ENABLE_LIBQUADMATH_SUPPORT}" = "no" ; then + enable_libquadmath_support=no +elif test "${ENABLE_LIBQUADMATH_SUPPORT}" = "default" ; then + enable_libquadmath_support=default +fi +LIBGCOBOL_CHECK_FLOAT128 + if test "${multilib}" = "yes"; then multilib_arg="--enable-multilib" else diff --git a/libgcobol/gfileio.cc b/libgcobol/gfileio.cc index ed250c47f94..e297e95a121 100644 --- a/libgcobol/gfileio.cc +++ b/libgcobol/gfileio.cc @@ -41,6 +41,7 @@ #include #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "io.h" diff --git a/libgcobol/gmath.cc b/libgcobol/gmath.cc index fb2eae38ef3..3fe2bbbc79d 100644 --- a/libgcobol/gmath.cc +++ b/libgcobol/gmath.cc @@ -40,6 +40,7 @@ #include #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "common-defs.h" @@ -54,10 +55,6 @@ #include #include -#ifdef __aarch64__ -#define __float128 _Float128 -#endif - #define MAX_INTERMEDIATE_BITS 126 #define MAX_INTERMEDIATE_DECIMALS 16 @@ -114,7 +111,7 @@ conditional_stash( cblc_field_t *destination, size_t destination_o, size_t destination_s, bool on_error_flag, - _Float128 value, + GCOB_FP128 value, cbl_round_t rounded) { int retval = compute_error_none; @@ -150,15 +147,10 @@ conditional_stash( cblc_field_t *destination, return retval; } - -#if defined(__aarch64__) -# define __float128 _Float128 /* double */ -#endif - static -_Float128 -divide_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +divide_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { if( b_value == 0 ) @@ -187,9 +179,9 @@ divide_helper_float(_Float128 a_value, } static -_Float128 -multiply_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +multiply_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { a_value *= b_value; @@ -210,9 +202,9 @@ multiply_helper_float(_Float128 a_value, } static -_Float128 -addition_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +addition_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { a_value += b_value; @@ -233,9 +225,9 @@ addition_helper_float(_Float128 a_value, } static -_Float128 -subtraction_helper_float(_Float128 a_value, - _Float128 b_value, +GCOB_FP128 +subtraction_helper_float(GCOB_FP128 a_value, + GCOB_FP128 b_value, int *compute_error) { a_value -= b_value; @@ -276,9 +268,9 @@ __gg__pow( cbl_arith_format_t, size_t *C_o = __gg__treeplet_3o; size_t *C_s = __gg__treeplet_3s; - _Float128 avalue = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); - _Float128 bvalue = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); - _Float128 tgt_value; + GCOB_FP128 avalue = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); + GCOB_FP128 bvalue = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); + GCOB_FP128 tgt_value; if( avalue == 0 && bvalue == 0 ) { @@ -295,7 +287,7 @@ __gg__pow( cbl_arith_format_t, // Calculate our answer, in floating point: errno = 0; feclearexcept(FE_ALL_EXCEPT); - tgt_value = powf128(avalue, bvalue); + tgt_value = FP128_FUNC(pow)(avalue, bvalue); if( errno || fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW) ) { // One of a large number of errors took place. See math_error(7) and @@ -568,7 +560,7 @@ get_int256_from_qualified_field(int256 &var, static int256 phase1_result; static int phase1_rdigits; -static _Float128 phase1_result_float; +static GCOB_FP128 phase1_result_float; extern "C" void @@ -654,11 +646,11 @@ __gg__addf1_fixed_phase2( cbl_arith_format_t , // proceed accordingly. // Convert the intermediate - _Float128 value_a = (_Float128)phase1_result.i128[0]; + GCOB_FP128 value_a = (GCOB_FP128)phase1_result.i128[0]; value_a /= __gg__power_of_ten(phase1_rdigits); // Pick up the target - _Float128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); value_a += value_b; @@ -740,7 +732,7 @@ __gg__fixed_phase2_assign_to_c( cbl_arith_format_t , // proceed accordingly. // Convert the intermediate - _Float128 value_a = (_Float128)phase1_result.i128[0]; + GCOB_FP128 value_a = (GCOB_FP128)phase1_result.i128[0]; value_a /= __gg__power_of_ten(phase1_rdigits); *compute_error |= conditional_stash(C[0], C_o[0], C_s[0], @@ -796,7 +788,7 @@ __gg__add_float_phase1( cbl_arith_format_t , for( size_t i=1; itype == FldFloat || C[i]->type == FldFloat ) { - _Float128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); - _Float128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); + GCOB_FP128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); value_a = addition_helper_float(value_a, value_b, compute_error); @@ -966,11 +958,11 @@ __gg__subtractf1_fixed_phase2(cbl_arith_format_t , // proceed accordingly. // Convert the intermediate - _Float128 value_a = (_Float128)phase1_result.i128[0]; + GCOB_FP128 value_a = (GCOB_FP128)phase1_result.i128[0]; value_a /= __gg__power_of_ten(phase1_rdigits); // Pick up the target - _Float128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); value_b -= value_a; @@ -1106,7 +1098,7 @@ __gg__subtractf1_float_phase2(cbl_arith_format_t , // This is the assignment phase of an ADD Format 2 // We take phase1_result and subtract it from C - _Float128 temp = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); + GCOB_FP128 temp = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); temp = subtraction_helper_float(temp, phase1_result_float, compute_error); *compute_error |= conditional_stash(C[0], C_o[0], C_s[0], on_size_error, @@ -1143,7 +1135,7 @@ __gg__subtractf2_float_phase1(cbl_arith_format_t , ); // Subtract that from the B value: - _Float128 value_b = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); // The two numbers have the same number of rdigits. It's now safe to add // them. @@ -1177,8 +1169,8 @@ __gg__subtractf3( cbl_arith_format_t , { if( A[i]->type == FldFloat || C[i]->type == FldFloat) { - _Float128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); - _Float128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); + GCOB_FP128 value_a = __gg__float128_from_qualified_field(A[i], A_o[i], A_s[i]); + GCOB_FP128 value_b = __gg__float128_from_qualified_field(C[i], C_o[i], C_s[i]); value_b = subtraction_helper_float(value_b, value_a, compute_error); @@ -1235,7 +1227,7 @@ __gg__subtractf3( cbl_arith_format_t , } static bool multiply_intermediate_is_float; -static _Float128 multiply_intermediate_float; +static GCOB_FP128 multiply_intermediate_float; static __int128 multiply_intermediate_int128; static int multiply_intermediate_rdigits; @@ -1351,8 +1343,8 @@ __gg__multiplyf1_phase2(cbl_arith_format_t , bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); int error_this_time=0; - _Float128 a_value; - _Float128 b_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; if( multiply_intermediate_is_float ) { @@ -1374,10 +1366,10 @@ __gg__multiplyf1_phase2(cbl_arith_format_t , if( C[0]->type == FldFloat ) { // gixed * float - a_value = (_Float128) multiply_intermediate_int128; + a_value = (GCOB_FP128) multiply_intermediate_int128; if( multiply_intermediate_rdigits ) { - a_value /= (_Float128)__gg__power_of_ten(multiply_intermediate_rdigits); + a_value /= (GCOB_FP128)__gg__power_of_ten(multiply_intermediate_rdigits); } b_value = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); goto float_float; @@ -1457,14 +1449,14 @@ __gg__multiplyf2( cbl_arith_format_t , bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); bool got_float = false; - _Float128 product_float; + GCOB_FP128 product_float; int256 product_fix; int product_fix_digits; if( A[0]->type == FldFloat || B[0]->type == FldFloat ) { - _Float128 a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); - _Float128 b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); + GCOB_FP128 a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); + GCOB_FP128 b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); product_float = multiply_helper_float(a_value, b_value, compute_error); got_float = true; } @@ -1834,8 +1826,8 @@ __gg__dividef1_phase2(cbl_arith_format_t , bool on_size_error = !!(on_error_flag & ON_SIZE_ERROR); int error_this_time=0; - _Float128 a_value; - _Float128 b_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; if( multiply_intermediate_is_float ) { @@ -1857,10 +1849,10 @@ __gg__dividef1_phase2(cbl_arith_format_t , if( C[0]->type == FldFloat ) { // gixed * float - a_value = (_Float128) multiply_intermediate_int128; + a_value = (GCOB_FP128) multiply_intermediate_int128; if( multiply_intermediate_rdigits ) { - a_value /= (_Float128)__gg__power_of_ten(multiply_intermediate_rdigits); + a_value /= (GCOB_FP128)__gg__power_of_ten(multiply_intermediate_rdigits); } b_value = __gg__float128_from_qualified_field(C[0], C_o[0], C_s[0]); goto float_float; @@ -1948,9 +1940,9 @@ __gg__dividef23(cbl_arith_format_t , if( A[0]->type == FldFloat || B[0]->type == FldFloat ) { - _Float128 a_value; - _Float128 b_value; - _Float128 c_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; + GCOB_FP128 c_value; a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); c_value = divide_helper_float(a_value, b_value, &error_this_time); @@ -2029,9 +2021,9 @@ __gg__dividef45(cbl_arith_format_t , if( A[0]->type == FldFloat || B[0]->type == FldFloat ) { - _Float128 a_value; - _Float128 b_value; - _Float128 c_value; + GCOB_FP128 a_value; + GCOB_FP128 b_value; + GCOB_FP128 c_value; a_value = __gg__float128_from_qualified_field(A[0], A_o[0], A_s[0]); b_value = __gg__float128_from_qualified_field(B[0], B_o[0], B_s[0]); c_value = divide_helper_float(a_value, b_value, &error_this_time); diff --git a/libgcobol/intrinsic.cc b/libgcobol/intrinsic.cc index e0bd3339708..844cd388063 100644 --- a/libgcobol/intrinsic.cc +++ b/libgcobol/intrinsic.cc @@ -45,6 +45,7 @@ #include #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "common-defs.h" @@ -53,6 +54,15 @@ #include "libgcobol.h" #include "charmaps.h" + +#if !defined (HAVE_STRTOF128) +# if USE_QUADMATH +# define strtof128 strtoflt128 +# else +# error "no available string to float 128" +# endif +#endif + #pragma GCC diagnostic ignored "-Wformat-truncation" #define JD_OF_1601_01_02 2305812.5 @@ -406,7 +416,7 @@ get_value_as_double_from_qualified_field( cblc_field_t *input, } static -_Float128 kahan_summation(size_t ncount, +GCOB_FP128 kahan_summation(size_t ncount, cblc_field_t **source, size_t *source_o, size_t *source_s, @@ -420,11 +430,11 @@ _Float128 kahan_summation(size_t ncount, // an aggressive optimizing compiler from just making it go away. *k_count = 0; - _Float128 sum = 0; - volatile _Float128 kahan_c = 0; - _Float128 input; - _Float128 y; - _Float128 t; + GCOB_FP128 sum = 0; + volatile GCOB_FP128 kahan_c = 0; + GCOB_FP128 input; + GCOB_FP128 y; + GCOB_FP128 t; for(size_t i=0; i +1.00Q ) + if( value < GCOB_FP128_LITERAL(-1.00) || value > GCOB_FP128_LITERAL(+1.00) ) { exception_raise(ec_argument_function_e); value = WEIRD_TRANSCENDENT_RETURN_VALUE; } else { - value = acosf128(value); + value = FP128_FUNC(acos)(value); } __gg__float128_to_field( dest, @@ -1011,12 +1021,12 @@ __gg__annuity(cblc_field_t *dest, { // FUNCTION ANNUITY - _Float128 retval = 0; + GCOB_FP128 retval = 0; - _Float128 val1 = fabsf128(__gg__float128_from_qualified_field(arg1, + GCOB_FP128 val1 = FP128_FUNC(fabs)(__gg__float128_from_qualified_field(arg1, arg1_offset, arg1_size)); - _Float128 val2 = fabsf128(__gg__float128_from_qualified_field(arg2, + GCOB_FP128 val2 = FP128_FUNC(fabs)(__gg__float128_from_qualified_field(arg2, arg2_offset, arg2_size)); if( val2 > 0) @@ -1031,7 +1041,7 @@ __gg__annuity(cblc_field_t *dest, } else { - retval = val1 / (1- powf128( (1+val1), -val2 )); + retval = val1 / (1- FP128_FUNC(pow)( (1+val1), -val2 )); } } else @@ -1053,19 +1063,19 @@ __gg__asin( cblc_field_t *dest, { // FUNCTION ASIN - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - if( value < -1.0Q || value > +1.00Q ) + if( value < GCOB_FP128_LITERAL(-1.0) || value > GCOB_FP128_LITERAL(+1.00) ) { exception_raise(ec_argument_function_e); value = WEIRD_TRANSCENDENT_RETURN_VALUE; } else { - value = asinf128(value); + value = FP128_FUNC(asin)(value); } __gg__float128_to_field( dest, @@ -1083,12 +1093,12 @@ __gg__atan( cblc_field_t *dest, { // FUNCTION ATAN - _Float128 value; + GCOB_FP128 value; value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = atanf128(value); + value = FP128_FUNC(atan)(value); __gg__float128_to_field( dest, value, @@ -1195,10 +1205,10 @@ __gg__cos(cblc_field_t *dest, { // FUNCTION COS - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = cosf128(value); + value = FP128_FUNC(cos)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1368,7 +1378,8 @@ void __gg__e(cblc_field_t *dest) { // FUNCTION E - static _Float128 e = 2.7182818284590452353602874713526624977572Q; + static GCOB_FP128 e + = GCOB_FP128_LITERAL(2.7182818284590452353602874713526624977572); __gg__float128_to_field(dest, e, truncation_e, @@ -1384,10 +1395,10 @@ __gg__exp(cblc_field_t *dest, { // FUNCTION EXP - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = expf128(value); + value = FP128_FUNC(exp)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1403,10 +1414,10 @@ __gg__exp10(cblc_field_t *dest, { // FUNCTION EXP10 - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = powf128(10.0Q, value); + value = FP128_FUNC(pow)(GCOB_FP128_LITERAL(10.0), value); __gg__float128_to_field(dest, value, truncation_e, @@ -1658,10 +1669,10 @@ __gg__integer(cblc_field_t *dest, size_t source_size) { // FUNCTION INTEGER - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - value = floorf128(value); + value = FP128_FUNC(floor)(value); __gg__float128_to_field(dest, value, truncation_e, @@ -1758,10 +1769,10 @@ __gg__integer_part( cblc_field_t *dest, size_t source_size) { // FUNCTION INTEGER-PART - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); - _Float128 retval = floorf128(fabsf128(value)); + GCOB_FP128 retval = FP128_FUNC(floor)(FP128_FUNC(fabs)(value)); if( value < 0 ) { @@ -1781,7 +1792,7 @@ __gg__fraction_part(cblc_field_t *dest, size_t source_size) { // FUNCTION INTEGER-PART - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); bool is_negative = false; @@ -1791,7 +1802,7 @@ __gg__fraction_part(cblc_field_t *dest, value = -value; } - _Float128 retval = value - floorf128(value); + GCOB_FP128 retval = value - FP128_FUNC(floor)(value); if( is_negative ) { @@ -1811,7 +1822,7 @@ __gg__log( cblc_field_t *dest, size_t source_size) { // FUNCTION LOG - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); if( value <= 0.00 ) @@ -1820,7 +1831,7 @@ __gg__log( cblc_field_t *dest, } else { - _Float128 retval = logf128(value); + GCOB_FP128 retval = FP128_FUNC(log)(value); __gg__float128_to_field(dest, retval, truncation_e, @@ -1836,7 +1847,7 @@ __gg__log10( cblc_field_t *dest, size_t source_size) { // FUNCTION LOG10 - _Float128 value = __gg__float128_from_qualified_field(source, + GCOB_FP128 value = __gg__float128_from_qualified_field(source, source_offset, source_size); if( value <= 0.00 ) @@ -1845,7 +1856,7 @@ __gg__log10( cblc_field_t *dest, } else { - _Float128 retval = log10f128(value); + GCOB_FP128 retval = FP128_FUNC(log10)(value); __gg__float128_to_field(dest, retval, truncation_e, @@ -1931,7 +1942,7 @@ __gg__max(cblc_field_t *dest, } else { - _Float128 retval; + GCOB_FP128 retval; bool first_time = true; assert(ncount); for(size_t i=0; i= retval ) { retval = candidate; @@ -1992,7 +2003,7 @@ __gg__mean( cblc_field_t *dest, { // FUNCTION MEAN size_t k_count; - _Float128 sum = kahan_summation(ninputs, + GCOB_FP128 sum = kahan_summation(ninputs, __gg__treeplet_1f, __gg__treeplet_1o, __gg__treeplet_1s, @@ -2021,7 +2032,7 @@ __gg__median( cblc_field_t *dest, size_t list_size = 1; - _Float128 *the_list = (_Float128 *)malloc(list_size *sizeof(_Float128)); + GCOB_FP128 *the_list = (GCOB_FP128 *)malloc(list_size *sizeof(GCOB_FP128)); size_t k_count = 0; assert(ncount); for(size_t i=0; i= list_size) { list_size *= 2; - the_list = (_Float128 *)realloc(the_list, list_size *sizeof(_Float128)); + the_list = (GCOB_FP128 *)realloc(the_list, list_size *sizeof(GCOB_FP128)); } the_list[k_count] = __gg__float128_from_qualified_field(__gg__treeplet_1f[i], @@ -2050,7 +2061,7 @@ __gg__median( cblc_field_t *dest, } std::sort(the_list, the_list+k_count); - _Float128 retval; + GCOB_FP128 retval; size_t i=k_count/2; if( k_count & 1 ) { @@ -2073,9 +2084,9 @@ __gg__midrange( cblc_field_t *dest, size_t ncount) { // FUNCTION MIDRANGE - _Float128 val; - _Float128 min=0; - _Float128 max=0; + GCOB_FP128 val; + GCOB_FP128 min=0; + GCOB_FP128 max=0; bool first_time = true; assert(ncount); for(size_t i=0; i 0); for(size_t i=0; idata + source_offset); char *data_end = data + source_size; diff --git a/libgcobol/libgcobol-fp.h b/libgcobol/libgcobol-fp.h new file mode 100644 index 00000000000..bd443f3a234 --- /dev/null +++ b/libgcobol/libgcobol-fp.h @@ -0,0 +1,50 @@ +/* Copyright The GNU Toolchain Authors. */ + +/* This file is part of the GNU COBOL runtime library (libgcobol). + +libgcobol is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public +License as published by the Free Software Foundation; either +version 3 of the License, or (at your option) any later version. + +libgcobol is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +Under Section 7 of GPL version 3, you are granted additional +permissions described in the GCC Runtime Library Exception, version +3.1, as published by the Free Software Foundation. + +You should have received a copy of the GNU General Public License and +a copy of the GCC Runtime Library Exception along with this program; +see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +. */ + +/* You must include "config.h" before this file. */ + +#if __LDBL_MANT_DIG__ == 113 && __LDBL_MIN_EXP__ == -16381 +// Use long double, l suffix on calls, l or L suffix in literals +# define GCOB_FP128 long double +# define GCOB_FP128_LITERAL(lit) (lit ## l) +# define FP128_FUNC(funcname) funcname ## l +#elif __FLT128_MANT_DIG__ == 113 && __FLT128_MIN_EXP__ == -16381 \ + && defined(USE_IEC_60559) +// Use _Float128, f128 suffix on calls, f128 or F128 suffix on literals +# define GCOB_FP128 _Float128 +# define GCOB_FP128_LITERAL(lit) (lit ## f128) +# define FP128_FUNC(funcname) funcname ## f128 +#elif __FLT128_MANT_DIG__ == 113 && __FLT128_MIN_EXP__ == -16381 +// Use __float128, q suffix on calls, q or Q suffix on literals +# define GCOB_FP128 __float128 +# define GCOB_FP128_LITERAL(lit) (lit ## q) +# define FP128_FUNC(funcname) funcname ## q +#else +# error "libgcobol requires 128b floating point" +#endif + +#if USE_QUADMATH +/* We will assume that unless we found the 128 to/from string and some + representative trig functions, we need libquadmath to support those. */ +# include "quadmath.h" +#endif diff --git a/libgcobol/libgcobol.cc b/libgcobol/libgcobol.cc index f7fa7a7527b..d912ea3fb08 100644 --- a/libgcobol/libgcobol.cc +++ b/libgcobol/libgcobol.cc @@ -50,6 +50,7 @@ #include #include "config.h" +#include "libgcobol-fp.h" #include "ec.h" #include "common-defs.h" @@ -92,6 +93,20 @@ strfromf64 (char *s, size_t n, const char *f, double v) # endif #endif +#if !defined (HAVE_STRFROMF128) +# if !USE_QUADMATH +# error "no available float 128 to string" +# endif +#endif + +#if !defined (HAVE_STRTOF128) +# if USE_QUADMATH +# define strtof128 strtoflt128 +# else +# error "no available string to float 128" +# endif +#endif + // This couldn't be defined in symbols.h because it conflicts with a LEVEL66 // in parse.h #define LEVEL66 (66) @@ -881,10 +896,12 @@ int128_to_int128_rounded( cbl_round_t rounded, int *compute_error) { // value is signed, and is scaled to the target - _Float128 fpart = _Float128(remainder) / _Float128(factor); + GCOB_FP128 fpart = ((GCOB_FP128)remainder) / ((GCOB_FP128)factor); __int128 retval = value; - if(rounded == nearest_even_e && fpart != -0.5Q && fpart != 0.5Q ) + if(rounded == nearest_even_e + && fpart != GCOB_FP128_LITERAL (-0.5) + && fpart != GCOB_FP128_LITERAL (0.5)) { // "bankers rounding" has been requested. // @@ -905,14 +922,14 @@ int128_to_int128_rounded( cbl_round_t rounded, // 0.5 through 0.9 becomes 1 if( value < 0 ) { - if( fpart <= -0.5Q ) + if( fpart <= GCOB_FP128_LITERAL(-0.5) ) { retval -= 1; } } else { - if( fpart >= 0.5Q ) + if( fpart >= GCOB_FP128_LITERAL(0.5) ) { retval += 1; } @@ -946,14 +963,14 @@ int128_to_int128_rounded( cbl_round_t rounded, // 0.6 through 0.9 becomes 1 if( value < 0 ) { - if( fpart < -0.5Q ) + if( fpart < GCOB_FP128_LITERAL(-0.5) ) { retval -= 1; } } else { - if( fpart > 0.5Q ) + if( fpart > GCOB_FP128_LITERAL(0.5) ) { retval += 1; } @@ -1035,15 +1052,17 @@ int128_to_int128_rounded( cbl_round_t rounded, static __int128 f128_to_i128_rounded( cbl_round_t rounded, - _Float128 value, + GCOB_FP128 value, int *compute_error) { // value is signed, and is scaled to the target - _Float128 ipart; - _Float128 fpart = modff128(value, &ipart); + GCOB_FP128 ipart; + GCOB_FP128 fpart = FP128_FUNC(modf)(value, &ipart); __int128 retval = (__int128)ipart; - if(rounded == nearest_even_e && fpart != -0.5Q && fpart != 0.5Q ) + if(rounded == nearest_even_e + && fpart != GCOB_FP128_LITERAL (-0.5) + && fpart != GCOB_FP128_LITERAL (0.5)) { // "bankers rounding" has been requested. // @@ -1064,14 +1083,14 @@ f128_to_i128_rounded( cbl_round_t rounded, // 0.5 through 0.9 becomes 1 if( value < 0 ) { - if( fpart <= -0.5Q ) + if( fpart <= GCOB_FP128_LITERAL (-0.5) ) { retval -= 1; } } else { - if( fpart >= 0.5Q ) + if( fpart >= GCOB_FP128_LITERAL (0.5) ) { retval += 1; } @@ -1105,14 +1124,14 @@ f128_to_i128_rounded( cbl_round_t rounded, // 0.6 through 0.9 becomes 1 if( value < 0 ) { - if( fpart < -0.5Q ) + if( fpart < GCOB_FP128_LITERAL (-0.5) ) { retval -= 1; } } else { - if( fpart > 0.5Q ) + if( fpart > GCOB_FP128_LITERAL (0.5) ) { retval += 1; } @@ -1276,8 +1295,8 @@ int128_to_field(cblc_field_t *var, { value = -value; } - _Float128 tvalue = (_Float128 )value; - tvalue /= (_Float128 )__gg__power_of_ten(source_rdigits); + GCOB_FP128 tvalue = (GCOB_FP128 )value; + tvalue /= (GCOB_FP128 )__gg__power_of_ten(source_rdigits); // *(_Float128 *)location = tvalue; // memcpy because *(_Float128 *) requires a 16-byte boundary. memcpy(location, &tvalue, 16); @@ -2573,7 +2592,7 @@ __gg__dirty_to_binary_internal( const char *dirty, } extern "C" -_Float128 +GCOB_FP128 __gg__dirty_to_float( const char *dirty, int length) { @@ -2589,7 +2608,7 @@ __gg__dirty_to_float( const char *dirty, // It also can handle 12345E-2 notation. - _Float128 retval = 0; + GCOB_FP128 retval = 0; int rdigits = 0; int hyphen = 0; @@ -3244,9 +3263,13 @@ format_for_display_internal(char **dest, // We can't use *(_Float64 *)actual_location; // That uses the SSE registers, which won't work if the source isn't // on a 16-bit boundary. - _Float128 floatval; + GCOB_FP128 floatval; memcpy(&floatval, actual_location, 16); +#if !defined (HAVE_STRFROMF128) && USE_QUADMATH + quadmath_snprintf(ach, sizeof(ach), "%.36QE", floatval); +#else strfromf128(ach, sizeof(ach), "%.36E", floatval); +#endif char *p = strchr(ach, 'E'); if( !p ) { @@ -3268,8 +3291,13 @@ format_for_display_internal(char **dest, int precision = 36 - exp; char achFormat[24]; +#if !defined (HAVE_STRFROMF128) && USE_QUADMATH + sprintf(achFormat, "%%.%dQf", precision); + quadmath_snprintf(ach, sizeof(ach), achFormat, floatval); +#else sprintf(achFormat, "%%.%df", precision); strfromf128(ach, sizeof(ach), achFormat, floatval); +#endif } __gg__remove_trailing_zeroes(ach); __gg__realloc_if_necessary(dest, dest_size, strlen(ach)+1); @@ -3481,11 +3509,11 @@ compare_88( const char *list, return cmpval; } -static _Float128 +static GCOB_FP128 get_float128( cblc_field_t *field, unsigned char *location ) { - _Float128 retval=0; + GCOB_FP128 retval=0; if(field->type == FldFloat ) { switch( field->capacity ) @@ -3710,7 +3738,7 @@ compare_field_class(cblc_field_t *conditional, case FldFloat: { - _Float128 value = get_float128(conditional, conditional_location) ; + GCOB_FP128 value = get_float128(conditional, conditional_location) ; char *walker = list->initial; while(*walker) { @@ -3734,7 +3762,7 @@ compare_field_class(cblc_field_t *conditional, walker = right + right_len; - _Float128 left_value; + GCOB_FP128 left_value; if( left_flag == 'F' && left[0] == 'Z' ) { left_value = 0; @@ -3745,7 +3773,7 @@ compare_field_class(cblc_field_t *conditional, left_len); } - _Float128 right_value; + GCOB_FP128 right_value; if( right_flag == 'F' && right[0] == 'Z' ) { right_value = 0; @@ -4100,7 +4128,7 @@ __gg__compare_2(cblc_field_t *left_side, case FldFloat: { - _Float128 value = __gg__float128_from_location(left_side, + GCOB_FP128 value = __gg__float128_from_location(left_side, left_location); retval = 0; retval = value < 0 ? -1 : retval; @@ -4157,8 +4185,8 @@ __gg__compare_2(cblc_field_t *left_side, if( left_side->type == FldFloat && right_side->type == FldFloat ) { // One or the other of the numerics is a FldFloat - _Float128 left_value = __gg__float128_from_location(left_side, left_location); - _Float128 right_value = __gg__float128_from_location(right_side, right_location); + GCOB_FP128 left_value = __gg__float128_from_location(left_side, left_location); + GCOB_FP128 right_value = __gg__float128_from_location(right_side, right_location); retval = 0; retval = left_value < right_value ? -1 : retval; retval = left_value > right_value ? 1 : retval; @@ -4170,8 +4198,8 @@ __gg__compare_2(cblc_field_t *left_side, { // The left side is a FldFloat; the other is another type of numeric: int rdecimals; - _Float128 left_value; - _Float128 right_value; + GCOB_FP128 left_value; + GCOB_FP128 right_value; if( right_side->type == FldLiteralN) { @@ -4203,7 +4231,7 @@ __gg__compare_2(cblc_field_t *left_side, case 4: { _Float32 left_value = *(_Float32 *)left_location; - _Float32 right_value = strtof32(buffer, NULL); + _Float32 right_value = strtof(buffer, NULL); retval = 0; retval = left_value < right_value ? -1 : retval; retval = left_value > right_value ? 1 : retval; @@ -4212,7 +4240,7 @@ __gg__compare_2(cblc_field_t *left_side, case 8: { _Float64 left_value = *(_Float64 *)left_location; - _Float64 right_value = strtof64(buffer, NULL); + _Float64 right_value = strtod(buffer, NULL); retval = 0; retval = left_value < right_value ? -1 : retval; retval = left_value > right_value ? 1 : retval; @@ -4221,9 +4249,9 @@ __gg__compare_2(cblc_field_t *left_side, case 16: { //_Float128 left_value = *(_Float128 *)left_location; - _Float128 left_value; + GCOB_FP128 left_value; memcpy(&left_value, left_location, 16); - _Float128 right_value = strtof128(buffer, NULL); + GCOB_FP128 right_value = strtof128(buffer, NULL); retval = 0; retval = left_value < right_value ? -1 : retval; retval = left_value > right_value ? 1 : retval; @@ -5725,7 +5753,7 @@ __gg__move( cblc_field_t *fdest, case 16: { //_Float128 val = *(_Float128 *)(fsource->data+source_offset); - _Float128 val; + GCOB_FP128 val; memcpy(&val, fsource->data+source_offset, 16); if(val < 0) { @@ -5813,7 +5841,7 @@ __gg__move( cblc_field_t *fdest, // We are converted a floating-point value fixed-point rdigits = get_scaled_rdigits(fdest); - _Float128 value=0; + GCOB_FP128 value=0; switch(fsource->capacity) { case 4: @@ -5963,18 +5991,18 @@ __gg__move( cblc_field_t *fdest, { case 4: { - *(float *)(fdest->data+dest_offset) = strtof32(ach, NULL); + *(float *)(fdest->data+dest_offset) = strtof(ach, NULL); break; } case 8: { - *(double *)(fdest->data+dest_offset) = strtof64(ach, NULL); + *(double *)(fdest->data+dest_offset) = strtod(ach, NULL); break; } case 16: { //*(_Float128 *)(fdest->data+dest_offset) = strtof128(ach, NULL); - _Float128 t = strtof128(ach, NULL); + GCOB_FP128 t = strtof128(ach, NULL); memcpy(fdest->data+dest_offset, &t, 16); break; } @@ -6133,17 +6161,17 @@ __gg__move_literala(cblc_field_t *field, { case 4: { - *(float *)(field->data+field_offset) = strtof32(ach, NULL); + *(float *)(field->data+field_offset) = strtof(ach, NULL); break; } case 8: { - *(double *)(field->data+field_offset) = strtof64(ach, NULL); + *(double *)(field->data+field_offset) = strtod(ach, NULL); break; } case 16: { - _Float128 t = strtof128(ach, NULL); + GCOB_FP128 t = strtof128(ach, NULL); memcpy(field->data+field_offset, &t, 16); break; } @@ -9127,10 +9155,10 @@ __gg__binary_value_from_qualified_field(int *rdigits, } extern "C" -_Float128 +GCOB_FP128 __gg__float128_from_field( cblc_field_t *field ) { - _Float128 retval=0; + GCOB_FP128 retval=0; if( field->type == FldFloat || field->type == FldLiteralN ) { retval = get_float128(field, field->data); @@ -9138,20 +9166,20 @@ __gg__float128_from_field( cblc_field_t *field ) else { int rdigits; - retval = (_Float128)__gg__binary_value_from_field(&rdigits, field); + retval = (GCOB_FP128)__gg__binary_value_from_field(&rdigits, field); if( rdigits ) { - retval /= (_Float128)__gg__power_of_ten(rdigits); + retval /= (GCOB_FP128)__gg__power_of_ten(rdigits); } } return retval; } extern "C" -_Float128 +GCOB_FP128 __gg__float128_from_qualified_field( cblc_field_t *field, size_t offset, size_t size) { - _Float128 retval=0; + GCOB_FP128 retval=0; if( field->type == FldFloat || field->type == FldLiteralN ) { retval = get_float128(field, field->data+offset); @@ -9159,10 +9187,10 @@ __gg__float128_from_qualified_field( cblc_field_t *field, size_t offset, size_t else { int rdigits; - retval = (_Float128)__gg__binary_value_from_qualified_field(&rdigits, field, offset, size); + retval = (GCOB_FP128)__gg__binary_value_from_qualified_field(&rdigits, field, offset, size); if( rdigits ) { - retval /= (_Float128)__gg__power_of_ten(rdigits); + retval /= (GCOB_FP128)__gg__power_of_ten(rdigits); } } return retval; @@ -9228,7 +9256,7 @@ __gg__int128_to_qualified_field(cblc_field_t *tgt, static __int128 float128_to_int128( int *rdigits, cblc_field_t *field, - _Float128 value, + GCOB_FP128 value, cbl_round_t rounded, int *compute_error) { @@ -9253,7 +9281,7 @@ float128_to_int128( int *rdigits, // get away with. // Calculate the number of digits to the left of the decimal point: - int digits = (int)(floorf128(logf128(fabsf128(value)))+1); + int digits = (int)(FP128_FUNC(floor)(FP128_FUNC(log)(FP128_FUNC(fabs)(value)))+1); // Make sure it is not a negative number digits = std::max(0, digits); @@ -9270,12 +9298,12 @@ float128_to_int128( int *rdigits, // We now multiply our value by 10**rdigits, in order to make the // floating-point value have the same magnitude as our target __int128 - value *= powf128(10.0Q, (_Float128)(*rdigits)); + value *= FP128_FUNC(pow)(GCOB_FP128_LITERAL (10.0), (GCOB_FP128)(*rdigits)); // We are ready to cast value to an __int128. But this value could be // too large to fit, which is an error condition we want to flag: - if( fabsf128(value) >= 1.0E38Q ) + if( FP128_FUNC(fabs)(value) >= GCOB_FP128_LITERAL (1.0E38) ) { *compute_error = compute_error_overflow; } @@ -9292,7 +9320,7 @@ static void float128_to_location( cblc_field_t *tgt, unsigned char *data, size_t size, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error) { @@ -9303,8 +9331,8 @@ float128_to_location( cblc_field_t *tgt, switch(tgt->capacity) { case 4: - if( fabsf128(value) == (_Float128)INFINITY - || fabsf128(value) > 3.4028235E38Q ) + if( FP128_FUNC(fabs)(value) == (GCOB_FP128)INFINITY + || FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { if( compute_error ) { @@ -9326,8 +9354,8 @@ float128_to_location( cblc_field_t *tgt, break; case 8: - if( fabsf128(value) == (_Float128)INFINITY - || fabsf128(value) > 1.7976931348623157E308Q ) + if( FP128_FUNC(fabs)(value) == (GCOB_FP128)INFINITY + || FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (1.7976931348623157E308) ) { if( compute_error ) { @@ -9349,7 +9377,7 @@ float128_to_location( cblc_field_t *tgt, break; case 16: - if( fabsf128(value) == (_Float128)INFINITY ) + if( FP128_FUNC(fabs)(value) == (GCOB_FP128)INFINITY ) { if( compute_error ) { @@ -9378,7 +9406,7 @@ float128_to_location( cblc_field_t *tgt, digits = tgt->digits; } - _Float128 maximum; + GCOB_FP128 maximum; if( digits ) { @@ -9387,7 +9415,7 @@ float128_to_location( cblc_field_t *tgt, // When digits is zero, this is a binary value without a PICTURE string. // we don't truncate in that case - if( digits && fabsf128(value) >= maximum ) + if( digits && FP128_FUNC(fabs)(value) >= maximum ) { *compute_error |= compute_error_truncate; } @@ -9415,7 +9443,7 @@ float128_to_location( cblc_field_t *tgt, extern "C" void __gg__float128_to_field(cblc_field_t *tgt, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error) { @@ -9431,7 +9459,7 @@ extern "C" void __gg__float128_to_qualified_field(cblc_field_t *tgt, size_t tgt_offset, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error) { @@ -10409,7 +10437,7 @@ __gg__fetch_call_by_value_value(cblc_field_t *field, case 16: // *(_Float128 *)(&retval) = double(*(_Float128 *)data); - _Float128 t; + GCOB_FP128 t; memcpy(&t, data, 16); memcpy(&retval, &t, 16); break; @@ -10470,7 +10498,7 @@ __gg__assign_value_from_stack(cblc_field_t *dest, __int128 parameter) case 16: // *(_Float128 *)(dest->data) = *(_Float128 *)¶meter; - _Float128 t; + GCOB_FP128 t; memcpy(&t, ¶meter, 16); memcpy(dest->data, &t, 16); break; @@ -11306,10 +11334,10 @@ __gg__pseudo_return_flush() } extern "C" -_Float128 +GCOB_FP128 __gg__float128_from_location(cblc_field_t *var, unsigned char *location) { - _Float128 retval = 0; + GCOB_FP128 retval = 0; switch( var->capacity ) { case 4: @@ -11338,9 +11366,9 @@ extern "C" __int128 __gg__integer_from_float128(cblc_field_t *field) { - _Float128 fvalue = __gg__float128_from_location(field, field->data); + GCOB_FP128 fvalue = __gg__float128_from_location(field, field->data); // we round() to take care of the possible 2.99999999999... problem. - fvalue = roundf128(fvalue); + fvalue = FP128_FUNC(round)(fvalue); return (__int128)fvalue; } @@ -11566,13 +11594,13 @@ __gg__float32_from_int128(cblc_field_t *destination, int *size_error) { int rdigits; - _Float128 value = get_binary_value_local( &rdigits, + GCOB_FP128 value = get_binary_value_local( &rdigits, source, source->data + source_offset, source->capacity); value /= __gg__power_of_ten(rdigits); - if( fabsf128(value) > 3.4028235E38Q ) + if( FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { if(size_error) { @@ -11607,7 +11635,7 @@ __gg__float64_from_int128(cblc_field_t *destination, *size_error = 0; } int rdigits; - _Float128 value = get_binary_value_local( &rdigits, + GCOB_FP128 value = get_binary_value_local( &rdigits, source, source->data + source_offset, source->capacity); @@ -11630,7 +11658,7 @@ __gg__float128_from_int128(cblc_field_t *destination, { if(size_error) *size_error = 0; int rdigits; - _Float128 value = get_binary_value_local( &rdigits, + GCOB_FP128 value = get_binary_value_local( &rdigits, source, source->data + source_offset, source->capacity); @@ -11657,7 +11685,7 @@ __gg__is_float_infinite(cblc_field_t *source, size_t offset) break; case 16: // retval = *(_Float128*)(source->data+offset) == INFINITY; - _Float128 t; + GCOB_FP128 t; memcpy(&t, source->data+offset, 16); retval = t == INFINITY; break; @@ -11674,9 +11702,9 @@ __gg__float32_from_128( cblc_field_t *dest, { int retval = 0; //_Float128 value = *(_Float128*)(source->data+source_offset); - _Float128 value; + GCOB_FP128 value; memcpy(&value, source->data+source_offset, 16); - if( fabsf128(value) > 3.4028235E38Q ) + if( FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { retval = 1; } @@ -11696,7 +11724,7 @@ __gg__float32_from_64( cblc_field_t *dest, { int retval = 0; _Float64 value = *(_Float64*)(source->data+source_offset); - if( fabsf128(value) > 3.4028235E38Q ) + if( FP128_FUNC(fabs)(value) > GCOB_FP128_LITERAL (3.4028235E38) ) { retval = 1; } @@ -11716,9 +11744,9 @@ __gg__float64_from_128( cblc_field_t *dest, { int retval = 0; // _Float128 value = *(_Float128*)(source->data+source_offset); - _Float128 value; + GCOB_FP128 value; memcpy(&value, source->data+source_offset, 16); - if( fabsf128(value) > 1.7976931348623157E308 ) + if( FP128_FUNC(fabs)(value) > 1.7976931348623157E308 ) { retval = 1; } diff --git a/libgcobol/libgcobol.h b/libgcobol/libgcobol.h index 246ef511495..f35987d5bac 100644 --- a/libgcobol/libgcobol.h +++ b/libgcobol/libgcobol.h @@ -67,7 +67,7 @@ extern "C" void __gg__int128_to_field(cblc_field_t *tgt, enum cbl_round_t rounded, int *compute_error); extern "C" void __gg__float128_to_field(cblc_field_t *tgt, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error); extern "C" void __gg__int128_to_qualified_field(cblc_field_t *tgt, @@ -79,10 +79,9 @@ extern "C" void __gg__int128_to_qualified_field(cblc_field_t *tgt, int *compute_error); extern "C" void __gg__float128_to_qualified_field(cblc_field_t *tgt, size_t tgt_offset, - _Float128 value, + GCOB_FP128 value, enum cbl_round_t rounded, int *compute_error); - extern "C" void __gg__double_to_target( cblc_field_t *tgt, double tgt_value, cbl_round_t rounded); @@ -91,7 +90,8 @@ extern "C" char __gg__get_decimal_point(); extern "C" char * __gg__get_default_currency_string(); extern "C" void __gg__clock_gettime(clockid_t clk_id, struct timespec *tp); -extern "C" _Float128 __gg__float128_from_location(cblc_field_t *var, + +extern "C" GCOB_FP128 __gg__float128_from_location(cblc_field_t *var, unsigned char *location); extern "C" void __gg__adjust_dest_size(cblc_field_t *dest, size_t ncount); @@ -104,7 +104,7 @@ extern "C" __int128 __gg__binary_value_from_qualified_field(int *rdigits, cblc_field_t *var, size_t offset, size_t size); -extern "C" _Float128 __gg__float128_from_qualified_field(cblc_field_t *field, +extern "C" GCOB_FP128 __gg__float128_from_qualified_field(cblc_field_t *field, size_t offset, size_t size); extern "C" __int128 __gg__integer_from_qualified_field(cblc_field_t *var, diff --git a/libgcobol/libgcobol.spec.in b/libgcobol/libgcobol.spec.in index e8ccc0db0dd..461587d1fb8 100644 --- a/libgcobol/libgcobol.spec.in +++ b/libgcobol/libgcobol.spec.in @@ -5,4 +5,4 @@ # %rename lib liborig -*lib: @LIBM@ %(liborig) +*lib: @LIBQUADSPEC@ @LIBM@ %(liborig)