From 4e222bf5bb42a84378a89461fe28abd1874487c1 Mon Sep 17 00:00:00 2001 From: Allen Byrne <50328838+byrnHDF@users.noreply.github.com> Date: Mon, 18 Mar 2024 10:36:55 -0500 Subject: [PATCH 1/9] Add filter plugin user guide text. Fix registered URL in docs (#4169) --- doxygen/aliases | 1 - doxygen/dox/UsersGuide.dox | 2 + doxygen/examples/H5.format.1.1.html | 4 +- doxygen/examples/H5.format.2.0.html | 10 +- doxygen/examples/H5.format.html | 8 +- src/H5Dmodule.h | 83 +++++++-- src/H5PLmodule.h | 272 +++++++++++++++++++++++++--- src/H5Zmodule.h | 2 +- 8 files changed, 335 insertions(+), 47 deletions(-) diff --git a/doxygen/aliases b/doxygen/aliases index 4eb19621e74..ad868432bee 100644 --- a/doxygen/aliases +++ b/doxygen/aliases @@ -235,7 +235,6 @@ ALIASES += sa_metadata_ops="\sa \li H5Pget_all_coll_metadata_ops() \li H5Pget_co ################################################################################ ALIASES += ref_cons_semantics="Enabling a Strict Consistency Semantics Model in Parallel HDF5" -ALIASES += ref_dld_filters="HDF5 Dynamically Loaded Filters" ALIASES += ref_file_image_ops="HDF5 File Image Operations" ALIASES += ref_filter_pipe="Data Flow Pipeline for H5Dread()" ALIASES += ref_group_impls="Group implementations in HDF5" diff --git a/doxygen/dox/UsersGuide.dox b/doxygen/dox/UsersGuide.dox index 4f955e6074d..b6113ad15bd 100644 --- a/doxygen/dox/UsersGuide.dox +++ b/doxygen/dox/UsersGuide.dox @@ -134,6 +134,7 @@ HDF5 Release 1.14
  • \ref subsubsec_dataset_transfer_props
  • \ref subsubsec_dataset_transfer_store
  • \ref subsubsec_dataset_transfer_partial +
  • \ref subsubsec_dataset_transfer_dyn_filter \li \ref subsec_dataset_allocation \ref sec_datatype diff --git a/doxygen/examples/H5.format.1.1.html b/doxygen/examples/H5.format.1.1.html index f5e4c4e0fe5..f437d9be970 100644 --- a/doxygen/examples/H5.format.1.1.html +++ b/doxygen/examples/H5.format.1.1.html @@ -5436,8 +5436,8 @@

    Name: Data Storage - Filter Pipeline

    filters requested and supported by third parties. Filters supported by The HDF Group are documented immediately below. Information on 3rd-party filters can be found at - - https://support.hdfgroup.org/services/contributions.html#filters. + + https://portal.hdfgroup.org/documentation/hdf5-docs/registered_filter_plugins.html. 1

    To request a filter identifier, please contact diff --git a/doxygen/examples/H5.format.2.0.html b/doxygen/examples/H5.format.2.0.html index bde030f3853..37cb7282eb1 100644 --- a/doxygen/examples/H5.format.2.0.html +++ b/doxygen/examples/H5.format.2.0.html @@ -12598,9 +12598,8 @@

    HDF5 Library and for filters requested and supported by third parties. Filters supported by The HDF Group are documented immediately below. Information on 3rd-party filters can be found at - The HDF Group’s - Contributions page. + The HDF Group’s + Registered Filters page.

    @@ -12854,9 +12853,8 @@

    HDF5 Library and for filters requested and supported by third parties. Filters supported by The HDF Group are documented immediately below. Information on 3rd-party filters can be found at - The HDF Group’s - Contributions page. + The HDF Group’s + Registered Filters page.

    diff --git a/doxygen/examples/H5.format.html b/doxygen/examples/H5.format.html index 7aba5fed440..30bd37cf10f 100644 --- a/doxygen/examples/H5.format.html +++ b/doxygen/examples/H5.format.html @@ -14226,8 +14226,8 @@

    IV.A.2.l. The Data Storage - Filter Filters supported by The HDF Group are documented immediately below. Information on 3rd-party filters can be found at The HDF Group’s - - Contributions page.

    + + Registered Filters page.

    To request a filter identifier, please contact @@ -14488,8 +14488,8 @@

    IV.A.2.l. The Data Storage - Filter Filters supported by The HDF Group are documented immediately below. Information on 3rd-party filters can be found at The HDF Group’s - - Contributions page.

    + + Registered Filters page.

    To request a filter identifier, please contact diff --git a/src/H5Dmodule.h b/src/H5Dmodule.h index 81f197d7147..27e5799968e 100644 --- a/src/H5Dmodule.h +++ b/src/H5Dmodule.h @@ -815,19 +815,10 @@ * * * - * + * * * * - * - * - * - * - * - * - * - * * * * @@ -844,6 +835,19 @@ * * * + * + * + * + * + * + * + * + * + * + * + * + * * *
    Data pipeline filters
    FilterBuilt-in FilterDescription
    gzip compressionData compression using zlib.
    Szip compressionData compression using the Szip library. See The HDF Group website for more information - * regarding the Szip filter.
    N-bit compressionData compression using an algorithm specialized for n-bit datatypes.
    Fletcher32Fletcher32 checksum for error-detection.
    Optional Built-in FilterDescription
    gzip compressionData compression using zlib.
    szip compressionData compression using the szip library. The HDF Group now uses the libaec library for the szip +filter.
    * @@ -861,6 +865,44 @@ * \li @see @ref subsubsec_dataset_filters_nbit * \li @see @ref subsubsec_dataset_filters_scale * + * \subsubsection subsubsec_dataset_transfer_dyn_filter Data Pipeline Dynamically Loaded Filters + * While the HDF5 “internal” compression methods work reasonably well on users’ + * datasets, there are certain drawbacks to this implementation. First, the “internal” compression + * methods may not provide the optimal compression ratio, as do some newly developed or specialized + * compression methods. Secondly, if a data provider wants to use a “non-internal” compression for + * storing the data in HDF5, they have to write a filter function that uses the new compression method + * and then register it with the library. Data consumers of such HDF5 files will need to have the new filter + * function and use it with their applications to read the data, or they will need a modified version of the + * HDF5 Library that has the new filter as a part of the library. + * + * If a user of such data does not have a modified HDF5 Library installed on his system, command-line tools + * such as h5dump or h5ls will not be able to display the compressed data. Furthermore, it would be + * practically impossible to determine the compression method used, making the data stored in HDF5 + * useless. + * + * It is clear that the internal HDF5 filter mechanism, while extensible, does not work well with third-party + * filters. It would be a maintenance nightmare to keep adding and supporting new compression methods + * in HDF5. For any set of HDF5 “internal” filters, there always will be data with which the “internal” +filters + * will not achieve the optimal performance needed to address data I/O and storage problems. Thus the + * internal HDF5 filter mechanism is enhanced to address the issues discussed above. + * + * We have a feature of HDF5 called “dynamically loaded filters in HDF5.” This feature + * makes the HDF5 third-party filters available to an application at runtime. The third-party HDF5 filter + * function has to be a part of the HDF5 filter plugin installed on the system as a shared library or DLL. + * + * To use a third-party filter an HDF5 application should call the #H5Pset_filter function when setting the + * filter pipeline for a dataset creation property. The HDF5 Library will register the filter with the library + * and the filter will be applied when data is written to the file. + * + * When an application reads data compressed with a third-party HDF5 filter, the HDF5 Library will search + * for the required filter plugin, register the filter with the library (if the filter function is not +registered) and + * apply it to the data on the read operation. + * + * For more information, + * \li @see @ref sec_filter_plugins + * * \subsubsection subsubsec_dataset_transfer_drive File Drivers * I/O is performed by the HDF5 virtual file layer. The file driver interface writes and reads blocks * of data; each driver module implements the interface using different I/O mechanisms. The table @@ -2685,8 +2727,25 @@ allocated if necessary. * and minimum values, and they will get a much larger minimum-bits (poor compression) *

  • * - * \subsubsection subsubsec_dataset_filters_szip Using the Szip Filter - * See The HDF Group website for further information regarding the Szip filter. + * \subsubsection subsubsec_dataset_filters_szip Using the SZip Filter + * See The HDF Group website for further information regarding the SZip filter. + * + * \subsubsection subsubsec_dataset_filters_dyn Using Dynamically-Loadable Filters + * \see \ref sec_filter_plugins for further information regarding the dynamically-loadable filters. + * + * HDF has a filter plugin repository of useful third-party plugins that can used + * + * + * + * + * + * + * + * + * + * + * + *
    FilterSetFilter Params
    BLOSCUD=32001,0,0
    BSHUFUD=32004,0,0
    BZIP2UD=307,0,1,9
    JPEGUD=32019,0,4,q,c,r,t
    LZ4 UD=32004,0,1,3
    LZFUD=32000,1,3,0,0,0
    SZUD=32017,1,5,2,7,20,40,0
    ZFPUD=32013,1,0,0
    ZSTDUD=32015,0,0
    * * Previous Chapter \ref sec_group - Next Chapter \ref sec_datatype * diff --git a/src/H5PLmodule.h b/src/H5PLmodule.h index 37654869746..436e8bdfa0a 100644 --- a/src/H5PLmodule.h +++ b/src/H5PLmodule.h @@ -27,7 +27,257 @@ #define H5_MY_PKG_ERR H5E_PLUGIN /** \page H5PL_UG The HDF5 Plugins - * @todo Under Construction + * + * \section sec_filter_plugins HDF5 Filter Plugins + * + * \subsection subsec_filter_plugins_intro Introduction + * HDF5 supports compression of data using a stackable pipeline of filters which can be + * implemented for reading and writing datasets, both at runtime and post‐process. + * These filters are supported as dynamically loadable plugins, and users can even + * implement custom filters of their own design. + * + * \subsection subsec_filter_plugins_model Programming Model for Applications + * This section describes the programming model for an application that uses a third-party HDF5 filter + * plugin to write or read data. For simplicity of presentation, it is assumed that the HDF5 filter plugin is + * available on the system in a default location. The HDF5 filter plugin is discussed in detail in the + * \ref subsec_filter_plugins_prog section. + * + * \subsubsection subsubsec_filter_plugins_model_apply Applying a Third-party Filter When Creating and Writing + * a Dataset A third-party filter can be added to the HDF5 filter pipeline by using the H5Pset_filter + * function, as a user would do in the past. The identification number and the filter parameters should be + * available to the application. For example, if the application intends to apply the HDF5 bzip2 compression + * filter that was registered with The HDF Group and has an identification number 307 + * (Registered + * Filters) then the application would follow the steps as outlined below: \code dcpl = H5Pcreate + * (H5P_DATASET_CREATE); status = H5Pset_filter (dcpl, (H5Z_filter_t)307, H5Z_FLAG_MANDATORY, (size_t)6, + * cd_values); dset = H5Dcreate (file, DATASET, H5T_STD_I32LE, space, H5P_DEFAULT, dcpl, status = H5Dwrite + * (dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata[0]); \endcode + * + * \subsubsection subsubsec_filter_plugins_model_read Reading Data with an Applied Third-party Filter + * An application does not need to do anything special to read the data with a third-party filter applied. For + * example, if one wants to read data written in the previous example, the following regular steps should be + * taken: \code file = H5Fopen (FILE, H5F_ACC_RDONLY, H5P_DEFAULT); dset = H5Dopen (file, DATASET, + * H5P_DEFAULT); H5Dread (dset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata[0]); \endcode + * + * The command-line utility h5dump, for example, will read and display the data as shown: + * \code + * HDF5 "h5ex_d_bzip2.h5" { + * GROUP "/" { + * DATASET "DS1" { + * DATATYPE H5T_STD_I32LE + * DATASPACE SIMPLE { ( 32, 64 ) / ( 32, 64 ) } + * STORAGE_LAYOUT { + * CHUNKED ( 4, 8 ) + * SIZE 6410 (1.278:1 COMPRESSION) + * } + * FILTERS { + * USER_DEFINED_FILTER { + * FILTER_ID 307 + * COMMENT HDF5 bzip2 filter; see http://www.hdfgroup.org/services/contributions.html + * PARAMS { 2 } + * } + * } + * FILLVALUE { + * FILL_TIME H5D_FILL_TIME_IFSET + * VALUE H5D_FILL_VALUE_DEFAULT + * } + * ALLOCATION_TIME { + * H5D_ALLOC_TIME_INCR + * } + * DATA { + * ... + * } + * } + * } + * } + * \endcode + * + * If the filter can not be loaded then h5dump will show the following: + * \code + * ... + * } + * DATA {h5dump error: unable to print data + * } + * ... + * \endcode + * + * \subsubsection subsubsec_filter_plugins_model_custom A Word of Caution When Using Custom Filters + * Data goes through the HDF5 filter pipeline only when it is written to the file or read into application + * memory space from the file. For example, the I/O operation is triggered with a call to #H5Fflush, or when + * a data item (HDF5 metadata or a raw data chunk) is evicted from the cache or brought into the cache. + * Please notice that #H5Dread/#H5Dwrite calls on the chunked datasets do not necessarily trigger I/O since + * the HDF5 Library uses a separate chunk cache. + * + * A data item may remain in the cache until the HDF5 Library is closed. If the HDF5 plugin that has to be + * applied to the data item becomes unavailable before the file and all objects in the file are closed, an + * error will occur. The following example demonstrates the issue. Please notice the position of the + * #H5Zunregister call: + * + * \code + * // Create a new group using compression. + * gcpl = H5Pcreate (H5P_GROUP_CREATE); + * status = H5Pset_filter(gcpl,H5Z_FILTER_BZIP2,H5Z_FLAG_MANDATORY,(size_t)1, cd_values); + * group = H5Gcreate (file, GNAME, H5P_DEFAULT, gcpl, H5P_DEFAULT); + * for (i=0; i < NGROUPS; i++) { + * sprintf(name, "group_%d", i); + * tmp_id = H5Gcreate (group, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * status = H5Gclose(tmp_id); + * } + * + * status = H5Pclose (gcpl); + * status = H5Gclose (group); + * + * // Unregister the filter. Call to H5Fclose will fail because the library tries + * // to apply the filter that is not available anymore. This has a cascade effect + * // on H5Fclose. + * H5Zunregister(H5Z_FILTER_BZIP2); + * status = H5Fclose (file); + * \endcode + * + * Here is an error stack produced by the program: + * \code + * HDF5-DIAG: Error detected in HDF5 (xx.yy.zz) thread 0: + * #000: H5F.c line **** in H5Fclose(): decrementing file ID failed + * major: Object atom + * minor: Unable to close file + * #001: H5I.c line **** in H5I_dec_app_ref(): can't decrement ID ref count + * major: Object atom + * minor: Unable to decrement reference count + * #002: H5F.c line **** in H5F_close(): can't close file + * major: File accessibility + * minor: Unable to close file + * ... + * #026: H5Z.c line **** in H5Z_find(): required filter is not registered + * major: Data filters + * minor: Object not found + * \endcode + * + * To avoid the problem make sure to close all objects to which the filter is applied and flush them using + * the H5Fflush call before unregistering the filter. + * + * \subsection subsec_filter_plugins_prog Programming Model for HDF5 Filter Plugins + * This section describes how to create an HDF5 filter, an HDF5 filter plugin, and how to install the HDF5 + * plugin on the system. + * + * \subsubsection subsubsec_filter_plugins_prog_write Writing a Filter Function + * The HDF5 filter function for the dynamically loaded filter feature should be written as any custom filter + * described in Custom Filters. See the + * “Example” section, section 5, of that document to get an idea of the simple filter function, and see the + * example of the more sophisticated HDF5 bzip2 filter function in the “Building an HDF5 bzip2 Plugin Example” + * section. The HDF5 bzip2 filter function is also available for download from Filter Plugin Repository. + * + * The user has to remember a few things when writing an HDF5 filter function. + * + * + * The signature of the HDF5 filter function and the accompanying filter structure (see the section below) + * are described in the HDF5 Reference Manual #H5Z_filter_t. + * + * \subsubsection subsubsec_filter_plugins_prog_reg Registering a Filter with The HDF Group + * If you are writing a filter that will be used by others, it would be a good idea to request a filter + * identification number and register it with The HDF Group. Please follow the procedure described at + * Registered + * Filters. + * + * The HDF Group anticipates that developers of HDF5 filter plugins will not only register new filters, but + * will also provide links to the source code and/or binaries for the corresponding HDF5 filter plugins. + * + * It is very important for the users of the filter that developers provide filter information in the “name” + * field of the filter structure, for example: + * \code + * const H5Z_class2_t H5Z_BZIP2[1] = {{ + * H5Z_CLASS_T_VERS, // H5Z_class_t version + * (H5Z_filter_t)H5Z_FILTER_BZIP2, // Filter id number + * 1, // encoder_present flag (set to true) + * 1, // decoder_present flag (set to true) + * "HDF5 bzip2 filter; see http://www.hdfgroup.org/services/contributions.html", + * // Filter name for debugging + * NULL, // The "can apply" callback + * NULL, // The "set local" callback + * (H5Z_func_t)H5Z_filter_bzip2, // The actual filter function + * }}; + * \endcode + * + * The HDF5 Library and command-line tools have access to the “name” field. An application can + * use the H5Pget_filter<*> functions to retrieve information about the filters. + * + * Using the example of the structure above, the h5dump tool will print the string “HDF5 bzip2 + * filter found at …” pointing users to the applied filter (see the example in the \ref + * subsubsec_filter_plugins_model_read section) thus solving the problem of the filter’s origin. + * + * \subsubsection subsubsec_filter_plugins_prog_create Creating an HDF5 Filter Plugin + * The HDF5 filter plugin source should include: + * + * Build the HDF5 filter plugin as a shared library. The following steps should be taken: + * + * + * \subsubsection subsubsec_filter_plugins_prog_install Installing an HDF5 Filter Plugin + * The default directory for an HDF5 filter plugin library is defined on UNIX-like systems as + * \code + * “/usr/local/hdf5/lib/plugin” + * \endcode + * and on Windows systems as + * \code + * "%ALLUSERSPROFILE%/hdf5/lib/plugin". + * \endcode + * + * The default path can be overwritten by a user with the #HDF5_PLUGIN_PATH environment variable. + * Several directories can be specified for the search path using “:” as a path separator for UNIX-like + * systems and “;” for Windows. + * + * Readers are encouraged to try the example in the “Building an HDF5 bzip2 Plugin Example” section. + * + * \subsection subsec_filter_plugins_design Design + * Dynamic loading of the HDF5 filter plugin (or filter library) is triggered only by two events: when an + * application calls the #H5Pset_filter function to set the filter for the first time, or when the data to + * which the filter is applied is read for the first time. + * + * \subsection subsec_filter_plugins_build Building an HDF5 bzip2 Plugin Example + * The HDF Group provides an repository of the HDF5 filter plugin that can be checked out from + * BZIP2 Filter Plugin. + * + * It contains the source code for the bzip2 + * plugin library and an example that uses the plugin. It requires the HDF5 Library with the dynamically + * loaded feature and the bzip2 library being available on the system. + * The plugin and the example can be built using configure or CMake commands. For instructions on how + * to build with CMake, see the README.txt file in the source code distribution. The bzip2 library that can + * be built with CMake is available from: + * \code + * GIT_URL: "https://github.com/libarchive/bzip2.git" + * GIT_BRANCH: "master" + * \endcode + * + * See the documentation at + * hdf5_plugins/docs folder In + * particular: + * INSTALL_With_CMake + * USING_HDF5_AND_CMake */ /** @@ -36,26 +286,6 @@ * Use the functions in this module to manage the loading behavior of HDF5 * plugins. * - * - * - * - * - * - * - * - * - * - * - *
    CreateRead
    - * \snippet H5PL_examples.c create - * - * \snippet H5PL_examples.c read - *
    UpdateDelete
    - * \snippet H5PL_examples.c update - * - * \snippet H5PL_examples.c delete - *
    - * * \attention The loading behavior of HDF5 plugins can be controlled via the * functions described below and certain environment variables, such * as \c HDF5_PLUGIN_PRELOAD and \c HDF5_PLUGIN_PATH. diff --git a/src/H5Zmodule.h b/src/H5Zmodule.h index 8b1a0dedc4e..c7f8300fb7c 100644 --- a/src/H5Zmodule.h +++ b/src/H5Zmodule.h @@ -102,7 +102,7 @@ * Custom filters that have been registered with the library will have * additional unique identifiers. * - * See \ref_dld_filters for more information on how an HDF5 application can + * See \ref sec_filter_plugins for more information on how an HDF5 application can * apply a filter that is not registered with the HDF5 library. * * \defgroup H5ZPRE Predefined Filters From 330b80a2665bee74d987491622c4023ef1ab8343 Mon Sep 17 00:00:00 2001 From: jhendersonHDF Date: Mon, 18 Mar 2024 23:36:46 -0500 Subject: [PATCH 2/9] Add support for _Float16 16-bit floating point type (#4065) Fixed some conversion issues with Clang due to problematic undefined behavior when casting a negative floating-point value to an integer Fixed a bug in the library's software integer to floating-point conversion function where a user's conversion exception function returning H5T_CONV_UNHANDLED in the case of overflows would result in incorrect data after conversion Added configure checks for functions and macros related to _Float16 usage since some compilers expose the datatype but not the functions or macros Fixed a dt_arith test failure when H5_WANT_DCONV_EXCEPTION isn't defined Fixed a few warnings from not explicitly casting some _Float16 variables upwards --- config/cmake/ConfigureChecks.cmake | 83 +- config/cmake/ConversionTests.c | 122 ++ config/cmake/H5pubconf.h.in | 12 + configure.ac | 103 ++ doxygen/dox/DDLBNF112.dox | 2 +- doxygen/dox/DDLBNF114.dox | 654 ++++++++++ doxygen/dox/IntroHDF5.dox | 2 +- doxygen/dox/LearnBasics1.dox | 4 +- doxygen/dox/LearnBasics2.dox | 5 + doxygen/dox/Specifications.dox | 1 + .../examples/tables/predefinedDatatypes.dox | 12 + hl/src/H5LT.c | 13 +- hl/src/H5LTanalyze.c | 456 +++---- hl/src/H5LTanalyze.l | 3 + hl/src/H5LTparse.c | 789 ++++++------ hl/src/H5LTparse.h | 63 +- hl/src/H5LTparse.y | 8 +- java/src/hdf/hdf5lib/HDF5Constants.java | 12 + java/src/jni/h5Constants.c | 15 + java/src/jni/h5util.c | 8 +- release_docs/RELEASE.txt | 119 ++ src/H5Fmodule.h | 2 +- src/H5Gmodule.h | 2 +- src/H5T.c | 570 ++++++--- src/H5Tconv.c | 435 ++++++- src/H5Tinit_float.c | 48 +- src/H5Tmodule.h | 19 +- src/H5Tnative.c | 28 +- src/H5Tpkg.h | 96 ++ src/H5Tpublic.h | 19 + src/H5private.h | 38 +- src/H5trace.c | 8 + test/API/H5_api_dataset_test.c | 10 +- test/API/H5_api_test_util.c | 14 +- test/dt_arith.c | 1062 +++++++++++++++-- test/dtypes.c | 425 ++++++- test/ntypes.c | 121 ++ tools/lib/h5diff_array.c | 265 +++- tools/lib/h5diff_util.c | 10 +- tools/lib/h5tools_dump.c | 10 +- tools/lib/h5tools_str.c | 12 +- tools/lib/h5tools_type.c | 8 +- tools/src/h5import/h5import.c | 108 ++ tools/src/h5ls/h5ls.c | 13 +- tools/test/h5dump/CMakeTests.cmake | 8 + tools/test/h5dump/CMakeTestsXML.cmake | 8 + tools/test/h5dump/expected/tfloat16.ddl | 46 + tools/test/h5dump/expected/tfloat16_be.ddl | 46 + .../test/h5dump/expected/xml/tfloat16.h5.xml | 302 +++++ .../h5dump/expected/xml/tfloat16_be.h5.xml | 302 +++++ tools/test/h5dump/h5dumpgentest.c | 163 +++ tools/test/h5dump/testfiles/tfloat16.h5 | Bin 0 -> 2304 bytes tools/test/h5dump/testfiles/tfloat16_be.h5 | Bin 0 -> 2304 bytes tools/test/h5dump/testh5dump.sh.in | 8 + tools/test/h5dump/testh5dumpxml.sh.in | 8 + tools/test/h5ls/CMakeTests.cmake | 33 + tools/test/h5ls/expected/tfloat16.ls | 8 + tools/test/h5ls/expected/tfloat16_be.ls | 8 + .../h5ls/expected/tfloat16_be_nosupport.ls | 8 + .../test/h5ls/expected/tfloat16_nosupport.ls | 8 + tools/test/h5ls/testh5ls.sh.in | 22 +- 61 files changed, 5765 insertions(+), 1022 deletions(-) create mode 100644 doxygen/dox/DDLBNF114.dox create mode 100644 tools/test/h5dump/expected/tfloat16.ddl create mode 100644 tools/test/h5dump/expected/tfloat16_be.ddl create mode 100644 tools/test/h5dump/expected/xml/tfloat16.h5.xml create mode 100644 tools/test/h5dump/expected/xml/tfloat16_be.h5.xml create mode 100644 tools/test/h5dump/testfiles/tfloat16.h5 create mode 100644 tools/test/h5dump/testfiles/tfloat16_be.h5 create mode 100644 tools/test/h5ls/expected/tfloat16.ls create mode 100644 tools/test/h5ls/expected/tfloat16_be.ls create mode 100644 tools/test/h5ls/expected/tfloat16_be_nosupport.ls create mode 100644 tools/test/h5ls/expected/tfloat16_nosupport.ls diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake index 2905fe9ad08..a3eb80e6beb 100644 --- a/config/cmake/ConfigureChecks.cmake +++ b/config/cmake/ConfigureChecks.cmake @@ -808,7 +808,8 @@ macro (H5ConversionTests TEST def msg) ${CMAKE_BINARY_DIR} ${HDF_RESOURCES_DIR}/ConversionTests.c CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=-D${TEST}_TEST - OUTPUT_VARIABLE OUTPUT + COMPILE_OUTPUT_VARIABLE ${TEST}_COMPILE_OUTPUT + RUN_OUTPUT_VARIABLE ${TEST}_RUN_OUTPUT ) if (${TEST}_COMPILE) if (${TEST}_RUN EQUAL "0") @@ -818,14 +819,17 @@ macro (H5ConversionTests TEST def msg) set (${TEST} "" CACHE INTERNAL ${msg}) message (VERBOSE "${msg}... no") file (APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log - "Test ${TEST} Run failed with the following output and exit code:\n ${OUTPUT}\n" + "Test ${TEST} Compile succeeded with the following output:\n ${${TEST}_COMPILE_OUTPUT}\n" + ) + file (APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log + "Test ${TEST} Run failed with exit code ${${TEST}_RUN} and with the following output:\n ${${TEST}_RUN_OUTPUT}\n" ) endif () else () set (${TEST} "" CACHE INTERNAL ${msg}) message (VERBOSE "${msg}... no") file (APPEND ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log - "Test ${TEST} Compile failed with the following output:\n ${OUTPUT}\n" + "Test ${TEST} Compile failed with the following output:\n ${${TEST}_COMPILE_OUTPUT}\n" ) endif () else () @@ -887,3 +891,76 @@ H5ConversionTests (${HDF_PREFIX}_LLONG_TO_LDOUBLE_CORRECT TRUE "Checking IF corr # some long double values #----------------------------------------------------------------------------- H5ConversionTests (${HDF_PREFIX}_DISABLE_SOME_LDOUBLE_CONV FALSE "Checking IF the cpu is power9 and cannot correctly converting long double values") + +#----------------------------------------------------------------------------- +# Check if _Float16 type is available +#----------------------------------------------------------------------------- +message (STATUS "Checking if _Float16 support is available") +set (${HDF_PREFIX}_HAVE__FLOAT16 0) +HDF_CHECK_TYPE_SIZE (_Float16 ${HDF_PREFIX}_SIZEOF__FLOAT16) +if (${HDF_PREFIX}_SIZEOF__FLOAT16) + # Request _Float16 support + set (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} "-D__STDC_WANT_IEC_60559_TYPES_EXT__") + + # Some compilers expose the _Float16 datatype, but not the macros and + # functions used with the datatype. We need the macros for proper + # datatype conversion support. Check for these here. + CHECK_SYMBOL_EXISTS (FLT16_EPSILON "float.h" h5_have_flt16_epsilon) + CHECK_SYMBOL_EXISTS (FLT16_MIN "float.h" h5_have_flt16_min) + CHECK_SYMBOL_EXISTS (FLT16_MAX "float.h" h5_have_flt16_max) + CHECK_SYMBOL_EXISTS (FLT16_MIN_10_EXP "float.h" h5_have_flt16_min_10_exp) + CHECK_SYMBOL_EXISTS (FLT16_MAX_10_EXP "float.h" h5_have_flt16_max_10_exp) + CHECK_SYMBOL_EXISTS (FLT16_MANT_DIG "float.h" h5_have_flt16_mant_dig) + + if (h5_have_flt16_epsilon AND h5_have_flt16_min AND + h5_have_flt16_max AND h5_have_flt16_min_10_exp AND + h5_have_flt16_max_10_exp AND h5_have_flt16_mant_dig) + # Some compilers like OneAPI on Windows appear to detect _Float16 support + # properly up to this point, and, in the absence of any architecture-specific + # tuning compiler flags, will generate code for H5Tconv.c that performs + # software conversions on _Float16 variables with compiler-internal functions + # such as __extendhfsf2, __truncsfhf2, or __truncdfhf2. However, these + # compilers will fail to link these functions into the build for currently + # unknown reasons and cause the build to fail. Since these are compiler-internal + # functions that we don't appear to have much control over, let's try to + # compile a program that will generate these functions to check for _Float16 + # support. If we fail to compile this program, we will simply disable + # _Float16 support for the time being. + H5ConversionTests ( + ${HDF_PREFIX}_FLOAT16_CONVERSION_FUNCS_LINK + FALSE + "Checking if compiler can convert _Float16 type with casts" + ) + + if (${${HDF_PREFIX}_FLOAT16_CONVERSION_FUNCS_LINK}) + # Finally, MacOS 13 appears to have a bug specifically when converting + # long double values to _Float16. Release builds of the dt_arith test + # would cause any assignments to a _Float16 variable to be elided, + # whereas Debug builds would perform incorrect hardware conversions by + # simply chopping off all the bytes of the value except for the first 2. + # These tests pass on MacOS 14, so let's perform a quick test to check + # if the hardware conversion is done correctly. + H5ConversionTests ( + ${HDF_PREFIX}_LDOUBLE_TO_FLOAT16_CORRECT + TRUE + "Checking if correctly converting long double to _Float16 values" + ) + + if (NOT ${${HDF_PREFIX}_LDOUBLE_TO_FLOAT16_CORRECT}) + message (VERBOSE "Conversions from long double to _Float16 appear to be incorrect. These will be emulated through a soft conversion function.") + endif () + + set (${HDF_PREFIX}_HAVE__FLOAT16 1) + + # Check if we can use fabsf16 + CHECK_FUNCTION_EXISTS (fabsf16 ${HDF_PREFIX}_HAVE_FABSF16) + else () + message (STATUS "_Float16 support has been disabled because the compiler couldn't compile and run a test program for _Float16 conversions") + message (STATUS "Check ${CMAKE_BINARY_DIR}/CMakeFiles/CMakeError.log for information on why the test program couldn't be compiled/run") + endif () + else () + message (STATUS "_Float16 support has been disabled since the required macros (FLT16_MAX, FLT16_EPSILON, etc. were not found)") + endif () +else () + message (STATUS "_Float16 support has been disabled since the _Float16 type was not found") +endif () diff --git a/config/cmake/ConversionTests.c b/config/cmake/ConversionTests.c index 725f0496f01..8e103bd3e97 100644 --- a/config/cmake/ConversionTests.c +++ b/config/cmake/ConversionTests.c @@ -285,3 +285,125 @@ int HDF_NO_UBSAN main(void) } #endif + +#ifdef H5_FLOAT16_CONVERSION_FUNCS_LINK_TEST + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ + +#include +#include + +int HDF_NO_UBSAN main(void) +{ + _Float16 fl16_var; + signed char sc; + unsigned char usc; + short s; + unsigned short us; + int i; + unsigned int ui; + long l; + unsigned long ul; + long long ll; + unsigned long long ull; + float f; + double d; + long double ld; + int ret = 0; + + /* + * Cast the _Float16 type between all the different C datatypes + * we support conversions for in H5Tconv.c to check if the compiler + * properly links any software conversion functions it may generate + * for the casts, such as __extendhfsf2 or __truncdfhf2. + */ + + fl16_var = 3.0f16; + + sc = (signed char)fl16_var; + usc = (unsigned char)fl16_var; + s = (short)fl16_var; + us = (unsigned short)fl16_var; + i = (int)fl16_var; + ui = (unsigned int)fl16_var; + l = (long)fl16_var; + ul = (unsigned long)fl16_var; + ll = (long long)fl16_var; + ull = (unsigned long long)fl16_var; + f = (float)fl16_var; + d = (double)fl16_var; + ld = (long double)fl16_var; + + sc = (signed char)3; + fl16_var = (_Float16)sc; + + usc = (unsigned char)3; + fl16_var = (_Float16)usc; + + s = (short)3; + fl16_var = (_Float16)s; + + us = (unsigned short)3; + fl16_var = (_Float16)us; + + i = (int)3; + fl16_var = (_Float16)i; + + ui = (unsigned int)3; + fl16_var = (_Float16)ui; + + l = (long)3; + fl16_var = (_Float16)l; + + ul = (unsigned long)3; + fl16_var = (_Float16)ul; + + ll = (long long)3; + fl16_var = (_Float16)ll; + + ull = (unsigned long long)3; + fl16_var = (_Float16)ull; + + f = (float)3.0f; + fl16_var = (_Float16)f; + + d = (double)3.0; + fl16_var = (_Float16)d; + + ld = (long double)3.0l; + fl16_var = (_Float16)ld; + +done: + exit(ret); +} + +#endif + +#ifdef H5_LDOUBLE_TO_FLOAT16_CORRECT_TEST + +#define __STDC_WANT_IEC_60559_TYPES_EXT__ + +#include +#include +#include +#include + +int HDF_NO_UBSAN main(void) +{ + long double ld; + _Float16 half; + int ret = 1; + + ld = 32.0L; + half = 64.0f16; + + half = (_Float16)ld; + + if (fabsl(ld - (long double)half) < LDBL_EPSILON) + ret = 0; + +done: + exit(ret); +} + +#endif diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index 8d866ec89a5..af8948d9f6e 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -131,6 +131,9 @@ /* Define if library information should be embedded in the executables */ #cmakedefine H5_HAVE_EMBEDDED_LIBINFO @H5_HAVE_EMBEDDED_LIBINFO@ +/* Define to 1 if you have the `fabsf16' function. */ +#cmakedefine H5_HAVE_FABSF16 @H5_HAVE_FABSF16@ + /* Define to 1 if you have the `fcntl' function. */ #cmakedefine H5_HAVE_FCNTL @H5_HAVE_FCNTL@ @@ -143,6 +146,9 @@ /* Define if support for szip filter is enabled */ #cmakedefine H5_HAVE_FILTER_SZIP @H5_HAVE_FILTER_SZIP@ +/* Determine if _Float16 is available */ +#cmakedefine H5_HAVE__FLOAT16 @H5_HAVE__FLOAT16@ + /* Determine if __float128 is available */ #cmakedefine H5_HAVE_FLOAT128 @H5_HAVE_FLOAT128@ @@ -384,6 +390,9 @@ /* Define if new-style references should be used with dimension scales */ #cmakedefine H5_DIMENSION_SCALES_WITH_NEW_REF @H5_DIMENSION_SCALES_WITH_NEW_REF@ +/* Define if your system can convert long double to _Float16 values correctly. */ +#cmakedefine H5_LDOUBLE_TO_FLOAT16_CORRECT @H5_LDOUBLE_TO_FLOAT16_CORRECT@ + /* Define if your system can convert long double to (unsigned) long long values correctly. */ #cmakedefine H5_LDOUBLE_TO_LLONG_ACCURATE @H5_LDOUBLE_TO_LLONG_ACCURATE@ @@ -586,6 +595,9 @@ /* The size of `_Quad', as computed by sizeof. */ #define H5_SIZEOF__QUAD @H5_SIZEOF__QUAD@ +/* 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@ diff --git a/configure.ac b/configure.ac index b76f18ff29f..f33fb8b87b9 100644 --- a/configure.ac +++ b/configure.ac @@ -559,6 +559,109 @@ AC_CHECK_SIZEOF([float]) AC_CHECK_SIZEOF([double]) AC_CHECK_SIZEOF([long double]) +## ---------------------------------------------------------------------- +## Check if _Float16 support is available +## +AC_MSG_NOTICE([checking if _Float16 support is available]) +HAVE__FLOAT16="no" +AC_CHECK_SIZEOF([_Float16]) +if test "$ac_cv_sizeof__Float16" != 0; then + # Some compilers expose the _Float16 datatype, but not the macros and + # functions used with the datatype. We need the macros for proper + # datatype conversion support. Check for these here. + AC_CHECK_DECL([FLT16_EPSILON], [], [], [[ + #define __STDC_WANT_IEC_60559_TYPES_EXT__ + #include ]]) + AC_CHECK_DECL([FLT16_MIN], [], [], [[ + #define __STDC_WANT_IEC_60559_TYPES_EXT__ + #include ]]) + AC_CHECK_DECL([FLT16_MAX], [], [], [[ + #define __STDC_WANT_IEC_60559_TYPES_EXT__ + #include ]]) + AC_CHECK_DECL([FLT16_MIN_10_EXP], [], [], [[ + #define __STDC_WANT_IEC_60559_TYPES_EXT__ + #include ]]) + AC_CHECK_DECL([FLT16_MAX_10_EXP], [], [], [[ + #define __STDC_WANT_IEC_60559_TYPES_EXT__ + #include ]]) + AC_CHECK_DECL([FLT16_MANT_DIG], [], [], [[ + #define __STDC_WANT_IEC_60559_TYPES_EXT__ + #include ]]) + + if test "X$ac_cv_have_decl_FLT16_EPSILON" = "Xyes" && + test "X$ac_cv_have_decl_FLT16_MIN" = "Xyes" && + test "X$ac_cv_have_decl_FLT16_MAX" = "Xyes" && + test "X$ac_cv_have_decl_FLT16_MIN_10_EXP" = "Xyes" && + test "X$ac_cv_have_decl_FLT16_MAX_10_EXP" = "Xyes" && + test "X$ac_cv_have_decl_FLT16_MANT_DIG" = "Xyes" ; then + # Some compilers like OneAPI on Windows appear to detect _Float16 support + # properly up to this point, and, in the absence of any architecture-specific + # tuning compiler flags, will generate code for H5Tconv.c that performs + # software conversions on _Float16 variables with compiler-internal functions + # such as __extendhfsf2, __truncsfhf2, or __truncdfhf2. However, these + # compilers will fail to link these functions into the build for currently + # unknown reasons and cause the build to fail. Since these are compiler-internal + # functions that we don't appear to have much control over, let's try to + # compile a program that will generate these functions to check for _Float16 + # support. If we fail to compile this program, we will simply disable + # _Float16 support for the time being. + AC_MSG_CHECKING([if compiler can correctly compile and run a test program which converts _Float16 to other types with casts]) + TEST_SRC="`(echo \"#define H5_FLOAT16_CONVERSION_FUNCS_LINK_TEST 1\"; cat $srcdir/config/cmake/ConversionTests.c)`" + AC_CACHE_VAL([hdf5_cv_float16_conversion_funcs_link], + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([$TEST_SRC])], + [hdf5_cv_float16_conversion_funcs_link=yes], [hdf5_cv_float16_conversion_funcs_link=no], [hdf5_cv_float16_conversion_funcs_link=no])]) + + if test ${hdf5_cv_float16_conversion_funcs_link} = "yes"; then + AC_MSG_RESULT([yes]) + + # Finally, MacOS 13 appears to have a bug specifically when converting + # long double values to _Float16. Release builds of the dt_arith test + # would cause any assignments to a _Float16 variable to be elided, + # whereas Debug builds would perform incorrect hardware conversions by + # simply chopping off all the bytes of the value except for the first 2. + # These tests pass on MacOS 14, so let's perform a quick test to check + # if the hardware conversion is done correctly. + AC_MSG_CHECKING([if compiler can correctly convert long double values to _Float16]) + TEST_SRC="`(echo \"#define H5_LDOUBLE_TO_FLOAT16_CORRECT_TEST 1\"; cat $srcdir/config/cmake/ConversionTests.c)`" + if test ${ac_cv_sizeof_long_double} = 0; then + hdf5_cv_ldouble_to_float16_correct=${hdf5_cv_ldouble_to_float16_correct=no} + else + AC_CACHE_VAL([hdf5_cv_ldouble_to_float16_correct], + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([$TEST_SRC])], + [hdf5_cv_ldouble_to_float16_correct=yes], [hdf5_cv_ldouble_to_float16_correct=no], [hdf5_cv_ldouble_to_float16_correct=yes])]) + fi + + if test ${hdf5_cv_ldouble_to_float16_correct} = "yes"; then + AC_DEFINE([LDOUBLE_TO_FLOAT16_CORRECT], [1], + [Define if your system can convert long double to _Float16 values correctly.]) + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + AC_MSG_NOTICE([Conversions from long double to _Float16 appear to be incorrect. These will be emulated through a soft conversion function.]) + fi + + HAVE__FLOAT16="yes" + + # Check if we can use fabsf16 + AC_CHECK_FUNC([fabsf16], [AC_DEFINE([HAVE_FABSF16], [1], + [Define if has fabsf16 function])], []) + + # Define HAVE__FLOAT16 macro for H5pubconf.h if _Float16 is available. + AC_DEFINE([HAVE__FLOAT16], [1], [Determine if _Float16 is available]) + else + AC_MSG_RESULT([no]) + fi + fi + + AC_MSG_CHECKING([if _Float16 support is enabled]) + AC_MSG_RESULT([$HAVE__FLOAT16]) +fi + +# Define HAVE__FLOAT16 value to substitute into other files for conditional testing +AC_SUBST([HAVE__FLOAT16]) + ## ---------------------------------------------------------------------- ## Check if the Fortran interface should be enabled ## diff --git a/doxygen/dox/DDLBNF112.dox b/doxygen/dox/DDLBNF112.dox index 6809a0632ff..cfe34c321f9 100644 --- a/doxygen/dox/DDLBNF112.dox +++ b/doxygen/dox/DDLBNF112.dox @@ -1,4 +1,4 @@ -/** \page DDLBNF112 DDL in BNF for HDF5 1.12 and above +/** \page DDLBNF112 DDL in BNF for HDF5 1.12 through HDF5 1.14.3 \todo Revise this & break it up! diff --git a/doxygen/dox/DDLBNF114.dox b/doxygen/dox/DDLBNF114.dox new file mode 100644 index 00000000000..61e9157e560 --- /dev/null +++ b/doxygen/dox/DDLBNF114.dox @@ -0,0 +1,654 @@ +/** \page DDLBNF114 DDL in BNF for HDF5 1.14.4 and above + +\todo Revise this & break it up! + +\section intro114 Introduction + +This document contains the data description language (DDL) for an HDF5 file. The +description is in Backus-Naur Form (BNF). + +\section expo114 Explanation of Symbols + +This section contains a brief explanation of the symbols used in the DDL. + +\code{.unparsed} +::= defined as + a token with the name tname + | one of or + opt zero or one occurrence of + * zero or more occurrence of + + one or more occurrence of + [0-9] an element in the range between 0 and 9 + '[' the token within the quotes (used for special characters) + TBD To Be Decided +\endcode + +\section ddl114 The DDL + +\code{.unparsed} + ::= HDF5 { opt } + + ::= + + ::= SUPER_BLOCK { + SUPERBLOCK_VERSION + FREELIST_VERSION + SYMBOLTABLE_VERSION + OBJECTHEADER_VERSION + OFFSET_SIZE + LENGTH_SIZE + BTREE_RANK + BTREE_LEAF + ISTORE_K + + USER_BLOCK { + USERBLOCK_SIZE + } + } + + ::= FILE_SPACE_STRATEGY + FREE_SPACE_PERSIST + FREE_SPACE_SECTION_THRESHOLD + FILE_SPACE_PAGE_SIZE + + ::= H5F_FSPACE_STRATEGY_FSM_AGGR | H5F_FSPACE_STRATEGY_PAGE | + H5F_FSPACE_STRATEGY_AGGR | H5F_FSPACE_STRATEGY_NONE | + Unknown strategy + + ::= GROUP "/" { + * + opt + opt + * + * + } + + ::= | | | + + ::= DATATYPE { + + } + + ::= the assigned name for anonymous named type is + in the form of #oid, where oid is the object id + of the type + + ::= | | * Libraries and Tools Reference. - * The HDF5 DDL grammar is described in the document \ref DDLBNF110. + * The HDF5 DDL grammar is described in the document \ref DDLBNF114. * * \subsection subsec_file_summary File Function Summaries * General library (\ref H5 functions and macros), (\ref H5F functions), file related diff --git a/src/H5Gmodule.h b/src/H5Gmodule.h index c330fcdb400..fb9cf732c09 100644 --- a/src/H5Gmodule.h +++ b/src/H5Gmodule.h @@ -343,7 +343,7 @@ * * h5dump is described on the “HDF5 Tools” page of the \ref RM. * - * The HDF5 DDL grammar is described in the @ref DDLBNF110. + * The HDF5 DDL grammar is described in the @ref DDLBNF114. * * \subsection subsec_group_function Group Function Summaries * Functions that can be used with groups (\ref H5G functions) and property list functions that can used diff --git a/src/H5T.c b/src/H5T.c index 7d3db702a84..1fb4b214833 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -100,6 +100,30 @@ dt->shared->u.atomic.msb_pad = H5T_PAD_ZERO; \ } +/* Define the code templates for standard 16-bit floats for the "GUTS" in the H5T_INIT_TYPE macro */ +#define H5T_INIT_TYPE_FLOAT16_COMMON(ENDIANNESS) \ + { \ + H5T_INIT_TYPE_NUM_COMMON(ENDIANNESS) \ + dt->shared->u.atomic.u.f.sign = 15; \ + dt->shared->u.atomic.u.f.epos = 10; \ + dt->shared->u.atomic.u.f.esize = 5; \ + dt->shared->u.atomic.u.f.ebias = 0xf; \ + dt->shared->u.atomic.u.f.mpos = 0; \ + dt->shared->u.atomic.u.f.msize = 10; \ + dt->shared->u.atomic.u.f.norm = H5T_NORM_IMPLIED; \ + dt->shared->u.atomic.u.f.pad = H5T_PAD_ZERO; \ + } + +#define H5T_INIT_TYPE_FLOAT16LE_CORE \ + { \ + H5T_INIT_TYPE_FLOAT16_COMMON(H5T_ORDER_LE) \ + } + +#define H5T_INIT_TYPE_FLOAT16BE_CORE \ + { \ + H5T_INIT_TYPE_FLOAT16_COMMON(H5T_ORDER_BE) \ + } + /* Define the code templates for standard floats for the "GUTS" in the H5T_INIT_TYPE macro */ #define H5T_INIT_TYPE_FLOAT_COMMON(ENDIANNESS) \ { \ @@ -375,102 +399,105 @@ H5T_order_t H5T_native_order_g = H5T_ORDER_ERROR; * If more of these are added, the new ones must be added to the list of * types to reset in H5T_term_package(). */ -hid_t H5T_IEEE_F32BE_g = FAIL; -hid_t H5T_IEEE_F32LE_g = FAIL; -hid_t H5T_IEEE_F64BE_g = FAIL; -hid_t H5T_IEEE_F64LE_g = FAIL; - -hid_t H5T_VAX_F32_g = FAIL; -hid_t H5T_VAX_F64_g = FAIL; - -hid_t H5T_STD_I8BE_g = FAIL; -hid_t H5T_STD_I8LE_g = FAIL; -hid_t H5T_STD_I16BE_g = FAIL; -hid_t H5T_STD_I16LE_g = FAIL; -hid_t H5T_STD_I32BE_g = FAIL; -hid_t H5T_STD_I32LE_g = FAIL; -hid_t H5T_STD_I64BE_g = FAIL; -hid_t H5T_STD_I64LE_g = FAIL; -hid_t H5T_STD_U8BE_g = FAIL; -hid_t H5T_STD_U8LE_g = FAIL; -hid_t H5T_STD_U16BE_g = FAIL; -hid_t H5T_STD_U16LE_g = FAIL; -hid_t H5T_STD_U32BE_g = FAIL; -hid_t H5T_STD_U32LE_g = FAIL; -hid_t H5T_STD_U64BE_g = FAIL; -hid_t H5T_STD_U64LE_g = FAIL; -hid_t H5T_STD_B8BE_g = FAIL; -hid_t H5T_STD_B8LE_g = FAIL; -hid_t H5T_STD_B16BE_g = FAIL; -hid_t H5T_STD_B16LE_g = FAIL; -hid_t H5T_STD_B32BE_g = FAIL; -hid_t H5T_STD_B32LE_g = FAIL; -hid_t H5T_STD_B64BE_g = FAIL; -hid_t H5T_STD_B64LE_g = FAIL; -hid_t H5T_STD_REF_OBJ_g = FAIL; -hid_t H5T_STD_REF_DSETREG_g = FAIL; -hid_t H5T_STD_REF_g = FAIL; - -hid_t H5T_UNIX_D32BE_g = FAIL; -hid_t H5T_UNIX_D32LE_g = FAIL; -hid_t H5T_UNIX_D64BE_g = FAIL; -hid_t H5T_UNIX_D64LE_g = FAIL; - -hid_t H5T_C_S1_g = FAIL; - -hid_t H5T_FORTRAN_S1_g = FAIL; - -hid_t H5T_NATIVE_SCHAR_g = FAIL; -hid_t H5T_NATIVE_UCHAR_g = FAIL; -hid_t H5T_NATIVE_SHORT_g = FAIL; -hid_t H5T_NATIVE_USHORT_g = FAIL; -hid_t H5T_NATIVE_INT_g = FAIL; -hid_t H5T_NATIVE_UINT_g = FAIL; -hid_t H5T_NATIVE_LONG_g = FAIL; -hid_t H5T_NATIVE_ULONG_g = FAIL; -hid_t H5T_NATIVE_LLONG_g = FAIL; -hid_t H5T_NATIVE_ULLONG_g = FAIL; -hid_t H5T_NATIVE_FLOAT_g = FAIL; -hid_t H5T_NATIVE_DOUBLE_g = FAIL; -hid_t H5T_NATIVE_LDOUBLE_g = FAIL; -hid_t H5T_NATIVE_B8_g = FAIL; -hid_t H5T_NATIVE_B16_g = FAIL; -hid_t H5T_NATIVE_B32_g = FAIL; -hid_t H5T_NATIVE_B64_g = FAIL; -hid_t H5T_NATIVE_OPAQUE_g = FAIL; -hid_t H5T_NATIVE_HADDR_g = FAIL; -hid_t H5T_NATIVE_HSIZE_g = FAIL; -hid_t H5T_NATIVE_HSSIZE_g = FAIL; -hid_t H5T_NATIVE_HERR_g = FAIL; -hid_t H5T_NATIVE_HBOOL_g = FAIL; - -hid_t H5T_NATIVE_INT8_g = FAIL; -hid_t H5T_NATIVE_UINT8_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST8_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST8_g = FAIL; -hid_t H5T_NATIVE_INT_FAST8_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST8_g = FAIL; - -hid_t H5T_NATIVE_INT16_g = FAIL; -hid_t H5T_NATIVE_UINT16_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST16_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST16_g = FAIL; -hid_t H5T_NATIVE_INT_FAST16_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST16_g = FAIL; - -hid_t H5T_NATIVE_INT32_g = FAIL; -hid_t H5T_NATIVE_UINT32_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST32_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST32_g = FAIL; -hid_t H5T_NATIVE_INT_FAST32_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST32_g = FAIL; - -hid_t H5T_NATIVE_INT64_g = FAIL; -hid_t H5T_NATIVE_UINT64_g = FAIL; -hid_t H5T_NATIVE_INT_LEAST64_g = FAIL; -hid_t H5T_NATIVE_UINT_LEAST64_g = FAIL; -hid_t H5T_NATIVE_INT_FAST64_g = FAIL; -hid_t H5T_NATIVE_UINT_FAST64_g = FAIL; +hid_t H5T_IEEE_F16BE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F16LE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F32BE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F32LE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F64BE_g = H5I_INVALID_HID; +hid_t H5T_IEEE_F64LE_g = H5I_INVALID_HID; + +hid_t H5T_VAX_F32_g = H5I_INVALID_HID; +hid_t H5T_VAX_F64_g = H5I_INVALID_HID; + +hid_t H5T_STD_I8BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I8LE_g = H5I_INVALID_HID; +hid_t H5T_STD_I16BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I16LE_g = H5I_INVALID_HID; +hid_t H5T_STD_I32BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I32LE_g = H5I_INVALID_HID; +hid_t H5T_STD_I64BE_g = H5I_INVALID_HID; +hid_t H5T_STD_I64LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U8BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U8LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U16BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U16LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U32BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U32LE_g = H5I_INVALID_HID; +hid_t H5T_STD_U64BE_g = H5I_INVALID_HID; +hid_t H5T_STD_U64LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B8BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B8LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B16BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B16LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B32BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B32LE_g = H5I_INVALID_HID; +hid_t H5T_STD_B64BE_g = H5I_INVALID_HID; +hid_t H5T_STD_B64LE_g = H5I_INVALID_HID; +hid_t H5T_STD_REF_OBJ_g = H5I_INVALID_HID; +hid_t H5T_STD_REF_DSETREG_g = H5I_INVALID_HID; +hid_t H5T_STD_REF_g = H5I_INVALID_HID; + +hid_t H5T_UNIX_D32BE_g = H5I_INVALID_HID; +hid_t H5T_UNIX_D32LE_g = H5I_INVALID_HID; +hid_t H5T_UNIX_D64BE_g = H5I_INVALID_HID; +hid_t H5T_UNIX_D64LE_g = H5I_INVALID_HID; + +hid_t H5T_C_S1_g = H5I_INVALID_HID; + +hid_t H5T_FORTRAN_S1_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_SCHAR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UCHAR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_SHORT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_USHORT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_ULONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LLONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_ULLONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_FLOAT16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_FLOAT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_DOUBLE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LDOUBLE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_OPAQUE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HADDR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HSIZE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HSSIZE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HERR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HBOOL_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST8_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST16_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST32_g = H5I_INVALID_HID; + +hid_t H5T_NATIVE_INT64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_LEAST64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_LEAST64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_FAST64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_FAST64_g = H5I_INVALID_HID; /* * Alignment constraints for HDF5 types. Accessing objects of these @@ -498,6 +525,7 @@ size_t H5T_NATIVE_LONG_ALIGN_g = 0; size_t H5T_NATIVE_ULONG_ALIGN_g = 0; size_t H5T_NATIVE_LLONG_ALIGN_g = 0; size_t H5T_NATIVE_ULLONG_ALIGN_g = 0; +size_t H5T_NATIVE_FLOAT16_ALIGN_g = 0; size_t H5T_NATIVE_FLOAT_ALIGN_g = 0; size_t H5T_NATIVE_DOUBLE_ALIGN_g = 0; size_t H5T_NATIVE_LDOUBLE_ALIGN_g = 0; @@ -533,6 +561,15 @@ size_t H5T_NATIVE_UINT_FAST64_ALIGN_g = 0; /* Useful floating-point values for conversion routines */ /* (+/- Inf for all floating-point types) */ +#ifdef H5_HAVE__FLOAT16 +/* Initialize these with a float literal since the f16 suffix + * is non-standard C and gives warnings when compiling the + * library with the -pedantic flag. These values will be + * overwritten anyway. + */ +H5__Float16 H5T_NATIVE_FLOAT16_POS_INF_g = 0.0f; +H5__Float16 H5T_NATIVE_FLOAT16_NEG_INF_g = 0.0f; +#endif float H5T_NATIVE_FLOAT_POS_INF_g = 0.0F; float H5T_NATIVE_FLOAT_NEG_INF_g = 0.0F; double H5T_NATIVE_DOUBLE_POS_INF_g = 0.0; @@ -685,6 +722,49 @@ H5T__init_inf(void) } /* end for */ } /* end if */ +#ifdef H5_HAVE__FLOAT16 + /* Get the _Float16 datatype */ + if (NULL == (dst_p = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT16_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + dst = &dst_p->shared->u.atomic; + + /* Check that we can re-order the bytes correctly */ + if (H5T_ORDER_LE != H5T_native_order_g && H5T_ORDER_BE != H5T_native_order_g) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + + /* +Inf */ + d = (uint8_t *)&H5T_NATIVE_FLOAT16_POS_INF_g; + H5T__bit_set(d, dst->u.f.sign, (size_t)1, false); + H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true); + H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false); + + /* Swap the bytes if the machine architecture is big-endian */ + if (H5T_ORDER_BE == H5T_native_order_g) { + half_size = dst_p->shared->size / 2; + for (u = 0; u < half_size; u++) { + uint8_t tmp = d[dst_p->shared->size - (u + 1)]; + d[dst_p->shared->size - (u + 1)] = d[u]; + d[u] = tmp; + } /* end for */ + } /* end if */ + + /* -Inf */ + d = (uint8_t *)&H5T_NATIVE_FLOAT16_NEG_INF_g; + H5T__bit_set(d, dst->u.f.sign, (size_t)1, true); + H5T__bit_set(d, dst->u.f.epos, dst->u.f.esize, true); + H5T__bit_set(d, dst->u.f.mpos, dst->u.f.msize, false); + + /* Swap the bytes if the machine architecture is big-endian */ + if (H5T_ORDER_BE == H5T_native_order_g) { + half_size = dst_p->shared->size / 2; + for (u = 0; u < half_size; u++) { + uint8_t tmp = d[dst_p->shared->size - (u + 1)]; + d[dst_p->shared->size - (u + 1)] = d[u]; + d[u] = tmp; + } /* end for */ + } /* end if */ +#endif + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__init_inf() */ @@ -738,6 +818,9 @@ H5T_init(void) herr_t status; bool copied_dtype = true; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */ +#ifdef H5_HAVE__FLOAT16 + H5T_t *native_float16 = NULL; /* Datatype structure for native _Float16 type */ +#endif herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -779,6 +862,10 @@ H5T_init(void) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); if (NULL == (native_ullong = (H5T_t *)H5I_object(H5T_NATIVE_ULLONG_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); +#ifdef H5_HAVE__FLOAT16 + if (NULL == (native_float16 = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT16_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); +#endif if (NULL == (native_float = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); if (NULL == (native_double = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_g))) @@ -823,6 +910,12 @@ H5T_init(void) *------------------------------------------------------------ */ + /* IEEE 2-byte little-endian float */ + H5T_INIT_TYPE(FLOAT16LE, H5T_IEEE_F16LE_g, COPY, native_double, SET, 2) + + /* IEEE 2-byte big-endian float */ + H5T_INIT_TYPE(FLOAT16BE, H5T_IEEE_F16BE_g, COPY, native_double, SET, 2) + /* IEEE 4-byte little-endian float */ H5T_INIT_TYPE(FLOATLE, H5T_IEEE_F32LE_g, COPY, native_double, SET, 4) @@ -1062,6 +1155,22 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "ldbl_flt", native_ldouble, native_float, H5T__conv_ldouble_float); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_dbl", native_ldouble, native_double, H5T__conv_ldouble_double); +#ifdef H5_HAVE__FLOAT16 + status |= + H5T__register_int(H5T_PERS_HARD, "flt16_flt", native_float16, native_float, H5T__conv__Float16_float); + status |= H5T__register_int(H5T_PERS_HARD, "flt16_dbl", native_float16, native_double, + H5T__conv__Float16_double); + status |= H5T__register_int(H5T_PERS_HARD, "flt16_ldbl", native_float16, native_ldouble, + H5T__conv__Float16_ldouble); + status |= + H5T__register_int(H5T_PERS_HARD, "flt_flt16", native_float, native_float16, H5T__conv_float__Float16); + status |= H5T__register_int(H5T_PERS_HARD, "dbl_flt16", native_double, native_float16, + H5T__conv_double__Float16); +#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "ldbl_flt16", native_ldouble, native_float16, + H5T__conv_ldouble__Float16); +#endif +#endif /* from long long */ status |= @@ -1220,6 +1329,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "schar_dbl", native_schar, native_double, H5T__conv_schar_double); status |= H5T__register_int(H5T_PERS_HARD, "schar_ldbl", native_schar, native_ldouble, H5T__conv_schar_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "schar_flt16", native_schar, native_float16, + H5T__conv_schar__Float16); +#endif /* From unsigned char to floats */ status |= @@ -1228,6 +1341,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "uchar_dbl", native_uchar, native_double, H5T__conv_uchar_double); status |= H5T__register_int(H5T_PERS_HARD, "uchar_ldbl", native_uchar, native_ldouble, H5T__conv_uchar_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "uchar_flt16", native_uchar, native_float16, + H5T__conv_uchar__Float16); +#endif /* From short to floats */ status |= @@ -1236,6 +1353,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "short_dbl", native_short, native_double, H5T__conv_short_double); status |= H5T__register_int(H5T_PERS_HARD, "short_ldbl", native_short, native_ldouble, H5T__conv_short_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "short_flt16", native_short, native_float16, + H5T__conv_short__Float16); +#endif /* From unsigned short to floats */ status |= @@ -1244,23 +1365,39 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "ushort_dbl", native_ushort, native_double, H5T__conv_ushort_double); status |= H5T__register_int(H5T_PERS_HARD, "ushort_ldbl", native_ushort, native_ldouble, H5T__conv_ushort_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "ushort_flt16", native_ushort, native_float16, + H5T__conv_ushort__Float16); +#endif /* From int to floats */ status |= H5T__register_int(H5T_PERS_HARD, "int_flt", native_int, native_float, H5T__conv_int_float); status |= H5T__register_int(H5T_PERS_HARD, "int_dbl", native_int, native_double, H5T__conv_int_double); status |= H5T__register_int(H5T_PERS_HARD, "int_ldbl", native_int, native_ldouble, H5T__conv_int_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= + H5T__register_int(H5T_PERS_HARD, "int_flt16", native_int, native_float16, H5T__conv_int__Float16); +#endif /* From unsigned int to floats */ status |= H5T__register_int(H5T_PERS_HARD, "uint_flt", native_uint, native_float, H5T__conv_uint_float); status |= H5T__register_int(H5T_PERS_HARD, "uint_dbl", native_uint, native_double, H5T__conv_uint_double); status |= H5T__register_int(H5T_PERS_HARD, "uint_ldbl", native_uint, native_ldouble, H5T__conv_uint_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= + H5T__register_int(H5T_PERS_HARD, "uint_flt16", native_uint, native_float16, H5T__conv_uint__Float16); +#endif /* From long to floats */ status |= H5T__register_int(H5T_PERS_HARD, "long_flt", native_long, native_float, H5T__conv_long_float); status |= H5T__register_int(H5T_PERS_HARD, "long_dbl", native_long, native_double, H5T__conv_long_double); status |= H5T__register_int(H5T_PERS_HARD, "long_ldbl", native_long, native_ldouble, H5T__conv_long_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= + H5T__register_int(H5T_PERS_HARD, "long_flt16", native_long, native_float16, H5T__conv_long__Float16); +#endif /* From unsigned long to floats */ status |= @@ -1269,6 +1406,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "ulong_dbl", native_ulong, native_double, H5T__conv_ulong_double); status |= H5T__register_int(H5T_PERS_HARD, "ulong_ldbl", native_ulong, native_ldouble, H5T__conv_ulong_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "ulong_flt16", native_ulong, native_float16, + H5T__conv_ulong__Float16); +#endif /* From long long to floats */ status |= @@ -1279,6 +1420,10 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "llong_ldbl", native_llong, native_ldouble, H5T__conv_llong_ldouble); #endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */ +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "llong_flt16", native_llong, native_float16, + H5T__conv_llong__Float16); +#endif /* From unsigned long long to floats */ status |= @@ -1289,6 +1434,10 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ullong_ldbl", native_ullong, native_ldouble, H5T__conv_ullong_ldouble); #endif /* H5T_CONV_INTERNAL_ULLONG_LDOUBLE */ +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "ullong_flt16", native_ullong, native_float16, + H5T__conv_ullong__Float16); +#endif /* From floats to char */ status |= @@ -1297,6 +1446,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "dbl_schar", native_double, native_schar, H5T__conv_double_schar); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_schar", native_ldouble, native_schar, H5T__conv_ldouble_schar); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_schar", native_float16, native_schar, + H5T__conv__Float16_schar); +#endif /* From floats to unsigned char */ status |= @@ -1305,6 +1458,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "dbl_uchar", native_double, native_uchar, H5T__conv_double_uchar); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_uchar", native_ldouble, native_uchar, H5T__conv_ldouble_uchar); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_uchar", native_float16, native_uchar, + H5T__conv__Float16_uchar); +#endif /* From floats to short */ status |= @@ -1313,6 +1470,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "dbl_short", native_double, native_short, H5T__conv_double_short); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_short", native_ldouble, native_short, H5T__conv_ldouble_short); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_short", native_float16, native_short, + H5T__conv__Float16_short); +#endif /* From floats to unsigned short */ status |= @@ -1321,23 +1482,39 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "dbl_ushort", native_double, native_ushort, H5T__conv_double_ushort); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ushort", native_ldouble, native_ushort, H5T__conv_ldouble_ushort); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_ushort", native_float16, native_ushort, + H5T__conv__Float16_ushort); +#endif /* From floats to int */ status |= H5T__register_int(H5T_PERS_HARD, "flt_int", native_float, native_int, H5T__conv_float_int); status |= H5T__register_int(H5T_PERS_HARD, "dbl_int", native_double, native_int, H5T__conv_double_int); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_int", native_ldouble, native_int, H5T__conv_ldouble_int); +#ifdef H5_HAVE__FLOAT16 + status |= + H5T__register_int(H5T_PERS_HARD, "flt16_int", native_float16, native_int, H5T__conv__Float16_int); +#endif /* From floats to unsigned int */ status |= H5T__register_int(H5T_PERS_HARD, "flt_uint", native_float, native_uint, H5T__conv_float_uint); status |= H5T__register_int(H5T_PERS_HARD, "dbl_uint", native_double, native_uint, H5T__conv_double_uint); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_uint", native_ldouble, native_uint, H5T__conv_ldouble_uint); +#ifdef H5_HAVE__FLOAT16 + status |= + H5T__register_int(H5T_PERS_HARD, "flt16_uint", native_float16, native_uint, H5T__conv__Float16_uint); +#endif /* From floats to long */ status |= H5T__register_int(H5T_PERS_HARD, "flt_long", native_float, native_long, H5T__conv_float_long); status |= H5T__register_int(H5T_PERS_HARD, "dbl_long", native_double, native_long, H5T__conv_double_long); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_long", native_ldouble, native_long, H5T__conv_ldouble_long); +#ifdef H5_HAVE__FLOAT16 + status |= + H5T__register_int(H5T_PERS_HARD, "flt16_long", native_float16, native_long, H5T__conv__Float16_long); +#endif /* From floats to unsigned long */ status |= @@ -1346,6 +1523,10 @@ H5T_init(void) H5T__register_int(H5T_PERS_HARD, "dbl_ulong", native_double, native_ulong, H5T__conv_double_ulong); status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ulong", native_ldouble, native_ulong, H5T__conv_ldouble_ulong); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_ulong", native_float16, native_ulong, + H5T__conv__Float16_ulong); +#endif /* From floats to long long */ status |= @@ -1356,6 +1537,10 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ldbl_llong", native_ldouble, native_llong, H5T__conv_ldouble_llong); #endif /* H5T_CONV_INTERNAL_LDOUBLE_LLONG */ +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_llong", native_float16, native_llong, + H5T__conv__Float16_llong); +#endif /* From floats to unsigned long long */ status |= @@ -1366,6 +1551,10 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ullong", native_ldouble, native_ullong, H5T__conv_ldouble_ullong); #endif /* H5T_CONV_INTERNAL_LDOUBLE_ULLONG */ +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_ullong", native_float16, native_ullong, + H5T__conv__Float16_ullong); +#endif /* * The special no-op conversion is the fastest, so we list it last. The @@ -1546,99 +1735,102 @@ H5T_top_term_package(void) /* Reset all the datatype IDs */ if (H5T_IEEE_F32BE_g > 0) { - H5T_IEEE_F32BE_g = FAIL; - H5T_IEEE_F32LE_g = FAIL; - H5T_IEEE_F64BE_g = FAIL; - H5T_IEEE_F64LE_g = FAIL; - - H5T_STD_I8BE_g = FAIL; - H5T_STD_I8LE_g = FAIL; - H5T_STD_I16BE_g = FAIL; - H5T_STD_I16LE_g = FAIL; - H5T_STD_I32BE_g = FAIL; - H5T_STD_I32LE_g = FAIL; - H5T_STD_I64BE_g = FAIL; - H5T_STD_I64LE_g = FAIL; - H5T_STD_U8BE_g = FAIL; - H5T_STD_U8LE_g = FAIL; - H5T_STD_U16BE_g = FAIL; - H5T_STD_U16LE_g = FAIL; - H5T_STD_U32BE_g = FAIL; - H5T_STD_U32LE_g = FAIL; - H5T_STD_U64BE_g = FAIL; - H5T_STD_U64LE_g = FAIL; - H5T_STD_B8BE_g = FAIL; - H5T_STD_B8LE_g = FAIL; - H5T_STD_B16BE_g = FAIL; - H5T_STD_B16LE_g = FAIL; - H5T_STD_B32BE_g = FAIL; - H5T_STD_B32LE_g = FAIL; - H5T_STD_B64BE_g = FAIL; - H5T_STD_B64LE_g = FAIL; - H5T_STD_REF_OBJ_g = FAIL; - H5T_STD_REF_DSETREG_g = FAIL; - H5T_STD_REF_g = FAIL; - - H5T_UNIX_D32BE_g = FAIL; - H5T_UNIX_D32LE_g = FAIL; - H5T_UNIX_D64BE_g = FAIL; - H5T_UNIX_D64LE_g = FAIL; - - H5T_C_S1_g = FAIL; - - H5T_FORTRAN_S1_g = FAIL; - - H5T_NATIVE_SCHAR_g = FAIL; - H5T_NATIVE_UCHAR_g = FAIL; - H5T_NATIVE_SHORT_g = FAIL; - H5T_NATIVE_USHORT_g = FAIL; - H5T_NATIVE_INT_g = FAIL; - H5T_NATIVE_UINT_g = FAIL; - H5T_NATIVE_LONG_g = FAIL; - H5T_NATIVE_ULONG_g = FAIL; - H5T_NATIVE_LLONG_g = FAIL; - H5T_NATIVE_ULLONG_g = FAIL; - H5T_NATIVE_FLOAT_g = FAIL; - H5T_NATIVE_DOUBLE_g = FAIL; - H5T_NATIVE_LDOUBLE_g = FAIL; - H5T_NATIVE_B8_g = FAIL; - H5T_NATIVE_B16_g = FAIL; - H5T_NATIVE_B32_g = FAIL; - H5T_NATIVE_B64_g = FAIL; - H5T_NATIVE_OPAQUE_g = FAIL; - H5T_NATIVE_HADDR_g = FAIL; - H5T_NATIVE_HSIZE_g = FAIL; - H5T_NATIVE_HSSIZE_g = FAIL; - H5T_NATIVE_HERR_g = FAIL; - H5T_NATIVE_HBOOL_g = FAIL; - - H5T_NATIVE_INT8_g = FAIL; - H5T_NATIVE_UINT8_g = FAIL; - H5T_NATIVE_INT_LEAST8_g = FAIL; - H5T_NATIVE_UINT_LEAST8_g = FAIL; - H5T_NATIVE_INT_FAST8_g = FAIL; - H5T_NATIVE_UINT_FAST8_g = FAIL; - - H5T_NATIVE_INT16_g = FAIL; - H5T_NATIVE_UINT16_g = FAIL; - H5T_NATIVE_INT_LEAST16_g = FAIL; - H5T_NATIVE_UINT_LEAST16_g = FAIL; - H5T_NATIVE_INT_FAST16_g = FAIL; - H5T_NATIVE_UINT_FAST16_g = FAIL; - - H5T_NATIVE_INT32_g = FAIL; - H5T_NATIVE_UINT32_g = FAIL; - H5T_NATIVE_INT_LEAST32_g = FAIL; - H5T_NATIVE_UINT_LEAST32_g = FAIL; - H5T_NATIVE_INT_FAST32_g = FAIL; - H5T_NATIVE_UINT_FAST32_g = FAIL; - - H5T_NATIVE_INT64_g = FAIL; - H5T_NATIVE_UINT64_g = FAIL; - H5T_NATIVE_INT_LEAST64_g = FAIL; - H5T_NATIVE_UINT_LEAST64_g = FAIL; - H5T_NATIVE_INT_FAST64_g = FAIL; - H5T_NATIVE_UINT_FAST64_g = FAIL; + H5T_IEEE_F16BE_g = H5I_INVALID_HID; + H5T_IEEE_F16LE_g = H5I_INVALID_HID; + H5T_IEEE_F32BE_g = H5I_INVALID_HID; + H5T_IEEE_F32LE_g = H5I_INVALID_HID; + H5T_IEEE_F64BE_g = H5I_INVALID_HID; + H5T_IEEE_F64LE_g = H5I_INVALID_HID; + + H5T_STD_I8BE_g = H5I_INVALID_HID; + H5T_STD_I8LE_g = H5I_INVALID_HID; + H5T_STD_I16BE_g = H5I_INVALID_HID; + H5T_STD_I16LE_g = H5I_INVALID_HID; + H5T_STD_I32BE_g = H5I_INVALID_HID; + H5T_STD_I32LE_g = H5I_INVALID_HID; + H5T_STD_I64BE_g = H5I_INVALID_HID; + H5T_STD_I64LE_g = H5I_INVALID_HID; + H5T_STD_U8BE_g = H5I_INVALID_HID; + H5T_STD_U8LE_g = H5I_INVALID_HID; + H5T_STD_U16BE_g = H5I_INVALID_HID; + H5T_STD_U16LE_g = H5I_INVALID_HID; + H5T_STD_U32BE_g = H5I_INVALID_HID; + H5T_STD_U32LE_g = H5I_INVALID_HID; + H5T_STD_U64BE_g = H5I_INVALID_HID; + H5T_STD_U64LE_g = H5I_INVALID_HID; + H5T_STD_B8BE_g = H5I_INVALID_HID; + H5T_STD_B8LE_g = H5I_INVALID_HID; + H5T_STD_B16BE_g = H5I_INVALID_HID; + H5T_STD_B16LE_g = H5I_INVALID_HID; + H5T_STD_B32BE_g = H5I_INVALID_HID; + H5T_STD_B32LE_g = H5I_INVALID_HID; + H5T_STD_B64BE_g = H5I_INVALID_HID; + H5T_STD_B64LE_g = H5I_INVALID_HID; + H5T_STD_REF_OBJ_g = H5I_INVALID_HID; + H5T_STD_REF_DSETREG_g = H5I_INVALID_HID; + H5T_STD_REF_g = H5I_INVALID_HID; + + H5T_UNIX_D32BE_g = H5I_INVALID_HID; + H5T_UNIX_D32LE_g = H5I_INVALID_HID; + H5T_UNIX_D64BE_g = H5I_INVALID_HID; + H5T_UNIX_D64LE_g = H5I_INVALID_HID; + + H5T_C_S1_g = H5I_INVALID_HID; + + H5T_FORTRAN_S1_g = H5I_INVALID_HID; + + H5T_NATIVE_SCHAR_g = H5I_INVALID_HID; + H5T_NATIVE_UCHAR_g = H5I_INVALID_HID; + H5T_NATIVE_SHORT_g = H5I_INVALID_HID; + H5T_NATIVE_USHORT_g = H5I_INVALID_HID; + H5T_NATIVE_INT_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_g = H5I_INVALID_HID; + H5T_NATIVE_LONG_g = H5I_INVALID_HID; + H5T_NATIVE_ULONG_g = H5I_INVALID_HID; + H5T_NATIVE_LLONG_g = H5I_INVALID_HID; + H5T_NATIVE_ULLONG_g = H5I_INVALID_HID; + H5T_NATIVE_FLOAT16_g = H5I_INVALID_HID; + H5T_NATIVE_FLOAT_g = H5I_INVALID_HID; + H5T_NATIVE_DOUBLE_g = H5I_INVALID_HID; + H5T_NATIVE_LDOUBLE_g = H5I_INVALID_HID; + H5T_NATIVE_B8_g = H5I_INVALID_HID; + H5T_NATIVE_B16_g = H5I_INVALID_HID; + H5T_NATIVE_B32_g = H5I_INVALID_HID; + H5T_NATIVE_B64_g = H5I_INVALID_HID; + H5T_NATIVE_OPAQUE_g = H5I_INVALID_HID; + H5T_NATIVE_HADDR_g = H5I_INVALID_HID; + H5T_NATIVE_HSIZE_g = H5I_INVALID_HID; + H5T_NATIVE_HSSIZE_g = H5I_INVALID_HID; + H5T_NATIVE_HERR_g = H5I_INVALID_HID; + H5T_NATIVE_HBOOL_g = H5I_INVALID_HID; + + H5T_NATIVE_INT8_g = H5I_INVALID_HID; + H5T_NATIVE_UINT8_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST8_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST8_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST8_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST8_g = H5I_INVALID_HID; + + H5T_NATIVE_INT16_g = H5I_INVALID_HID; + H5T_NATIVE_UINT16_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST16_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST16_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST16_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST16_g = H5I_INVALID_HID; + + H5T_NATIVE_INT32_g = H5I_INVALID_HID; + H5T_NATIVE_UINT32_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST32_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST32_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST32_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST32_g = H5I_INVALID_HID; + + H5T_NATIVE_INT64_g = H5I_INVALID_HID; + H5T_NATIVE_UINT64_g = H5I_INVALID_HID; + H5T_NATIVE_INT_LEAST64_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_LEAST64_g = H5I_INVALID_HID; + H5T_NATIVE_INT_FAST64_g = H5I_INVALID_HID; + H5T_NATIVE_UINT_FAST64_g = H5I_INVALID_HID; n++; } /* end if */ diff --git a/src/H5Tconv.c b/src/H5Tconv.c index a37800bfed3..0e35fb5461b 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -112,6 +112,14 @@ * at least as wide as the destination. Overflow can occur * when the source magnitude is too large for the destination. * + * fX: Floating-point values to integers where the destination is at least + * as wide as the source. This case cannot generate overflows. + * + * Xf: Integers to floating-point values where the source is at least as + * wide as the destination. Overflows can occur when the destination is + * narrower than the source. + * + * * The macros take a subset of these arguments in the order listed here: * * CDATA: A pointer to the H5T_cdata_t structure that was passed to the @@ -704,6 +712,99 @@ H5T_CONV(H5T_CONV_Fx, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y) \ } while (0) +#define H5T_CONV_fX(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) <= sizeof(DT)); \ + H5T_CONV(H5T_CONV_xX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N) \ + } while (0) + +#define H5T_CONV_Xf_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + if (*(S) > (ST)(D_MAX) || (sprec < dprec && *(S) == (ST)(D_MAX))) { \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ + if (except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ + *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g); \ + else if (except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } \ + else if (*(S) < (ST)(D_MIN)) { \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, S, D, \ + conv_ctx->u.conv.cb_struct.user_data); \ + if (except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ + *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g); \ + else if (except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } \ + else if (sprec > dprec) { \ + unsigned low_bit_pos, high_bit_pos; \ + \ + /* Detect high & low bits set in source */ \ + H5T_HI_LO_BIT_SET(ST, *(S), low_bit_pos, high_bit_pos) \ + \ + /* Check for more bits of precision in src than available in dst */ \ + if ((high_bit_pos - low_bit_pos) >= dprec) { \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_PRECISION, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, \ + S, D, conv_ctx->u.conv.cb_struct.user_data); \ + if (except_ret == H5T_CONV_UNHANDLED) \ + /* Let compiler convert if case is ignored by user handler*/ \ + *(D) = (DT)(*(S)); \ + else if (except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); \ + /* if(except_ret==H5T_CONV_HANDLED): Fall through, user handled it */ \ + } \ + else \ + *(D) = (DT)(*(S)); \ + } \ + else \ + *(D) = (DT)(*(S)); \ + } +#define H5T_CONV_Xf_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + if (*(S) > (ST)(D_MAX)) \ + *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g); \ + else { \ + intmax_t s_cast = (intmax_t)(*(S)); \ + intmax_t d_cast = (intmax_t)(D_MAX); \ + \ + /* Check if source value would underflow destination. Do NOT do this \ + * by comparing against D_MIN casted to type ST here, as this will \ + * generally be undefined behavior (casting negative float value <= 1.0 \ + * to integer) for all floating point types and some compilers optimize \ + * this in a way that causes unexpected behavior. Instead, grab the \ + * absolute value of the source value first, then compare it to D_MAX. \ + */ \ + if (s_cast != INTMAX_MIN) \ + s_cast = imaxabs(s_cast); \ + else { \ + /* Handle two's complement integer representations where abs(INTMAX_MIN) \ + * can't be represented. Other representations will fall here as well, \ + * but this should be fine. \ + */ \ + s_cast = INTMAX_MAX; \ + d_cast -= 1; \ + } \ + \ + if (s_cast > d_cast) \ + *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g); \ + else \ + *(D) = (DT)(*(S)); \ + } \ + } + +#define H5T_CONV_Xf(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) >= sizeof(DT)); \ + H5T_CONV(H5T_CONV_Xf, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y) \ + } while (0) + /* Since all "no exception" cores do the same thing (assign the value in the * source location to the destination location, using casting), use one "core" * to do them all. @@ -8215,6 +8316,255 @@ H5T__conv_ldouble_ullong(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_con } #endif /*H5T_CONV_INTERNAL_LDOUBLE_ULLONG*/ +/* Conversions for _Float16 type */ +#ifdef H5_HAVE__FLOAT16 +herr_t +H5T__conv_schar__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_xF(SCHAR, FLOAT16, signed char, H5__Float16, -, -); +} + +herr_t +H5T__conv_uchar__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_xF(UCHAR, FLOAT16, unsigned char, H5__Float16, -, -); +} + +herr_t +H5T__conv_short__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_xF(SHORT, FLOAT16, short, H5__Float16, -, -); +} + +herr_t +H5T__conv_ushort__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Xf(USHORT, FLOAT16, unsigned short, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_int__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Xf(INT, FLOAT16, int, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_uint__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Xf(UINT, FLOAT16, unsigned int, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_long__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Xf(LONG, FLOAT16, long, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_ulong__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Xf(ULONG, FLOAT16, unsigned long, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_llong__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Xf(LLONG, FLOAT16, long long, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_ullong__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Xf(ULLONG, FLOAT16, unsigned long long, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_float__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Ff(FLOAT, FLOAT16, float, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +herr_t +H5T__conv_double__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Ff(DOUBLE, FLOAT16, double, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} + +#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 +herr_t +H5T__conv_ldouble__Float16(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + /* Suppress warning about non-standard floating-point literal suffix */ + H5_GCC_CLANG_DIAG_OFF("pedantic") + H5T_CONV_Ff(LDOUBLE, FLOAT16, long double, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} +#endif + +herr_t +H5T__conv__Float16_schar(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5_GCC_CLANG_DIAG_OFF("float-equal") + H5T_CONV_Fx(FLOAT16, SCHAR, H5__Float16, signed char, SCHAR_MIN, SCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +herr_t +H5T__conv__Float16_uchar(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5_GCC_CLANG_DIAG_OFF("float-equal") + H5T_CONV_Fx(FLOAT16, UCHAR, H5__Float16, unsigned char, 0, UCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +herr_t +H5T__conv__Float16_short(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5_GCC_CLANG_DIAG_OFF("float-equal") + H5T_CONV_Fx(FLOAT16, SHORT, H5__Float16, short, SHRT_MIN, SHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +herr_t +H5T__conv__Float16_ushort(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fX(FLOAT16, USHORT, H5__Float16, unsigned short, 0, USHRT_MAX); +} + +herr_t +H5T__conv__Float16_int(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fX(FLOAT16, INT, H5__Float16, int, INT_MIN, INT_MAX); +} + +herr_t +H5T__conv__Float16_uint(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fX(FLOAT16, UINT, H5__Float16, unsigned int, 0, UINT_MAX); +} + +herr_t +H5T__conv__Float16_long(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fX(FLOAT16, LONG, H5__Float16, long, LONG_MIN, LONG_MAX); +} + +herr_t +H5T__conv__Float16_ulong(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fX(FLOAT16, ULONG, H5__Float16, unsigned long, 0, ULONG_MAX); +} + +herr_t +H5T__conv__Float16_llong(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fX(FLOAT16, LLONG, H5__Float16, long long, LLONG_MIN, LLONG_MAX); +} + +herr_t +H5T__conv__Float16_ullong(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fX(FLOAT16, ULLONG, H5__Float16, unsigned long long, 0, ULLONG_MAX); +} + +herr_t +H5T__conv__Float16_float(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fF(FLOAT16, FLOAT, H5__Float16, float, -, -); +} + +herr_t +H5T__conv__Float16_double(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fF(FLOAT16, DOUBLE, H5__Float16, double, -, -); +} + +herr_t +H5T__conv__Float16_ldouble(H5T_t *st, H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + H5T_CONV_fF(FLOAT16, LDOUBLE, H5__Float16, long double, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_f_i * @@ -8249,8 +8599,9 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx uint8_t *int_buf = NULL; /*buffer for temporary value */ size_t buf_size; /*buffer size for temporary value */ size_t i; /*miscellaneous counters */ - size_t first; /*first bit(MSB) in an integer */ - ssize_t sfirst; /*a signed version of `first' */ + ssize_t msb_pos_s; /*first bit(MSB) in an integer */ + ssize_t new_msb_pos; /*MSB position after shifting mantissa by exponent */ + hssize_t shift_val; /*shift value when shifting mantissa by exponent */ bool truncated; /*if fraction value is dropped */ bool reverse; /*if reverse order of destination at the end */ H5T_conv_ret_t except_ret; /*return of callback function */ @@ -8314,8 +8665,11 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx /* Allocate enough space for the buffer holding temporary * converted value */ - buf_size = (size_t)(pow(2.0, (double)src.u.f.esize) / 8 + 1); - int_buf = (uint8_t *)H5MM_calloc(buf_size); + if (dst.prec / 8 > src_p->shared->size) + buf_size = (dst.prec + 7) / 8; + else + buf_size = src_p->shared->size; + int_buf = (uint8_t *)H5MM_calloc(buf_size); /* Allocate space for order-reversed source buffer */ src_rev = (uint8_t *)H5MM_calloc(src_p->shared->size); @@ -8580,36 +8934,47 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx if (H5T_NORM_IMPLIED == src.u.f.norm) H5T__bit_inc(int_buf, src.u.f.msize, 8 * buf_size - src.u.f.msize); + /* + * What is the bit position for the most significant bit(MSB) of S + * which is set? This is checked before shifting and before possibly + * converting to a negative integer. Note that later use of this value + * assumes that H5T__bit_shift will always shift in 0 during a right + * shift. + */ + msb_pos_s = H5T__bit_find(int_buf, (size_t)0, src.prec, H5T_BIT_MSB, true); + + /* + * The temporary buffer has no bits set and must therefore be + * zero; nothing to do. + */ + if (msb_pos_s < 0) + goto padding; + /* * Shift mantissa part by exponent minus mantissa size(right shift), * or by mantissa size minus exponent(left shift). Example: Sequence * 10...010111, expo=20, expo-msize=-3. Right-shift the sequence, we get * 00010...10. The last three bits were dropped. */ - H5T__bit_shift(int_buf, expo - (ssize_t)src.u.f.msize, (size_t)0, buf_size * 8); + shift_val = expo - (ssize_t)src.u.f.msize; + H5T__bit_shift(int_buf, shift_val, (size_t)0, buf_size * 8); + + /* Calculate the new position of the MSB after shifting and + * skip to the padding section if we shifted exactly to 0 + * (MSB position is -1) + */ + new_msb_pos = msb_pos_s + shift_val; + if (new_msb_pos == -1) + goto padding; /* - * If expo is less than mantissa size, the frantional value is dropped off + * If expo is less than mantissa size, the fractional value is dropped off * during conversion. Set exception type to be "truncate" */ if ((size_t)expo < src.u.f.msize && conv_ctx->u.conv.cb_struct.func) truncated = true; - /* - * What is the bit position for the most significant bit(MSB) of S - * which is set? This is checked before converted to negative - * integer. - */ - sfirst = H5T__bit_find(int_buf, (size_t)0, 8 * buf_size, H5T_BIT_MSB, true); - first = (size_t)sfirst; - - if (sfirst < 0) { - /* - * The source has no bits set and must therefore be zero. - * Set the destination to zero - nothing to do. - */ - } - else if (H5T_SGN_NONE == dst.u.i.sign) { /*destination is unsigned*/ + if (H5T_SGN_NONE == dst.u.i.sign) { /*destination is unsigned*/ /* * Destination is unsigned. Library's default way: If the source value * is greater than the maximal destination value then it overflows, the @@ -8639,7 +9004,7 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } } else { /*source is positive*/ - if (first >= dst.prec) { + if (new_msb_pos >= (ssize_t)dst.prec) { /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ @@ -8663,7 +9028,7 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); } - else if (first < dst.prec) { + else { if (truncated && conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ @@ -8675,9 +9040,11 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx conv_ctx->u.conv.cb_struct.user_data); } - if (except_ret == H5T_CONV_UNHANDLED) + if (except_ret == H5T_CONV_UNHANDLED) { /*copy source value into it if case is ignored by user handler*/ - H5T__bit_copy(d, dst.offset, int_buf, (size_t)0, first + 1); + if (new_msb_pos >= 0) + H5T__bit_copy(d, dst.offset, int_buf, (size_t)0, (size_t)new_msb_pos + 1); + } else if (except_ret == H5T_CONV_HANDLED) { /*No need to reverse the order of destination because user handles it*/ reverse = false; @@ -8691,7 +9058,7 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } else if (H5T_SGN_2 == dst.u.i.sign) { /*Destination is signed*/ if (sign) { /*source is negative*/ - if (first < dst.prec - 1) { + if ((new_msb_pos >= 0) && ((size_t)new_msb_pos < dst.prec - 1)) { if (truncated && conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ @@ -8705,8 +9072,8 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx if (except_ret == H5T_CONV_UNHANDLED) { /*If this case ignored by user handler*/ /*Convert to integer representation. Equivalent to ~(value - 1).*/ - H5T__bit_dec(int_buf, (size_t)0, 8 * buf_size); - H5T__bit_neg(int_buf, (size_t)0, 8 * buf_size); + H5T__bit_dec(int_buf, (size_t)0, dst.prec); + H5T__bit_neg(int_buf, (size_t)0, dst.prec); /*copy source value into destination*/ H5T__bit_copy(d, dst.offset, int_buf, (size_t)0, dst.prec - 1); @@ -8749,7 +9116,7 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx } } else { /*source is positive*/ - if (first >= dst.prec - 1) { + if (new_msb_pos >= (ssize_t)dst.prec - 1) { /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ @@ -8773,7 +9140,7 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx goto next; } } - else if (first < dst.prec - 1) { + else if (new_msb_pos < (ssize_t)dst.prec - 1) { if (truncated && conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ /*reverse order first*/ @@ -8787,7 +9154,8 @@ H5T__conv_f_i(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx if (except_ret == H5T_CONV_UNHANDLED) { /*copy source value into it if case is ignored by user handler*/ - H5T__bit_copy(d, dst.offset, int_buf, (size_t)0, first + 1); + if (new_msb_pos >= 0) + H5T__bit_copy(d, dst.offset, int_buf, (size_t)0, (size_t)new_msb_pos + 1); } else if (except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, @@ -8963,7 +9331,7 @@ H5T__conv_i_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx /* Allocate enough space for the buffer holding temporary * converted value */ - buf_size = (src.prec > dst.u.f.msize ? src.prec : dst.u.f.msize) / 8 + 1; + buf_size = ((src.prec > dst.u.f.msize ? src.prec : dst.u.f.msize) + 7) / 8; int_buf = (uint8_t *)H5MM_calloc(buf_size); /* Allocate space for order-reversed source buffer */ @@ -9189,7 +9557,8 @@ H5T__conv_i_f(H5T_t *src_p, H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx goto padding; } } - else { + + if (!conv_ctx->u.conv.cb_struct.func || (except_ret == H5T_CONV_UNHANDLED)) { /*make destination infinity by setting exponent to maximal number and *mantissa to zero.*/ expo = expo_max; diff --git a/src/H5Tinit_float.c b/src/H5Tinit_float.c index 8384c3161df..de959b49735 100644 --- a/src/H5Tinit_float.c +++ b/src/H5Tinit_float.c @@ -54,8 +54,8 @@ * Purpose: This macro takes a floating point type like `double' and * and detects byte order, mantissa location, exponent location, * sign bit location, presence or absence of implicit mantissa - * bit, and exponent bias and initializes a detected_t structure - * with those properties. + * bit, and exponent bias and initializes a H5T_fpoint_det_t + * structure with those properties. * * Note that these operations can raise floating-point * exceptions and building with some compiler options @@ -307,14 +307,17 @@ H5T__fix_order(int n, int last, int *perm, H5T_order_t *order) if (last <= 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "failed to detect byte order"); - /* We have at least three points to consider */ - if (perm[last] < perm[last - 1] && perm[last - 1] < perm[last - 2]) { + if (perm[last] < perm[last - 1] && + /* Only check perm[last - 2] if we have more than 2 points to consider */ + ((last < 2) || (perm[last - 1] < perm[last - 2]))) { /* Little endian */ *order = H5T_ORDER_LE; for (int i = 0; i < n; i++) perm[i] = i; } - else if (perm[last] > perm[last - 1] && perm[last - 1] > perm[last - 2]) { + else if (perm[last] > perm[last - 1] && + /* Only check perm[last - 2] if we have more than 2 points to consider */ + ((last < 2) || (perm[last - 1] > perm[last - 2]))) { /* Big endian */ *order = H5T_ORDER_BE; for (int i = 0; i < n; i++) @@ -359,7 +362,7 @@ H5T__fix_order(int n, int last, int *perm, H5T_order_t *order) * Return: imp_bit will be set to 1 if the most significant bit * of the mantissa is discarded (ie, the mantissa has an * implicit `one' as the most significant bit). Otherwise, - * imp_bit will be set to zero zero. + * imp_bit will be set to zero. * * SUCCEED/FAIL *------------------------------------------------------------------------- @@ -571,6 +574,39 @@ H5T__init_native_float_types(void) */ H5T_native_order_g = det.order; +#ifdef H5_HAVE__FLOAT16 + /* H5T_NATIVE_FLOAT16 */ + + /* Get the type's characteristics */ + memset(&det, 0, sizeof(H5T_fpoint_det_t)); + DETECT_F(H5__Float16, det); + + /* Allocate and fill type structure */ + if (NULL == (dt = H5T__alloc())) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, "datatype allocation failed"); + dt->shared->state = H5T_STATE_IMMUTABLE; + dt->shared->type = H5T_FLOAT; + dt->shared->size = det.size; + dt->shared->u.atomic.order = det.order; + dt->shared->u.atomic.offset = det.offset; + dt->shared->u.atomic.prec = det.prec; + dt->shared->u.atomic.lsb_pad = H5T_PAD_ZERO; + dt->shared->u.atomic.msb_pad = H5T_PAD_ZERO; + dt->shared->u.atomic.u.f.sign = det.sign; + dt->shared->u.atomic.u.f.epos = det.epos; + dt->shared->u.atomic.u.f.esize = det.esize; + dt->shared->u.atomic.u.f.ebias = det.ebias; + dt->shared->u.atomic.u.f.mpos = det.mpos; + dt->shared->u.atomic.u.f.msize = det.msize; + dt->shared->u.atomic.u.f.norm = det.norm; + dt->shared->u.atomic.u.f.pad = H5T_PAD_ZERO; + + /* Register the type and set global variables */ + if ((H5T_NATIVE_FLOAT16_g = H5I_register(H5I_DATATYPE, dt, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "can't register ID for built-in datatype"); + H5T_NATIVE_FLOAT16_ALIGN_g = det.comp_align; +#endif + done: /* Clear any FE_INVALID exceptions from NaN handling */ if (feclearexcept(FE_INVALID) != 0) diff --git a/src/H5Tmodule.h b/src/H5Tmodule.h index f1b7b175f2e..35e748bac3f 100644 --- a/src/H5Tmodule.h +++ b/src/H5Tmodule.h @@ -712,6 +712,14 @@ * * * + * #H5T_NATIVE_FLOAT16 + * + * + * _Float16 + * + * + * + * * #H5T_NATIVE_FLOAT * * @@ -3732,8 +3740,8 @@ filled according to the value of this property. The padding can be: * datatypes. * * The currently supported text format used by #H5LTtext_to_dtype and #H5LTdtype_to_text is the - * data description language (DDL) and conforms to the \ref DDLBNF110. The portion of the - * \ref DDLBNF110 that defines HDF5 datatypes appears below. + * data description language (DDL) and conforms to the \ref DDLBNF114. The portion of the + * \ref DDLBNF114 that defines HDF5 datatypes appears below. * The definition of HDF5 datatypes from the HDF5 DDL * \code * ::= | | | @@ -3753,10 +3761,11 @@ filled according to the value of this property. The padding can be: * H5T_NATIVE_INT | H5T_NATIVE_UINT | * H5T_NATIVE_LONG | H5T_NATIVE_ULONG | * H5T_NATIVE_LLONG | H5T_NATIVE_ULLONG - * ::= H5T_IEEE_F32BE | H5T_IEEE_F32LE | + * ::= H5T_IEEE_F16BE | H5T_IEEE_F16LE | + * H5T_IEEE_F32BE | H5T_IEEE_F32LE | * H5T_IEEE_F64BE | H5T_IEEE_F64LE | - * H5T_NATIVE_FLOAT | H5T_NATIVE_DOUBLE | - * H5T_NATIVE_LDOUBLE + * H5T_NATIVE_FLOAT16 | H5T_NATIVE_FLOAT | + * H5T_NATIVE_DOUBLE | H5T_NATIVE_LDOUBLE *