Skip to content

Commit

Permalink
Final cleanup of CMake __float128 code
Browse files Browse the repository at this point in the history
  • Loading branch information
derobins committed Jul 14, 2024
1 parent 137c05e commit a485b4d
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 33 deletions.
60 changes: 42 additions & 18 deletions config/cmake/ConfigureChecks.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -644,15 +644,38 @@ endif()
#-----------------------------------------------------------------------------

if (HDF5_BUILD_FORTRAN)
HDF_CHECK_TYPE_SIZE(__float128 _SIZEOF___FLOAT128)
if (_SIZEOF___FLOAT128)
set (${HDF_PREFIX}_HAVE_FLOAT128 1)
set (${HDF_PREFIX}_SIZEOF___FLOAT128 ${_SIZEOF___FLOAT128})
# ----------------------------------------------------------------------
# __float128 checks
#
# If __float128 exists and we can determine its precision, we will use
# it in the Fortran interface. The checks for this require that the
# precision be specified via a symbol named FLT128_DIG, which might be
# found in quadmath.h.
#
# The checks here are based on the GNU __float128 extension type from
# libquadmath, which is now part of gcc. Other compilers (clang, Intel)
# also expose __float128 and/or __float128 may be an alias for some
# other 128-bit floating point type.
#
# 128-bit floating-point math is usually handled in software and is thus
# orders of magnitude slower than hardware-supported floating-point math.
#

#-----------------------------------------------------------------------------
# Is the __float128 type available?
#-----------------------------------------------------------------------------
HDF_FUNCTION_TEST (HAVE___FLOAT128)
# Convert TRUE/FALSE to 0/1 for preprocessor values in test code, below
if (${HAVE___FLOAT128})
set(C_HAVE_FLOAT128 1)
else ()
set (${HDF_PREFIX}_HAVE_FLOAT128 0)
set (${HDF_PREFIX}_SIZEOF___FLOAT128 0)
set(C_HAVE_FLOAT128 0)
endif ()

#-----------------------------------------------------------------------------
# Get the max decimal precision in C, checking both long double and
# __float128 (if available)
#-----------------------------------------------------------------------------
if (NOT CMAKE_CROSSCOMPILING)
#-----------------------------------------------------------------------------
# The provided CMake C macros don't provide a general compile/run function
Expand All @@ -673,7 +696,7 @@ if (HDF5_BUILD_FORTRAN)
TRY_RUN (RUN_RESULT_VAR COMPILE_RESULT_VAR
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testCCompiler1.c
COMPILE_DEFINITIONS "-D_SIZEOF___FLOAT128=${H5_SIZEOF___FLOAT128};-D_HAVE_QUADMATH_H=${H5_HAVE_QUADMATH_H}"
COMPILE_DEFINITIONS "-D_HAVE_QUADMATH_H=${H5_HAVE_QUADMATH_H}"
COMPILE_OUTPUT_VARIABLE COMPILEOUT
${_RUN_OUTPUT_VARIABLE} OUTPUT_VAR
)
Expand Down Expand Up @@ -710,8 +733,7 @@ if (HDF5_BUILD_FORTRAN)
"
#include <float.h>\n\
#include <stdio.h>\n\
#define CHECK_FLOAT128 _SIZEOF___FLOAT128\n\
#if CHECK_FLOAT128!=0\n\
#if ${C_HAVE_FLOAT128}\n\
# if ${INCLUDE_QUADMATH_H}!=0\n\
# include <quadmath.h>\n\
# endif\n\
Expand All @@ -732,19 +754,21 @@ int main(void) {\nprintf(\"\\%d\\\;\\%d\\\;\", C_LDBL_DIG, C_FLT128_DIG)\\\;\n\n
C_RUN ("maximum decimal precision for C" ${PROG_SRC} PROG_RES PROG_OUTPUT4)
message (STATUS "Testing maximum decimal precision for C - ${PROG_OUTPUT4}")

# dnl The output from the above program will be:
# dnl -- long double decimal precision -- __float128 decimal precision
# The output from the above program will be:
# -- long double decimal precision -- __float128 decimal precision

list (GET PROG_OUTPUT4 0 H5_LDBL_DIG)
list (GET PROG_OUTPUT4 1 H5_FLT128_DIG)
list (GET PROG_OUTPUT4 0 MY_LDBL_DIG)
list (GET PROG_OUTPUT4 1 MY_FLT128_DIG)

if (${HDF_PREFIX}_SIZEOF___FLOAT128 EQUAL "0" OR FLT128_DIG EQUAL "0")
set (${HDF_PREFIX}_HAVE_FLOAT128 0)
set (${HDF_PREFIX}_SIZEOF___FLOAT128 0)
set (_PAC_C_MAX_REAL_PRECISION ${H5_LDBL_DIG})
# Set configure output and behavior
if (${HAVE___FLOAT128} AND (${MY_FLT128_DIG} GREATER ${MY_LDBL_DIG}))
set (${HDF_PREFIX}_HAVE_FLOAT128 1)
set (_PAC_C_MAX_REAL_PRECISION ${MY_FLT128_DIG})
else ()
set (_PAC_C_MAX_REAL_PRECISION ${H5_FLT128_DIG})
# No __float128 or the precision of __float128 <= that of long double
set (_PAC_C_MAX_REAL_PRECISION ${MY_LDBL_DIG})
endif ()

if (NOT ${_PAC_C_MAX_REAL_PRECISION})
set (${HDF_PREFIX}_PAC_C_MAX_REAL_PRECISION 0)
else ()
Expand Down
3 changes: 0 additions & 3 deletions config/cmake/H5pubconf.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -586,9 +586,6 @@
/* The size of `_Float16', as computed by sizeof. */
#define H5_SIZEOF__FLOAT16 @H5_SIZEOF__FLOAT16@

/* The size of `__float128', as computed by sizeof. */
#define H5_SIZEOF___FLOAT128 @H5_SIZEOF___FLOAT128@

/* Define if strict file format checks are enabled */
#cmakedefine H5_STRICT_FORMAT_CHECKS @H5_STRICT_FORMAT_CHECKS@

Expand Down
23 changes: 11 additions & 12 deletions config/cmake/HDF5UseFortran.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -363,13 +363,13 @@ set (PROG_SRC3
"
)
FORTRAN_RUN ("SIZEOF NATIVE KINDs" ${PROG_SRC3} XX YY PAC_SIZEOF_NATIVE_KINDS_RESULT PROG_OUTPUT3)
# dnl The output from the above program will be:
# dnl -- LINE 1 -- sizeof INTEGER
# dnl -- LINE 2 -- kind of INTEGER
# dnl -- LINE 3 -- sizeof REAL
# dnl -- LINE 4 -- kind of REAL
# dnl -- LINE 5 -- sizeof DOUBLE PRECISION
# dnl -- LINE 6 -- kind of DOUBLE PRECISION
# The output from the above program will be:
# -- LINE 1 -- sizeof INTEGER
# -- LINE 2 -- kind of INTEGER
# -- LINE 3 -- sizeof REAL
# -- LINE 4 -- kind of REAL
# -- LINE 5 -- sizeof DOUBLE PRECISION
# -- LINE 6 -- kind of DOUBLE PRECISION
#
# Convert the string to a list of strings by replacing the carriage return with a semicolon
string (REGEX REPLACE "[\r\n]+" ";" PROG_OUTPUT3 "${PROG_OUTPUT3}")
Expand Down Expand Up @@ -402,11 +402,10 @@ endif ()

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

# remove the invalid kind from the list
if (NOT(${${HDF_PREFIX}_SIZEOF___FLOAT128} EQUAL 0))
if (NOT(${${HDF_PREFIX}_SIZEOF___FLOAT128} EQUAL ${max_real_fortran_sizeof})
AND NOT(${${HDF_PREFIX}_FORTRAN_SIZEOF_LONG_DOUBLE} EQUAL ${max_real_fortran_sizeof})
# account for the fact that the C compiler can have 16-byte __float128 and the fortran compiler only has 8-byte doubles,
# Remove the invalid kind from the list
if (${${HDF_PREFIX}_HAVE_FLOAT128})
if (NOT(16 EQUAL ${max_real_fortran_sizeof}) AND NOT(${${HDF_PREFIX}_FORTRAN_SIZEOF_LONG_DOUBLE} EQUAL ${max_real_fortran_sizeof})
# Account for the fact that the C compiler can have 16-byte __float128 and the fortran compiler only has 8-byte doubles,
# so we don't want to remove the 8-byte fortran doubles.
AND NOT(${PAC_FORTRAN_NATIVE_DOUBLE_SIZEOF} EQUAL ${max_real_fortran_sizeof}))
message (WARNING "
Expand Down
12 changes: 12 additions & 0 deletions config/cmake/HDFTests.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,18 @@
/* A simple test program to see if a function "works" */
#define SIMPLE_TEST(x) int main(void){ x; return 0; }

#ifdef HAVE___FLOAT128

/* Check if __float128 works (only used in the Fortran interface) */
int
main ()
{
__float128 x;

return 0;
}

#endif /* HAVE___FLOAT128 */

#ifdef HAVE_BUILTIN_EXPECT

Expand Down

0 comments on commit a485b4d

Please sign in to comment.