Skip to content

Commit 4f26344

Browse files
derobinsqkoziol
authored andcommitted
Clean up Fortran __float128 configure-time checks (HDFGroup#4649)
* Always use DECIMAL_DIG instead of LDBL_DIG. This was controlled by an ifdef that is always true in C99 or greater It's confusing to use float.h C constants as variable names in configure.ac and the PAC_FC_LDBL_DIG macro. * Directly compare MY_FLT128_DIG and MY_LDBL_DIG * Make uniform across CMake and Autotools * Don't export quadmath.h variables to H5pubconf.h
1 parent 4fbb888 commit 4f26344

File tree

7 files changed

+170
-106
lines changed

7 files changed

+170
-106
lines changed

config/cmake/ConfigureChecks.cmake

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,15 @@ endif ()
133133

134134
## Check for non-standard extension quadmath.h
135135

136-
CHECK_INCLUDE_FILES(quadmath.h C_HAVE_QUADMATH)
137-
if (C_HAVE_QUADMATH)
138-
set(${HDF_PREFIX}_HAVE_QUADMATH_H 1)
136+
# gcc puts symbols like FLT128_DIG in quadmath.h instead of float.h, so
137+
# check for that. This is only used by the build system and doesn't need
138+
# to be exported to H5pubconf.h.
139+
CHECK_INCLUDE_FILES("quadmath.h" INCLUDE_QUADMATH_H)
140+
# Convert TRUE/FALSE to 0/1 for preprocessor values in test code, below
141+
if (${INCLUDE_QUADMATH_H})
142+
set(C_INCLUDE_QUADMATH_H 1)
139143
else ()
140-
set(${HDF_PREFIX}_HAVE_QUADMATH_H 0)
144+
set(C_INCLUDE_QUADMATH_H 0)
141145
endif ()
142146

143147
if (CYGWIN)
@@ -641,22 +645,38 @@ endif()
641645
#-----------------------------------------------------------------------------
642646

643647
if (HDF5_BUILD_FORTRAN)
644-
HDF_CHECK_TYPE_SIZE(__float128 _SIZEOF___FLOAT128)
645-
if (_SIZEOF___FLOAT128)
646-
set (${HDF_PREFIX}_HAVE_FLOAT128 1)
647-
set (${HDF_PREFIX}_SIZEOF___FLOAT128 ${_SIZEOF___FLOAT128})
648-
else ()
649-
set (${HDF_PREFIX}_HAVE_FLOAT128 0)
650-
set (${HDF_PREFIX}_SIZEOF___FLOAT128 0)
651-
endif ()
648+
# ----------------------------------------------------------------------
649+
# __float128 checks
650+
#
651+
# If __float128 exists and we can determine its precision, we will use
652+
# it in the Fortran interface. The checks for this require that the
653+
# precision be specified via a symbol named FLT128_DIG, which might be
654+
# found in quadmath.h.
655+
#
656+
# The checks here are based on the GNU __float128 extension type from
657+
# libquadmath, which is now part of gcc. Other compilers (clang, Intel)
658+
# also expose __float128 and/or __float128 may be an alias for some
659+
# other 128-bit floating point type.
660+
#
661+
# 128-bit floating-point math is usually handled in software and is thus
662+
# orders of magnitude slower than hardware-supported floating-point math.
663+
#
652664

653-
HDF_CHECK_TYPE_SIZE(_Quad _SIZEOF__QUAD)
654-
if (NOT _SIZEOF__QUAD)
655-
set (${HDF_PREFIX}_SIZEOF__QUAD 0)
665+
#-----------------------------------------------------------------------------
666+
# Is the __float128 type available?
667+
#-----------------------------------------------------------------------------
668+
HDF_FUNCTION_TEST (HAVE___FLOAT128)
669+
# Convert TRUE/FALSE to 0/1 for preprocessor values in test code, below
670+
if (${HAVE___FLOAT128})
671+
set(C_HAVE_FLOAT128 1)
656672
else ()
657-
set (${HDF_PREFIX}_SIZEOF__QUAD ${_SIZEOF__QUAD})
673+
set(C_HAVE_FLOAT128 0)
658674
endif ()
659675

676+
#-----------------------------------------------------------------------------
677+
# Get the max decimal precision in C, checking both long double and
678+
# __float128 (if available)
679+
#-----------------------------------------------------------------------------
660680
if (NOT CMAKE_CROSSCOMPILING)
661681
#-----------------------------------------------------------------------------
662682
# The provided CMake C macros don't provide a general compile/run function
@@ -677,7 +697,6 @@ if (HDF5_BUILD_FORTRAN)
677697
TRY_RUN (RUN_RESULT_VAR COMPILE_RESULT_VAR
678698
${CMAKE_BINARY_DIR}
679699
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler1.c
680-
COMPILE_DEFINITIONS "-D_SIZEOF___FLOAT128=${H5_SIZEOF___FLOAT128};-D_HAVE_QUADMATH_H=${H5_HAVE_QUADMATH_H}"
681700
COMPILE_OUTPUT_VARIABLE COMPILEOUT
682701
${_RUN_OUTPUT_VARIABLE} OUTPUT_VAR
683702
)
@@ -714,43 +733,42 @@ if (HDF5_BUILD_FORTRAN)
714733
"
715734
#include <float.h>\n\
716735
#include <stdio.h>\n\
717-
#define CHECK_FLOAT128 _SIZEOF___FLOAT128\n\
718-
#if CHECK_FLOAT128!=0\n\
719-
#if _HAVE_QUADMATH_H!=0\n\
720-
#include <quadmath.h>\n\
721-
#endif\n\
722-
#ifdef FLT128_DIG\n\
723-
#define C_FLT128_DIG FLT128_DIG\n\
724-
#else\n\
725-
#define C_FLT128_DIG 0\n\
726-
#endif\n\
736+
#if ${C_HAVE_FLOAT128}\n\
737+
# if ${C_INCLUDE_QUADMATH_H}\n\
738+
# include <quadmath.h>\n\
739+
# endif\n\
740+
# ifdef FLT128_DIG\n\
741+
# define C_FLT128_DIG FLT128_DIG\n\
742+
# else\n\
743+
# define C_FLT128_DIG 0\n\
744+
# endif\n\
727745
#else\n\
728-
#define C_FLT128_DIG 0\n\
746+
# define C_FLT128_DIG 0\n\
729747
#endif\n\
730-
#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L\n\
731748
#define C_LDBL_DIG DECIMAL_DIG\n\
732-
#else\n\
733-
#define C_LDBL_DIG LDBL_DIG\n\
734-
#endif\n\nint main(void) {\nprintf(\"\\%d\\\;\\%d\\\;\", C_LDBL_DIG, C_FLT128_DIG)\\\;\n\nreturn 0\\\;\n}\n
735-
"
749+
\n\
750+
int main(void) {\nprintf(\"\\%d\\\;\\%d\\\;\", C_LDBL_DIG, C_FLT128_DIG)\\\;\n\nreturn 0\\\;\n}\n
751+
"
736752
)
737753

738754
C_RUN ("maximum decimal precision for C" ${PROG_SRC} PROG_RES PROG_OUTPUT4)
739755
message (STATUS "Testing maximum decimal precision for C - ${PROG_OUTPUT4}")
740756

741-
# dnl The output from the above program will be:
742-
# dnl -- long double decimal precision -- __float128 decimal precision
757+
# The output from the above program will be:
758+
# -- long double decimal precision -- __float128 decimal precision
743759

744-
list (GET PROG_OUTPUT4 0 H5_LDBL_DIG)
745-
list (GET PROG_OUTPUT4 1 H5_FLT128_DIG)
760+
list (GET PROG_OUTPUT4 0 MY_LDBL_DIG)
761+
list (GET PROG_OUTPUT4 1 MY_FLT128_DIG)
746762

747-
if (${HDF_PREFIX}_SIZEOF___FLOAT128 EQUAL "0" OR FLT128_DIG EQUAL "0")
748-
set (${HDF_PREFIX}_HAVE_FLOAT128 0)
749-
set (${HDF_PREFIX}_SIZEOF___FLOAT128 0)
750-
set (_PAC_C_MAX_REAL_PRECISION ${H5_LDBL_DIG})
763+
# Set configure output and behavior
764+
if (${HAVE___FLOAT128} AND (${MY_FLT128_DIG} GREATER ${MY_LDBL_DIG}))
765+
set (${HDF_PREFIX}_HAVE_FLOAT128 1)
766+
set (_PAC_C_MAX_REAL_PRECISION ${MY_FLT128_DIG})
751767
else ()
752-
set (_PAC_C_MAX_REAL_PRECISION ${H5_FLT128_DIG})
768+
# No __float128 or the precision of __float128 <= that of long double
769+
set (_PAC_C_MAX_REAL_PRECISION ${MY_LDBL_DIG})
753770
endif ()
771+
754772
if (NOT ${_PAC_C_MAX_REAL_PRECISION})
755773
set (${HDF_PREFIX}_PAC_C_MAX_REAL_PRECISION 0)
756774
else ()

config/cmake/H5pubconf.h.in

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
/* Determine if _Float16 is available */
145145
#cmakedefine H5_HAVE__FLOAT16 @H5_HAVE__FLOAT16@
146146

147-
/* Determine if __float128 is available */
147+
/* Determine if __float128 will be used in the Fortran wrappers */
148148
#cmakedefine H5_HAVE_FLOAT128 @H5_HAVE_FLOAT128@
149149

150150
/* Define to 1 if you have the `flock' function. */
@@ -265,9 +265,6 @@
265265
/* Define to 1 if you have the <pwd.h> header file. */
266266
#cmakedefine H5_HAVE_PWD_H @H5_HAVE_PWD_H@
267267

268-
/* Define to 1 if you have the <quadmath.h> header file. */
269-
#cmakedefine H5_HAVE_QUADMATH_H @H5_HAVE_QUADMATH_H@
270-
271268
/* Define whether the Read-Only S3 virtual file driver (VFD) should be
272269
compiled */
273270
#cmakedefine H5_HAVE_ROS3_VFD @H5_HAVE_ROS3_VFD@
@@ -595,15 +592,9 @@
595592
/* The size of `unsigned', as computed by sizeof. */
596593
#cmakedefine H5_SIZEOF_UNSIGNED @H5_SIZEOF_UNSIGNED@
597594

598-
/* The size of `_Quad', as computed by sizeof. */
599-
#define H5_SIZEOF__QUAD @H5_SIZEOF__QUAD@
600-
601595
/* The size of `_Float16', as computed by sizeof. */
602596
#define H5_SIZEOF__FLOAT16 @H5_SIZEOF__FLOAT16@
603597

604-
/* The size of `__float128', as computed by sizeof. */
605-
#define H5_SIZEOF___FLOAT128 @H5_SIZEOF___FLOAT128@
606-
607598
/* Define if strict file format checks are enabled */
608599
#cmakedefine H5_STRICT_FORMAT_CHECKS @H5_STRICT_FORMAT_CHECKS@
609600

config/cmake/HDF5UseFortran.cmake

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,13 @@ set (PROG_SRC3
363363
"
364364
)
365365
FORTRAN_RUN ("SIZEOF NATIVE KINDs" ${PROG_SRC3} XX YY PAC_SIZEOF_NATIVE_KINDS_RESULT PROG_OUTPUT3)
366-
# dnl The output from the above program will be:
367-
# dnl -- LINE 1 -- sizeof INTEGER
368-
# dnl -- LINE 2 -- kind of INTEGER
369-
# dnl -- LINE 3 -- sizeof REAL
370-
# dnl -- LINE 4 -- kind of REAL
371-
# dnl -- LINE 5 -- sizeof DOUBLE PRECISION
372-
# dnl -- LINE 6 -- kind of DOUBLE PRECISION
366+
# The output from the above program will be:
367+
# -- LINE 1 -- sizeof INTEGER
368+
# -- LINE 2 -- kind of INTEGER
369+
# -- LINE 3 -- sizeof REAL
370+
# -- LINE 4 -- kind of REAL
371+
# -- LINE 5 -- sizeof DOUBLE PRECISION
372+
# -- LINE 6 -- kind of DOUBLE PRECISION
373373
#
374374
# Convert the string to a list of strings by replacing the carriage return with a semicolon
375375
string (REGEX REPLACE "[\r\n]+" ";" PROG_OUTPUT3 "${PROG_OUTPUT3}")
@@ -402,11 +402,10 @@ endif ()
402402

403403
set (${HDF_PREFIX}_FORTRAN_SIZEOF_LONG_DOUBLE ${${HDF_PREFIX}_SIZEOF_LONG_DOUBLE})
404404

405-
# remove the invalid kind from the list
406-
if (NOT(${${HDF_PREFIX}_SIZEOF___FLOAT128} EQUAL 0))
407-
if (NOT(${${HDF_PREFIX}_SIZEOF___FLOAT128} EQUAL ${max_real_fortran_sizeof})
408-
AND NOT(${${HDF_PREFIX}_FORTRAN_SIZEOF_LONG_DOUBLE} EQUAL ${max_real_fortran_sizeof})
409-
# account for the fact that the C compiler can have 16-byte __float128 and the fortran compiler only has 8-byte doubles,
405+
# Remove the invalid kind from the list
406+
if (${${HDF_PREFIX}_HAVE_FLOAT128})
407+
if (NOT(16 EQUAL ${max_real_fortran_sizeof}) AND NOT(${${HDF_PREFIX}_FORTRAN_SIZEOF_LONG_DOUBLE} EQUAL ${max_real_fortran_sizeof})
408+
# Account for the fact that the C compiler can have 16-byte __float128 and the fortran compiler only has 8-byte doubles,
410409
# so we don't want to remove the 8-byte fortran doubles.
411410
AND NOT(${PAC_FORTRAN_NATIVE_DOUBLE_SIZEOF} EQUAL ${max_real_fortran_sizeof}))
412411
message (WARNING "

config/cmake/HDFTests.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,18 @@
1515
/* A simple test program to see if a function "works" */
1616
#define SIMPLE_TEST(x) int main(void){ x; return 0; }
1717

18+
#ifdef HAVE___FLOAT128
19+
20+
/* Check if __float128 works (only used in the Fortran interface) */
21+
int
22+
main ()
23+
{
24+
__float128 x;
25+
26+
return 0;
27+
}
28+
29+
#endif /* HAVE___FLOAT128 */
1830

1931
#ifdef HAVE_BUILTIN_EXPECT
2032

configure.ac

Lines changed: 66 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -794,41 +794,87 @@ AC_MSG_RESULT([$HDF_FORTRAN])
794794

795795
if test "X$HDF_FORTRAN" = "Xyes"; then
796796

797-
## ----------------------------------------------------------------------
798-
## Check for non-standard extension __FLOAT128
799-
##
800-
HAVE_FLOAT128=0
801-
HAVE_QUADMATH=0
802-
FLT128_DIG=0
803-
LDBL_DIG=0
797+
## ----------------------------------------------------------------------
798+
## __float128 checks
799+
##
800+
## If __float128 exists and we can determine its precision, we will use
801+
## it in the Fortran interface. The checks for this require that the
802+
## precision be specified via a symbol named FLT128_DIG, which might be
803+
## found in quadmath.h.
804+
##
805+
## The checks here are based on the GNU __float128 extension type from
806+
## libquadmath, which is now part of gcc. Other compilers (clang, Intel)
807+
## also expose __float128 and/or __float128 may be an alias for some
808+
## other 128-bit floating point type.
809+
##
810+
## 128-bit floating-point math is usually handled in software and is thus
811+
## orders of magnitude slower than hardware-supported floating-point math.
812+
##
813+
AC_MSG_CHECKING([if __float128 exists])
814+
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]],[[__float128 x; return 0;]])],
815+
[HAVE___FLOAT128=1; AC_MSG_RESULT([yes])],
816+
[HAVE___FLOAT128=0; AC_MSG_RESULT([no])]
817+
)
818+
819+
## gcc puts symbols like FLT128_DIG in quadmath.h instead of float.h,
820+
## so check for that before running the precision macro. Note that
821+
## using AC_CHECK_HEADER instead of AC_CHECK_HEADERS keeps the
822+
## H5_HAVE_QUADMATH_H symbol out of the public config header.
823+
##
824+
AC_CHECK_HEADER([quadmath.h], [INCLUDE_QUADMATH_H=1], [INCLUDE_QUADMATH_H=0])
825+
826+
## ----------------------------------------------------------------------
827+
## Get the max decimal precision in C, checking both long double and
828+
## __float128 (if available)
829+
##
830+
AC_MSG_CHECKING([maximum decimal precision for C])
804831

805-
AC_CHECK_SIZEOF([__float128])
806-
AC_CHECK_SIZEOF([_Quad])
807-
AC_CHECK_HEADERS([quadmath.h], [HAVE_QUADMATH=1], [])
832+
MY_FLT128_DIG=0
833+
MY_LDBL_DIG=0
834+
835+
## Macro to compare long double and __float128 to see which has higher precision
808836
PAC_FC_LDBL_DIG
809837

838+
## Set results
839+
if test "$MY_FLT128_DIG" -gt "$MY_LDBL_DIG" ; then
840+
PAC_C_MAX_REAL_PRECISION=$MY_FLT128_DIG
841+
PRECISION_TYPE="(__float128)"
842+
else
843+
PAC_C_MAX_REAL_PRECISION=$MY_LDBL_DIG
844+
PRECISION_TYPE="(long double)"
845+
fi
846+
AC_MSG_RESULT([$PAC_C_MAX_REAL_PRECISION $PRECISION_TYPE])
847+
848+
## Store results in config file
810849
AC_SUBST([PAC_C_MAX_REAL_PRECISION])
850+
AC_DEFINE_UNQUOTED([PAC_C_MAX_REAL_PRECISION], $PAC_C_MAX_REAL_PRECISION, [Determine the maximum decimal precision in C])
851+
852+
## Are we going to use __float128?
853+
AC_MSG_CHECKING([if __float128 will be used in the Fortran wrappers])
811854

812-
if test "$ac_cv_sizeof___float128" != 0 && test "$FLT128_DIG" != 0 ; then
813-
AC_DEFINE([HAVE_FLOAT128], [1], [Determine if __float128 is available])
814-
PAC_C_MAX_REAL_PRECISION=$FLT128_DIG
855+
if test "$MY_FLT128_DIG" -gt "$MY_LDBL_DIG" ; then
856+
AC_MSG_RESULT([yes])
857+
AC_DEFINE([HAVE_FLOAT128], [1], [Determine if __float128 will be used in the Fortran wrappers])
815858
else
816-
PAC_C_MAX_REAL_PRECISION=$LDBL_DIG
859+
## Can't use __float128, but write an undef line anyway
860+
AC_MSG_RESULT([no])
861+
AH_TEMPLATE([HAVE_FLOAT128], [Determine if __float128 will be used in the Fortran wrappers])
817862
fi
818-
AC_DEFINE_UNQUOTED([PAC_C_MAX_REAL_PRECISION], $PAC_C_MAX_REAL_PRECISION, [Determine the maximum decimal precision in C])
819-
AC_MSG_RESULT([$PAC_C_MAX_REAL_PRECISION])
820863

864+
## ----------------------------------------------------------------------
865+
## Define interface version
866+
##
821867
VERS_MAJOR=`cat $srcdir/src/H5public.h | sed -n 's/^#define H5_VERS_MAJOR //p'`
822868
VERS_MINOR=`cat $srcdir/src/H5public.h | sed -n 's/^#define H5_VERS_MINOR //p'`
823869
VERS_RELEASE=`cat $srcdir/src/H5public.h | sed -n 's/^#define H5_VERS_RELEASE //p'`
824870
AC_DEFINE_UNQUOTED([VERS_MAJOR_TMP], $VERS_MAJOR, [Define major library version])
825871
AC_DEFINE_UNQUOTED([VERS_MINOR_TMP], $VERS_MINOR, [Define minor library version])
826872
AC_DEFINE_UNQUOTED([VERS_RELEASE_TMP], $VERS_RELEASE, [Define release library version])
827873

828-
## We will output an include file for Fortran, H5config_f.inc which
829-
## contains various configure definitions used by the Fortran Library.
830-
## Prepend H5_ to all macro names. This avoids name conflict between HDF5 macro
831-
## names and those generated by another software package that uses the HDF5 library.
874+
## We will output an include file for Fortran, H5config_f.inc which
875+
## contains various configure definitions used by the Fortran Library.
876+
## Prepend H5_ to all macro names. This avoids name conflict between HDF5 macro
877+
## names and those generated by another software package that uses the HDF5 library.
832878
AC_CONFIG_HEADERS([fortran/src/H5config_f.inc],
833879
[cat fortran/src/H5config_f.inc | sed '1d;s%^/\* \(.*\) \*/%\1%;s/#define /#define H5_/;s/#undef /#undef H5_/' >fortran/src/H5config_f.inc.tmp; sed -i 's\_TMP\\g' fortran/src/H5config_f.inc.tmp; mv -f fortran/src/H5config_f.inc.tmp fortran/src/H5config_f.inc])
834880

fortran/test/tH5T_F03.F90

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,10 +1090,8 @@ SUBROUTINE test_h5kind_to_type(total_error)
10901090
CALL check("H5Dcreate_f",error, total_error)
10911091
CALL H5Dcreate_f(file_id, dsetnamer8, h5kind_to_type(real_kind_15,H5_REAL_KIND), dspace_id, dset_idr8, error)
10921092
CALL check("H5Dcreate_f",error, total_error)
1093-
!#ifdef H5_HAVE_FLOAT128
10941093
CALL H5Dcreate_f(file_id, dsetnamer16, h5kind_to_type(real_kind_31,H5_REAL_KIND), dspace_id, dset_idr16, error)
10951094
CALL check("H5Dcreate_f",error, total_error)
1096-
!#endif
10971095
!
10981096
! Write the dataset.
10991097
!
@@ -1123,11 +1121,9 @@ SUBROUTINE test_h5kind_to_type(total_error)
11231121
f_ptr = C_LOC(dset_data_r15(1))
11241122
CALL h5dwrite_f(dset_idr8, h5kind_to_type(real_kind_15,H5_REAL_KIND), f_ptr, error)
11251123
CALL check("H5Dwrite_f",error, total_error)
1126-
!#ifdef H5_HAVE_FLOAT128
11271124
f_ptr = C_LOC(dset_data_r31(1))
11281125
CALL h5dwrite_f(dset_idr16, h5kind_to_type(real_kind_31,H5_REAL_KIND), f_ptr, error)
11291126
CALL check("H5Dwrite_f",error, total_error)
1130-
!#endif
11311127
!
11321128
! Close the file
11331129
!

0 commit comments

Comments
 (0)