From 16daa2904610bcbac70226bcb4c405d8c414b082 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Fri, 3 May 2024 11:30:44 -0500 Subject: [PATCH] Implement support for Complex number datatypes replace usages of word "complex" to distinguish from complex datatypes --- HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java | 3 +- c++/test/tattr.cpp | 8 +- config/cmake/ConfigureChecks.cmake | 25 + config/cmake/H5pubconf.h.in | 15 + config/cmake/HDFTests.c | 31 + doxygen/aliases | 2 +- doxygen/dox/DDLBNF114.dox | 14 +- .../examples/tables/predefinedDatatypes.dox | 12 + fortran/src/H5Tf.c | 15 +- fortran/src/H5Tff.F90 | 6 +- fortran/src/H5_f.c | 1 + fortran/src/H5_ff.F90 | 3 +- fortran/src/H5f90global.F90 | 2 + hl/src/H5LT.c | 7 + hl/src/H5LTanalyze.l | 5 + hl/src/H5LTparse.y | 4 + hl/tools/h5watch/h5watch.c | 33 +- java/src/hdf/hdf5lib/H5.java | 2 + java/src/hdf/hdf5lib/HDF5Constants.java | 16 + java/src/jni/h5Constants.c | 20 + java/src/jni/h5aImp.c | 42 +- java/src/jni/h5dImp.c | 42 +- java/src/jni/h5util.c | 32 + java/test/TestH5T.java | 2 + src/CMakeLists.txt | 13 +- src/H5Odtype.c | 82 + src/H5Pfapl.c | 6 +- src/H5Plapl.c | 6 +- src/H5S.c | 10 +- src/H5Spublic.h | 4 +- src/H5Sselect.c | 18 +- src/H5T.c | 577 +- src/H5Tbit.c | 2 +- src/H5Tcomplex.c | 153 + src/H5Tcompound.c | 7 + src/H5Tconv.c | 221 +- src/H5Tconv.h | 11 +- src/H5Tconv_bitfield.c | 7 +- src/H5Tconv_complex.c | 2265 +++++ src/H5Tconv_complex.h | 210 + src/H5Tconv_float.c | 2479 +++--- src/H5Tconv_float.h | 76 + src/H5Tconv_integer.c | 1412 ++- src/H5Tconv_integer.h | 123 + src/H5Tconv_macros.h | 496 +- src/H5Tconv_vlen.c | 3 +- src/H5Tdbg.c | 51 +- src/H5Tfields.c | 2 + src/H5Tfixed.c | 24 +- src/H5Tmodule.h | 15 +- src/H5Tnative.c | 139 +- src/H5Toffset.c | 7 + src/H5Tpkg.h | 84 +- src/H5Tprecis.c | 8 + src/H5Tpublic.h | 75 +- src/H5Tvisit.c | 11 +- src/H5Tvlen.c | 37 +- src/H5VL.c | 20 +- src/H5Znbit.c | 24 + src/H5Zscaleoffset.c | 4 + src/H5trace.c | 12 + src/Makefile.am | 7 +- test/API/H5_api_test_util.c | 10 + test/dt_arith.c | 7567 ++++++++++++----- test/dtypes.c | 1110 ++- test/tarray.c | 8 + test/tattr.c | 8 +- test/tfile.c | 16 +- tools/lib/h5diff_array.c | 123 +- tools/lib/h5diff_dset.c | 1 + tools/lib/h5diff_util.c | 4 + tools/lib/h5tools.c | 4 + tools/lib/h5tools.h | 108 +- tools/lib/h5tools_dump.c | 61 +- tools/lib/h5tools_str.c | 74 +- tools/lib/h5tools_type.c | 8 + tools/src/h5dump/h5dump_ddl.c | 17 +- tools/src/h5dump/h5dump_xml.c | 244 +- tools/src/h5import/h5import.c | 4 + tools/src/h5ls/h5ls.c | 96 +- tools/test/h5diff/h5diffgentest.c | 4 +- tools/test/h5dump/CMakeTests.cmake | 12 + tools/test/h5dump/CMakeTestsXML.cmake | 8 + tools/test/h5dump/expected/tcomplex.ddl | 421 + tools/test/h5dump/expected/tcomplex_be.ddl | 421 + .../test/h5dump/expected/tcomplex_be_info.ddl | 124 + tools/test/h5dump/expected/tcomplex_info.ddl | 124 + .../test/h5dump/expected/xml/tcomplex.h5.xml | 644 ++ .../h5dump/expected/xml/tcomplex_be.h5.xml | 644 ++ tools/test/h5dump/h5dumpgentest.c | 271 +- tools/test/h5dump/testfiles/tcomplex.h5 | Bin 0 -> 15552 bytes tools/test/h5dump/testfiles/tcomplex_be.h5 | Bin 0 -> 15552 bytes tools/test/h5dump/testh5dump.sh.in | 12 + tools/test/h5dump/testh5dumpxml.sh.in | 6 + tools/test/h5ls/CMakeTests.cmake | 8 + tools/test/h5ls/expected/tcomplex.ls | 36 + tools/test/h5ls/expected/tcomplex_be.ls | 48 + tools/test/h5ls/testh5ls.sh.in | 8 + tools/test/h5repack/h5repacktst.c | 2 +- 99 files changed, 17266 insertions(+), 4033 deletions(-) create mode 100644 src/H5Tcomplex.c create mode 100644 src/H5Tconv_complex.c create mode 100644 src/H5Tconv_complex.h create mode 100644 tools/test/h5dump/expected/tcomplex.ddl create mode 100644 tools/test/h5dump/expected/tcomplex_be.ddl create mode 100644 tools/test/h5dump/expected/tcomplex_be_info.ddl create mode 100644 tools/test/h5dump/expected/tcomplex_info.ddl create mode 100644 tools/test/h5dump/expected/xml/tcomplex.h5.xml create mode 100644 tools/test/h5dump/expected/xml/tcomplex_be.h5.xml create mode 100644 tools/test/h5dump/testfiles/tcomplex.h5 create mode 100644 tools/test/h5dump/testfiles/tcomplex_be.h5 create mode 100644 tools/test/h5ls/expected/tcomplex.ls create mode 100644 tools/test/h5ls/expected/tcomplex_be.ls diff --git a/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java b/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java index cd26a96e25b..db46cf38663 100644 --- a/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java +++ b/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java @@ -47,7 +47,8 @@ enum H5T_class { H5T_ENUM(HDF5Constants.H5T_ENUM), // enumeration types H5T_VLEN(HDF5Constants.H5T_VLEN), // Variable-Length types H5T_ARRAY(HDF5Constants.H5T_ARRAY), // Array types - H5T_NCLASSES(11); // this must be last + H5T_COMPLEX(HDF5Constants.H5T_COMPLEX), // Complex number types + H5T_NCLASSES(12); // this must be last private static final Map lookup = new HashMap(); diff --git a/c++/test/tattr.cpp b/c++/test/tattr.cpp index 5135e0c7fa7..0d5281f65ca 100644 --- a/c++/test/tattr.cpp +++ b/c++/test/tattr.cpp @@ -632,7 +632,7 @@ test_attr_compound_write(FileAccPropList &fapl) hsize_t dims2[] = {ATTR4_DIM1, ATTR4_DIM2}; DataSpace sid2(ATTR4_RANK, dims2); - // Create complex attribute for the dataset + // Create compound attribute for the dataset Attribute attr = dataset.createAttribute(ATTR4_NAME, comp_type, sid2); // Try to create the same attribute again (should fail) @@ -643,7 +643,7 @@ test_attr_compound_write(FileAccPropList &fapl) { } // do nothing, exception expected - // Write complex attribute data + // Write compound attribute data attr.write(comp_type, attr_data4); PASSED(); @@ -2001,8 +2001,8 @@ test_attr() test_attr_rename(curr_fapl); // Test renaming attribute test_attr_basic_read(curr_fapl); // Test basic H5A reading code - test_attr_compound_write(curr_fapl); // Test complex datatype H5A writing code - test_attr_compound_read(curr_fapl); // Test complex datatype H5A reading code + test_attr_compound_write(curr_fapl); // Test compound datatype H5A writing code + test_attr_compound_read(curr_fapl); // Test compound datatype H5A reading code test_attr_scalar_write(curr_fapl); // Test scalar dataspace H5A writing code test_attr_scalar_read(curr_fapl); // Test scalar dataspace H5A reading code diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake index af2d13e5180..20e077ad64e 100644 --- a/config/cmake/ConfigureChecks.cmake +++ b/config/cmake/ConfigureChecks.cmake @@ -816,6 +816,31 @@ macro (H5ConversionTests TEST def msg) endif () endmacro () +#----------------------------------------------------------------------------- +# Check for complex number support +#----------------------------------------------------------------------------- +message (STATUS "Checking if complex number support is available") +HDF_CHECK_TYPE_SIZE ("float _Complex" ${HDF_PREFIX}_SIZEOF_FLOAT_COMPLEX) +HDF_CHECK_TYPE_SIZE ("double _Complex" ${HDF_PREFIX}_SIZEOF_DOUBLE_COMPLEX) +HDF_CHECK_TYPE_SIZE ("long double _Complex" ${HDF_PREFIX}_SIZEOF_LONG_DOUBLE_COMPLEX) + +if (${HDF_PREFIX}_SIZEOF_FLOAT_COMPLEX AND ${HDF_PREFIX}_SIZEOF_DOUBLE_COMPLEX AND + ${HDF_PREFIX}_SIZEOF_LONG_DOUBLE_COMPLEX) + # Check if __STDC_NO_COMPLEX__ macro is defined, in which case complex number + # support is not available + HDF_FUNCTION_TEST (HAVE_STDC_NO_COMPLEX) + + if (NOT H5_HAVE_STDC_NO_COMPLEX) + # TODO: imaginary number support + + set (${HDF_PREFIX}_HAVE_COMPLEX_NUMBERS 1) + else () + message (STATUS "Complex number support has been disabled since __STDC_NO_COMPLEX__ is defined") + endif () +else () + message (STATUS "Complex number support has been disabled since the C types were not found") +endif () + #----------------------------------------------------------------------------- # Check various conversion capabilities #----------------------------------------------------------------------------- diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index c6e3a619162..8f07ea18e4b 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -110,6 +110,9 @@ /* Define to 1 if CLOCK_MONOTONIC_COARSE is available */ #cmakedefine H5_HAVE_CLOCK_MONOTONIC_COARSE @H5_HAVE_CLOCK_MONOTONIC_COARSE@ +/* Define if complex number support is available */ +#cmakedefine H5_HAVE_COMPLEX_NUMBERS @H5_HAVE_COMPLEX_NUMBERS@ + /* Define to 1 if you have the header file. */ #cmakedefine H5_HAVE_CURL_CURL_H @H5_HAVE_CURL_H@ @@ -445,9 +448,15 @@ /* The size of `double', as computed by sizeof. */ #cmakedefine H5_SIZEOF_DOUBLE @H5_SIZEOF_DOUBLE@ +/* The size of `double _Complex', as computed by sizeof. */ +#cmakedefine H5_SIZEOF_DOUBLE_COMPLEX @H5_SIZEOF_DOUBLE_COMPLEX@ + /* The size of `float', as computed by sizeof. */ #cmakedefine H5_SIZEOF_FLOAT @H5_SIZEOF_FLOAT@ +/* The size of `float _Complex', as computed by sizeof. */ +#cmakedefine H5_SIZEOF_FLOAT_COMPLEX @H5_SIZEOF_FLOAT_COMPLEX@ + /* The size of `int', as computed by sizeof. */ #cmakedefine H5_SIZEOF_INT @H5_SIZEOF_INT@ @@ -501,6 +510,9 @@ /* The size of `long double', as computed by sizeof. */ #cmakedefine H5_SIZEOF_LONG_DOUBLE @H5_SIZEOF_LONG_DOUBLE@ +/* The size of `long double _Complex', as computed by sizeof. */ +#cmakedefine H5_SIZEOF_LONG_DOUBLE_COMPLEX @H5_SIZEOF_LONG_DOUBLE_COMPLEX@ + #else /* On Apple, to support Universal Binaries (where multiple CPU @@ -520,10 +532,13 @@ # if defined(__i386__) || defined(__x86_64__) #define H5_SIZEOF_LONG_DOUBLE 16 + #define H5_SIZEOF_LONG_DOUBLE_COMPLEX 32 # elif defined(__aarch64__) #define H5_SIZEOF_LONG_DOUBLE 8 + #define H5_SIZEOF_LONG_DOUBLE_COMPLEX 16 # else #cmakedefine H5_SIZEOF_LONG_DOUBLE @H5_SIZEOF_LONG_DOUBLE@ + #cmakedefine H5_SIZEOF_LONG_DOUBLE_COMPLEX @H5_SIZEOF_LONG_DOUBLE_COMPLEX@ # endif #endif diff --git a/config/cmake/HDFTests.c b/config/cmake/HDFTests.c index 8d0e78f46b7..7f9ca7684c1 100644 --- a/config/cmake/HDFTests.c +++ b/config/cmake/HDFTests.c @@ -118,3 +118,34 @@ main(void) #endif } #endif + +#ifdef HAVE_STDC_NO_COMPLEX +#ifndef __STDC_NO_COMPLEX__ +#error "__STDC_NO_COMPLEX__ not defined" +#else +int +main(void) +{ + return 0; +} +#endif +#endif + +#ifdef HAVE_COMPLEX_NUMBERS +#include + +int +main(void) +{ + float _Complex z1 = 1.0f + 3.0f * I; + double _Complex z2 = 2.0 + 4.0 * I; + long double _Complex z3 = 3.0L + 5.0L * I; + float r1 = creal(z1); + float i1 = cimag(z1); + double r2 = creal(z2); + double i2 = cimage(z2); + long double r3 = creal(z3); + long double i3 = cimag(z3); + return 0; +} +#endif diff --git a/doxygen/aliases b/doxygen/aliases index e3ec6438021..d6c244ff0a6 100644 --- a/doxygen/aliases +++ b/doxygen/aliases @@ -370,7 +370,7 @@ ALIASES += ref_rfc20040811="Conve ALIASES += click4more="(Click on a enumerator, field, or type for more information.)" ALIASES += csets="
#H5T_CSET_ASCIIUS ASCII
#H5T_CSET_UTF8UTF-8 Unicode encoding
" -ALIASES += datatype_class=" \li #H5T_INTEGER \li #H5T_FLOAT \li #H5T_STRING \li #H5T_BITFIELD \li #H5T_OPAQUE \li #H5T_COMPOUND \li #H5T_REFERENCE \li #H5T_ENUM \li #H5T_VLEN \li #H5T_ARRAY" +ALIASES += datatype_class=" \li #H5T_INTEGER \li #H5T_FLOAT \li #H5T_STRING \li #H5T_BITFIELD \li #H5T_OPAQUE \li #H5T_COMPOUND \li #H5T_REFERENCE \li #H5T_ENUM \li #H5T_VLEN \li #H5T_ARRAY \li #H5T_COMPLEX" ALIASES += file_access="
#H5F_ACC_RDWRFile was opened with read/write access.
#H5F_ACC_RDONLYFile was opened with read-only access.
#H5F_ACC_SWMR_WRITEFile was opened with read/write access for a single-writer/multiple-reader (SWMR) scenario. Note that the writer process must also open the file with the #H5F_ACC_RDWR flag.
#H5F_ACC_SWMR_READFile was opened with read-only access for a single-writer/multiple-reader (SWMR) scenario. Note that the reader process must also open the file with the #H5F_ACC_RDONLY flag.
" ALIASES += id_types="
#H5I_FILEFile
#H5I_GROUPGroup
#H5I_DATATYPEDatatype
#H5I_DATASPACEDataspace
#H5I_DATASETDataset
#H5I_ATTRAttribute
" ALIASES += indexes="
#H5_INDEX_NAMELexicographic order on name
#H5_INDEX_CRT_ORDERIndex on creation order
" diff --git a/doxygen/dox/DDLBNF114.dox b/doxygen/dox/DDLBNF114.dox index 61e9157e560..d7914d71f1a 100644 --- a/doxygen/dox/DDLBNF114.dox +++ b/doxygen/dox/DDLBNF114.dox @@ -1,4 +1,4 @@ -/** \page DDLBNF114 DDL in BNF for HDF5 1.14.4 and above +/** \page DDLBNF114 DDL in BNF for HDF5 1.14.5 and above \todo Revise this & break it up! @@ -63,7 +63,8 @@ This section contains a brief explanation of the symbols used in the DDL. * } - ::= | | | + ::= | | | | + ::= DATATYPE { @@ -169,6 +170,15 @@ This section contains a brief explanation of the symbols used in the DDL. ::= + ::= H5T_COMPLEX { } | + H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_DOUBLE_COMPLEX | + H5T_NATIVE_LDOUBLE_COMPLEX + + ::= +// Currently complex number datatypes can only hold homogeneous floating-point +// type data, but they may be expanded in the future to hold heterogeneous +// floating-point type data or even non-floating-point type data + ::= + ::= / diff --git a/doxygen/examples/tables/predefinedDatatypes.dox b/doxygen/examples/tables/predefinedDatatypes.dox index 6cf044af5d4..1743532bc22 100644 --- a/doxygen/examples/tables/predefinedDatatypes.dox +++ b/doxygen/examples/tables/predefinedDatatypes.dox @@ -489,6 +489,18 @@ C-style long double +#H5T_NATIVE_FLOAT_COMPLEX +C-style float _Complex (May be H5I_INVALID_HID if platform doesn't support float _Complex type) + + +#H5T_NATIVE_DOUBLE_COMPLEX +C-style double _Complex (May be H5I_INVALID_HID if platform doesn't support double _Complex type) + + +#H5T_NATIVE_LDOUBLE_COMPLEX +C-style long double _Complex (May be H5I_INVALID_HID if platform doesn't support long double _Complex type) + + #H5T_NATIVE_B8 8-bit bitfield based on native types diff --git a/fortran/src/H5Tf.c b/fortran/src/H5Tf.c index 393873e110b..746c21deb19 100644 --- a/fortran/src/H5Tf.c +++ b/fortran/src/H5Tf.c @@ -212,11 +212,12 @@ h5tequal_c(hid_t_f *type1_id, hid_t_f *type2_id, int_f *c_flag) * H5T_STRING_F (3) * H5T_BITFIELD_F (4) * H5T_OPAQUE_F (5) - * H5T_COMPOUNDF (6) + * H5T_COMPOUND_F (6) * H5T_REFERENCE_F (7) * H5T_ENUM_F (8) * H5T_VLEN_F (9) * H5T_ARRAY_F (10) + * H5T_COMPLEX_F (11) * RETURNS * 0 on success, -1 on failure * SOURCE @@ -239,17 +240,7 @@ h5tget_class_c(hid_t_f *type_id, int_f *classtype) return ret_value; } *classtype = c_classtype; - /* - if (c_classtype == H5T_INTEGER) *classtype = H5T_INTEGER_F; - if (c_classtype == H5T_FLOAT) *classtype = H5T_FLOAT_F; - if (c_classtype == H5T_TIME) *classtype = H5T_TIME_F; - if (c_classtype == H5T_STRING) *classtype = H5T_STRING_F; - if (c_classtype == H5T_BITFIELD) *classtype = H5T_BITFIELD_F; - if (c_classtype == H5T_OPAQUE) *classtype = H5T_OPAQUE_F; - if (c_classtype == H5T_COMPOUND) *classtype = H5T_COMPOUND_F; - if (c_classtype == H5T_REFERENCE) *classtype = H5T_REFERENCE_F; - if (c_classtype == H5T_ENUM) *classtype = H5T_ENUM_F; - */ + return ret_value; } diff --git a/fortran/src/H5Tff.F90 b/fortran/src/H5Tff.F90 index b93e3c3a03c..7c1e84a60e7 100644 --- a/fortran/src/H5Tff.F90 +++ b/fortran/src/H5Tff.F90 @@ -267,6 +267,7 @@ END SUBROUTINE h5tclose_f !! \li H5T_ENUM_F !! \li H5T_VLEN_F !! \li H5T_ARRAY_F +!! \li H5T_COMPLEX_F !! \param hdferr \fortran_error !! !! See C API: @ref H5Tget_class() @@ -1726,9 +1727,9 @@ END SUBROUTINE h5tis_variable_str_f !! !! \brief Returns datatype class of compound datatype member. !! -!! \param type_id Datartpe identifier. +!! \param type_id Datatype identifier. !! \param member_no Index of compound datatype member. -!! \param class Class type for compound dadtype member. Valid classes: +!! \param class Class type for compound datatype member. Valid classes: !! \li H5T_NO_CLASS_F (error) !! \li H5T_INTEGER_F !! \li H5T_FLOAT_F @@ -1741,6 +1742,7 @@ END SUBROUTINE h5tis_variable_str_f !! \li H5T_ENUM_F !! \li H5T_VLEN_F !! \li H5T_ARRAY_F +!! \li H5T_COMPLEX_F !! \param hdferr \fortran_error !! !! See C API: @ref H5Tget_member_class() diff --git a/fortran/src/H5_f.c b/fortran/src/H5_f.c index 530068ba880..2f8351f7545 100644 --- a/fortran/src/H5_f.c +++ b/fortran/src/H5_f.c @@ -847,6 +847,7 @@ h5init_flags_c(int_f *h5d_flags, size_t_f *h5d_size_flags, int_f *h5e_flags, hid h5t_flags[32] = (int_f)H5T_ARRAY; h5t_flags[33] = (int_f)H5T_DIR_ASCEND; h5t_flags[34] = (int_f)H5T_DIR_DESCEND; + h5t_flags[35] = (int_f)H5T_COMPLEX; /* * H5VL flags diff --git a/fortran/src/H5_ff.F90 b/fortran/src/H5_ff.F90 index fb3bba67198..1b819af9c87 100644 --- a/fortran/src/H5_ff.F90 +++ b/fortran/src/H5_ff.F90 @@ -144,7 +144,7 @@ MODULE H5LIB ! ! H5T flags declaration ! - INTEGER, PARAMETER :: H5T_FLAGS_LEN = 35 + INTEGER, PARAMETER :: H5T_FLAGS_LEN = 36 INTEGER, DIMENSION(1:H5T_FLAGS_LEN) :: H5T_flags ! ! H5VL flags declaration @@ -704,6 +704,7 @@ END FUNCTION h5init1_flags_c H5T_ARRAY_F = H5T_flags(33) H5T_DIR_ASCEND_F = H5T_flags(34) H5T_DIR_DESCEND_F = H5T_flags(35) + H5T_COMPLEX_F = H5T_flags(36) ! ! H5VL flags ! diff --git a/fortran/src/H5f90global.F90 b/fortran/src/H5f90global.F90 index 4794bdc83c8..ececaa8ddab 100644 --- a/fortran/src/H5f90global.F90 +++ b/fortran/src/H5f90global.F90 @@ -861,6 +861,7 @@ MODULE H5GLOBAL !DEC$ATTRIBUTES DLLEXPORT :: H5T_ENUM_F !DEC$ATTRIBUTES DLLEXPORT :: H5T_VLEN_F !DEC$ATTRIBUTES DLLEXPORT :: H5T_ARRAY_F + !DEC$ATTRIBUTES DLLEXPORT :: H5T_COMPLEX_F !DEC$ATTRIBUTES DLLEXPORT :: H5T_ORDER_LE_F !DEC$ATTRIBUTES DLLEXPORT :: H5T_ORDER_BE_F !DEC$ATTRIBUTES DLLEXPORT :: H5T_ORDER_VAX_F @@ -899,6 +900,7 @@ MODULE H5GLOBAL INTEGER :: H5T_ENUM_F !< H5T_ENUM INTEGER :: H5T_VLEN_F !< H5T_VLEN INTEGER :: H5T_ARRAY_F !< H5T_ARRAY + INTEGER :: H5T_COMPLEX_F !< H5T_COMPLEX INTEGER :: H5T_ORDER_LE_F !< H5T_ORDER_LE INTEGER :: H5T_ORDER_BE_F !< H5T_ORDER_BE INTEGER :: H5T_ORDER_VAX_F !< H5T_ORDER_VAX diff --git a/hl/src/H5LT.c b/hl/src/H5LT.c index 7d44792fbc0..311b348920b 100644 --- a/hl/src/H5LT.c +++ b/hl/src/H5LT.c @@ -2753,6 +2753,13 @@ H5LT_dtype_to_text(hid_t dtype, char *dt_str, H5LT_lang_t lang, size_t *slen, bo break; } + case H5T_COMPLEX: + snprintf(dt_str, *slen, "H5T_COMPLEX {"); + + /* TODO */ + + break; + case H5T_TIME: snprintf(dt_str, *slen, "H5T_TIME: not yet implemented"); break; diff --git a/hl/src/H5LTanalyze.l b/hl/src/H5LTanalyze.l index a573f8137f3..99418c5b0ad 100644 --- a/hl/src/H5LTanalyze.l +++ b/hl/src/H5LTanalyze.l @@ -93,6 +93,10 @@ H5T_NATIVE_FLOAT {return hid(H5T_NATIVE_FLOAT_TOKEN);} H5T_NATIVE_DOUBLE {return hid(H5T_NATIVE_DOUBLE_TOKEN);} H5T_NATIVE_LDOUBLE {return hid(H5T_NATIVE_LDOUBLE_TOKEN);} +H5T_NATIVE_FLOAT_COMPLEX {return hid(H5T_NATIVE_FLOAT_COMPLEX_TOKEN);} +H5T_NATIVE_DOUBLE_COMPLEX {return hid(H5T_NATIVE_DOUBLE_COMPLEX_TOKEN);} +H5T_NATIVE_LDOUBLE_COMPLEX {return hid(H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN);} + H5T_STRING {return token(H5T_STRING_TOKEN);} STRSIZE {return token(STRSIZE_TOKEN);} STRPAD {return token(STRPAD_TOKEN);} @@ -111,6 +115,7 @@ H5T_COMPOUND {return token(H5T_COMPOUND_TOKEN);} H5T_ENUM {return token(H5T_ENUM_TOKEN);} H5T_ARRAY {return token(H5T_ARRAY_TOKEN);} H5T_VLEN {return token(H5T_VLEN_TOKEN);} +H5T_COMPLEX {return token(H5T_COMPLEX_TOKEN);} H5T_OPAQUE {return token(H5T_OPAQUE_TOKEN);} OPQ_SIZE {return token(OPQ_SIZE_TOKEN);} diff --git a/hl/src/H5LTparse.y b/hl/src/H5LTparse.y index 3a14e769419..844d8998cc3 100644 --- a/hl/src/H5LTparse.y +++ b/hl/src/H5LTparse.y @@ -83,6 +83,8 @@ static char* enum_memb_symbol; /*enum member symbol string*/ %token H5T_IEEE_F32BE_TOKEN H5T_IEEE_F32LE_TOKEN H5T_IEEE_F64BE_TOKEN H5T_IEEE_F64LE_TOKEN %token H5T_NATIVE_FLOAT16_TOKEN H5T_NATIVE_FLOAT_TOKEN H5T_NATIVE_DOUBLE_TOKEN H5T_NATIVE_LDOUBLE_TOKEN +%token H5T_NATIVE_FLOAT_COMPLEX_TOKEN H5T_NATIVE_DOUBLE_COMPLEX_TOKEN H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN + %token H5T_STRING_TOKEN STRSIZE_TOKEN STRPAD_TOKEN CSET_TOKEN CTYPE_TOKEN H5T_VARIABLE_TOKEN %token H5T_STR_NULLTERM_TOKEN H5T_STR_NULLPAD_TOKEN H5T_STR_SPACEPAD_TOKEN %token H5T_CSET_ASCII_TOKEN H5T_CSET_UTF8_TOKEN H5T_C_S1_TOKEN H5T_FORTRAN_S1_TOKEN @@ -93,6 +95,7 @@ static char* enum_memb_symbol; /*enum member symbol string*/ %token H5T_ENUM_TOKEN %token H5T_ARRAY_TOKEN %token H5T_VLEN_TOKEN +%token H5T_COMPLEX_TOKEN %token STRING %token NUMBER @@ -106,6 +109,7 @@ ddl_type : atomic_type | compound_type | array_type | vlen_type + | complex_type ; atomic_type : integer_type | fp_type diff --git a/hl/tools/h5watch/h5watch.c b/hl/tools/h5watch/h5watch.c index b4dd62fd70c..0d51305ae6c 100644 --- a/hl/tools/h5watch/h5watch.c +++ b/hl/tools/h5watch/h5watch.c @@ -94,16 +94,21 @@ static struct h5_long_options l_opts[] = {{"help", no_arg, 'h'}, {"hel", static herr_t doprint(hid_t did, const hsize_t *start, const hsize_t *block, int rank) { - h5tools_context_t ctx; /* print context */ - h5tool_format_t info; /* Format info for the tools library */ - static char fmt_double[16], fmt_float[16]; /* Format info */ - struct subset_t subset; /* Subsetting info */ - hsize_t ss_start[H5S_MAX_RANK]; /* Info for hyperslab */ - hsize_t ss_stride[H5S_MAX_RANK]; /* Info for hyperslab */ - hsize_t ss_block[H5S_MAX_RANK]; /* Info for hyperslab */ - hsize_t ss_count[H5S_MAX_RANK]; /* Info for hyperslab */ - int i; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t info; /* Format info for the tools library */ + static char fmt_ldouble[16]; /* Format info */ + static char fmt_double[16]; /* Format info */ + static char fmt_float[16]; /* Format info */ + static char fmt_ldouble_complex[32]; /* Format info */ + static char fmt_double_complex[32]; /* Format info */ + static char fmt_float_complex[16]; /* Format info */ + struct subset_t subset; /* Subsetting info */ + hsize_t ss_start[H5S_MAX_RANK]; /* Info for hyperslab */ + hsize_t ss_stride[H5S_MAX_RANK]; /* Info for hyperslab */ + hsize_t ss_block[H5S_MAX_RANK]; /* Info for hyperslab */ + hsize_t ss_count[H5S_MAX_RANK]; /* Info for hyperslab */ + int i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ /* Subsetting information for the tools library printing routines */ subset.start.data = ss_start; @@ -175,6 +180,14 @@ doprint(hid_t did, const hsize_t *start, const hsize_t *block, int rank) info.fmt_float = fmt_float; snprintf(fmt_double, sizeof(fmt_double), "%%1.%dg", DBL_DIG); info.fmt_double = fmt_double; + snprintf(fmt_ldouble, sizeof(fmt_ldouble), "%%1.%dLg", LDBL_DIG); + info.fmt_ldouble = fmt_ldouble; + snprintf(fmt_float_complex, sizeof(fmt_float_complex), "%%1.%dg%%+1.%dgi", FLT_DIG, FLT_DIG); + info.fmt_float_complex = fmt_float_complex; + snprintf(fmt_double_complex, sizeof(fmt_double_complex), "%%1.%dg%%+1.%dgi", DBL_DIG, DBL_DIG); + info.fmt_double_complex = fmt_double_complex; + snprintf(fmt_ldouble_complex, sizeof(fmt_ldouble_complex), "%%1.%dLg%%+1.%dLgi", LDBL_DIG, LDBL_DIG); + info.fmt_ldouble_complex = fmt_ldouble_complex; info.dset_format = "DSET-%s "; info.dset_hidefileno = 0; diff --git a/java/src/hdf/hdf5lib/H5.java b/java/src/hdf/hdf5lib/H5.java index 388ba18f87a..25fa61d7284 100644 --- a/java/src/hdf/hdf5lib/H5.java +++ b/java/src/hdf/hdf5lib/H5.java @@ -14250,6 +14250,8 @@ else if (HDF5Constants.H5T_VLEN == class_id) /* Variable-Length types */ retValue = "H5T_VLEN"; else if (HDF5Constants.H5T_ARRAY == class_id) /* Array types */ retValue = "H5T_ARRAY"; + else if (HDF5Constants.H5T_COMPLEX == class_id) /* Complex number types */ + retValue = "H5T_COMPLEX"; else retValue = "H5T_NO_CLASS"; diff --git a/java/src/hdf/hdf5lib/HDF5Constants.java b/java/src/hdf/hdf5lib/HDF5Constants.java index 55b6f4be913..b62fee46713 100644 --- a/java/src/hdf/hdf5lib/HDF5Constants.java +++ b/java/src/hdf/hdf5lib/HDF5Constants.java @@ -1041,6 +1041,8 @@ public class HDF5Constants { /** */ public static final long H5T_C_S1 = H5T_C_S1(); /** */ + public static final int H5T_COMPLEX = H5T_COMPLEX(); + /** */ public static final int H5T_COMPOUND = H5T_COMPOUND(); /** */ public static final int H5T_CONV_CONV = H5T_CONV_CONV(); @@ -1177,10 +1179,14 @@ public class HDF5Constants { /** */ public static final long H5T_NATIVE_DOUBLE = H5T_NATIVE_DOUBLE(); /** */ + public static final long H5T_NATIVE_DOUBLE_COMPLEX = H5T_NATIVE_DOUBLE_COMPLEX(); + /** */ public static final long H5T_NATIVE_FLOAT = H5T_NATIVE_FLOAT(); /** */ public static final long H5T_NATIVE_FLOAT16 = H5T_NATIVE_FLOAT16(); /** */ + public static final long H5T_NATIVE_FLOAT_COMPLEX = H5T_NATIVE_FLOAT_COMPLEX(); + /** */ public static final long H5T_NATIVE_HADDR = H5T_NATIVE_HADDR(); /** */ public static final long H5T_NATIVE_HBOOL = H5T_NATIVE_HBOOL(); @@ -1223,6 +1229,8 @@ public class HDF5Constants { /** */ public static final long H5T_NATIVE_LONG = H5T_NATIVE_LONG(); /** */ + public static final long H5T_NATIVE_LDOUBLE_COMPLEX = H5T_NATIVE_LDOUBLE_COMPLEX(); + /** */ public static final long H5T_NATIVE_OPAQUE = H5T_NATIVE_OPAQUE(); /** */ public static final long H5T_NATIVE_SCHAR = H5T_NATIVE_SCHAR(); @@ -2532,6 +2540,8 @@ public class HDF5Constants { private static native final long H5T_C_S1(); + private static native final int H5T_COMPLEX(); + private static native final int H5T_COMPOUND(); private static native final int H5T_CONV_CONV(); @@ -2668,10 +2678,14 @@ public class HDF5Constants { private static native final long H5T_NATIVE_DOUBLE(); + private static native final long H5T_NATIVE_DOUBLE_COMPLEX(); + private static native final long H5T_NATIVE_FLOAT(); private static native final long H5T_NATIVE_FLOAT16(); + private static native final long H5T_NATIVE_FLOAT_COMPLEX(); + private static native final long H5T_NATIVE_HADDR(); private static native final long H5T_NATIVE_HBOOL(); @@ -2714,6 +2728,8 @@ public class HDF5Constants { private static native final long H5T_NATIVE_LONG(); + private static native final long H5T_NATIVE_LDOUBLE_COMPLEX(); + private static native final long H5T_NATIVE_OPAQUE(); private static native final long H5T_NATIVE_SCHAR(); diff --git a/java/src/jni/h5Constants.c b/java/src/jni/h5Constants.c index 41395a4413f..8e958e55a04 100644 --- a/java/src/jni/h5Constants.c +++ b/java/src/jni/h5Constants.c @@ -2543,6 +2543,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1C_1S1(JNIEnv *env, jclass cls) return H5T_C_S1; } JNIEXPORT jint JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX; +} +JNIEXPORT jint JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPOUND(JNIEnv *env, jclass cls) { return H5T_COMPOUND; @@ -2883,6 +2888,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1DOUBLE(JNIEnv *env, jclass cls) return H5T_NATIVE_DOUBLE; } JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1DOUBLE_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_NATIVE_DOUBLE_COMPLEX; +} +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1FLOAT(JNIEnv *env, jclass cls) { return H5T_NATIVE_FLOAT; @@ -2893,6 +2903,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1FLOAT16(JNIEnv *env, jclass cls) return H5T_NATIVE_FLOAT16; } JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1FLOAT_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_NATIVE_FLOAT_COMPLEX; +} +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1HADDR(JNIEnv *env, jclass cls) { return H5T_NATIVE_HADDR; @@ -2998,6 +3013,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1LONG(JNIEnv *env, jclass cls) return H5T_NATIVE_LONG; } JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1LDOUBLE_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_NATIVE_LDOUBLE_COMPLEX; +} +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1OPAQUE(JNIEnv *env, jclass cls) { return H5T_NATIVE_OPAQUE; diff --git a/java/src/jni/h5aImp.c b/java/src/jni/h5aImp.c index 54c862eff6c..73b4d0fef18 100644 --- a/java/src/jni/h5aImp.c +++ b/java/src/jni/h5aImp.c @@ -1243,12 +1243,13 @@ Java_hdf_hdf5lib_H5_H5Aread_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1272,13 +1273,13 @@ Java_hdf_hdf5lib_H5_H5Aread_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1289,7 +1290,7 @@ Java_hdf_hdf5lib_H5_H5Aread_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5AreadVL_asstr(env, (hid_t)attr_id, (hid_t)mem_type_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); } @@ -1447,12 +1448,13 @@ Java_hdf_hdf5lib_H5_H5Awrite_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1476,13 +1478,13 @@ Java_hdf_hdf5lib_H5_H5Awrite_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1493,7 +1495,7 @@ Java_hdf_hdf5lib_H5_H5Awrite_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5AwriteVL_asstr(env, (hid_t)attr_id, (hid_t)mem_type_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); } diff --git a/java/src/jni/h5dImp.c b/java/src/jni/h5dImp.c index f6318b222d4..7447eca2e88 100644 --- a/java/src/jni/h5dImp.c +++ b/java/src/jni/h5dImp.c @@ -1259,12 +1259,13 @@ Java_hdf_hdf5lib_H5_H5Dread_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_i jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1288,13 +1289,13 @@ Java_hdf_hdf5lib_H5_H5Dread_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_i if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1305,7 +1306,7 @@ Java_hdf_hdf5lib_H5_H5Dread_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_i isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5DreadVL_asstr(env, (hid_t)dataset_id, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)xfer_plist_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); @@ -1484,12 +1485,13 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_ jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1513,13 +1515,13 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_ if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1530,7 +1532,7 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_ isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5DwriteVL_asstr(env, (hid_t)dataset_id, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)xfer_plist_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); diff --git a/java/src/jni/h5util.c b/java/src/jni/h5util.c index 9c441729a39..90fc92cefbd 100644 --- a/java/src/jni/h5util.c +++ b/java/src/jni/h5util.c @@ -620,6 +620,10 @@ h5str_convert(JNIEnv *env, char **in_str, hid_t container, hid_t tid, void *out_ break; } + case H5T_COMPLEX: + /* TODO */ + break; + case H5T_NCLASSES: case H5T_NO_CLASS: { H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_convert: invalid datatype class"); @@ -1482,6 +1486,10 @@ h5str_sprintf(JNIEnv *env, h5str_t *out_str, hid_t container, hid_t tid, void *i break; } + case H5T_COMPLEX: + /* TODO */ + break; + case H5T_NO_CLASS: case H5T_NCLASSES: { H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_sprintf: invalid datatype class"); @@ -2116,6 +2124,10 @@ h5str_get_little_endian_type(hid_t tid) break; } + case H5T_COMPLEX: + /* TODO */ + break; + case H5T_NO_CLASS: case H5T_NCLASSES: { goto done; @@ -2212,6 +2224,10 @@ h5str_get_big_endian_type(hid_t tid) break; } + case H5T_COMPLEX: + /* TODO */ + break; + case H5T_NO_CLASS: case H5T_NCLASSES: { goto done; @@ -2468,6 +2484,10 @@ h5str_render_bin_output(FILE *stream, hid_t container, hid_t tid, void *_mem, hs break; } + case H5T_COMPLEX: + /* TODO */ + break; + case H5T_NO_CLASS: case H5T_NCLASSES: { ret_value = FAIL; @@ -4312,6 +4332,9 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo break; } /* H5T_STRING */ + case H5T_COMPLEX: + /* TODO */ + break; case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: @@ -4536,6 +4559,9 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_ } break; } /* H5T_STRING */ + case H5T_COMPLEX: + /* TODO */ + break; case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: @@ -4758,6 +4784,9 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t } break; } + case H5T_COMPLEX: + /* TODO */ + break; case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: @@ -4920,6 +4949,9 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t } break; } + case H5T_COMPLEX: + /* TODO */ + break; case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: diff --git a/java/test/TestH5T.java b/java/test/TestH5T.java index 0121cc24297..ba76a613e6d 100644 --- a/java/test/TestH5T.java +++ b/java/test/TestH5T.java @@ -171,6 +171,8 @@ public void testH5Tarray_create() } } + /* TODO: add complex number support */ + @Test public void testH5Tget_array_ndims() { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6743a85ff7..6c47ed9c90d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -600,17 +600,19 @@ set (H5T_SOURCES ${HDF5_SRC_DIR}/H5Tarray.c ${HDF5_SRC_DIR}/H5Tbit.c ${HDF5_SRC_DIR}/H5Tcommit.c + ${HDF5_SRC_DIR}/H5Tcomplex.c ${HDF5_SRC_DIR}/H5Tcompound.c ${HDF5_SRC_DIR}/H5Tconv.c - ${HDF5_SRC_DIR}/H5Tconv_integer.c - ${HDF5_SRC_DIR}/H5Tconv_float.c - ${HDF5_SRC_DIR}/H5Tconv_string.c + ${HDF5_SRC_DIR}/H5Tconv_array.c ${HDF5_SRC_DIR}/H5Tconv_bitfield.c + ${HDF5_SRC_DIR}/H5Tconv_complex.c ${HDF5_SRC_DIR}/H5Tconv_compound.c - ${HDF5_SRC_DIR}/H5Tconv_reference.c ${HDF5_SRC_DIR}/H5Tconv_enum.c + ${HDF5_SRC_DIR}/H5Tconv_float.c + ${HDF5_SRC_DIR}/H5Tconv_integer.c + ${HDF5_SRC_DIR}/H5Tconv_reference.c + ${HDF5_SRC_DIR}/H5Tconv_string.c ${HDF5_SRC_DIR}/H5Tconv_vlen.c - ${HDF5_SRC_DIR}/H5Tconv_array.c ${HDF5_SRC_DIR}/H5Tcset.c ${HDF5_SRC_DIR}/H5Tdbg.c ${HDF5_SRC_DIR}/H5Tdeprec.c @@ -958,6 +960,7 @@ set (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5Tconv.h ${HDF5_SRC_DIR}/H5Tconv_array.h ${HDF5_SRC_DIR}/H5Tconv_bitfield.h + ${HDF5_SRC_DIR}/H5Tconv_complex.h ${HDF5_SRC_DIR}/H5Tconv_compound.h ${HDF5_SRC_DIR}/H5Tconv_enum.h ${HDF5_SRC_DIR}/H5Tconv_float.h diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 24671b02107..0eecb75ff64 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -830,6 +830,35 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t dt->shared->force_conv = true; break; + case H5T_COMPLEX: + /* + * Complex number datatypes... + */ + + /* Set whether the complex number datatype is homogeneous */ + dt->shared->u.cplx.homogeneous = (bool)(flags & 0x01); + + if (!dt->shared->u.cplx.homogeneous) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + + /* Set the form of the complex number datatype */ + dt->shared->u.cplx.form = (H5T_complex_form_t)((flags >> 1) & 0x03); + + if (dt->shared->u.cplx.form != H5T_COMPLEX_RECTANGULAR) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "only complex number datatypes in rectangular form are currently supported"); + + /* Decode the base datatype of the complex number */ + if (NULL == (dt->shared->parent = H5T__alloc())) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, + "unable to allocate complex number base datatype"); + if (H5O__dtype_decode_helper(ioflags, pp, dt->shared->parent, skip, p_end) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, + "unable to decode complex number base datatype"); + + break; + case H5T_NO_CLASS: case H5T_NCLASSES: default: @@ -1347,6 +1376,28 @@ H5O__dtype_encode_helper(uint8_t **pp, const H5T_t *dt) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, "unable to encode VL parent type"); break; + case H5T_COMPLEX: + if (!dt->shared->u.cplx.homogeneous) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + if (dt->shared->u.cplx.form != H5T_COMPLEX_RECTANGULAR) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, + "complex number datatypes not in rectangular form are currently unsupported"); + + /* Store whether complex number is homogeneous in first flag bit */ + if (dt->shared->u.cplx.homogeneous) + flags |= 0x01; + + /* Store complex number form in next two bits */ + flags = (unsigned)(flags | (((unsigned)dt->shared->u.cplx.form & 0x03) << 1)); + + /* Encode the base datatype of the complex number */ + if (H5O__dtype_encode_helper(pp, dt->shared->parent) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, + "unable to encode complex number base datatype"); + + break; + case H5T_NO_CLASS: case H5T_NCLASSES: default: @@ -1644,6 +1695,13 @@ H5O__dtype_size(const H5F_t *f, const void *_mesg) ret_value += H5O__dtype_size(f, dt->shared->parent); break; + case H5T_COMPLEX: + if (dt->shared->u.cplx.homogeneous) + ret_value += H5O__dtype_size(f, dt->shared->parent); + else + ret_value = 0; + break; + case H5T_NO_CLASS: case H5T_STRING: case H5T_REFERENCE: @@ -2001,6 +2059,10 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt s = "vlen"; break; + case H5T_COMPLEX: + s = "complex number"; + break; + case H5T_NO_CLASS: case H5T_NCLASSES: default: @@ -2244,6 +2306,26 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt fprintf(stream, "%*s%s\n", indent, "", "Base type:"); H5O__dtype_debug(f, dt->shared->parent, stream, indent + 3, MAX(0, fwidth - 3)); } /* end else if */ + else if (H5T_COMPLEX == dt->shared->type) { + switch (dt->shared->u.cplx.form) { + case H5T_COMPLEX_RECTANGULAR: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "rectangular"); + break; + case H5T_COMPLEX_POLAR: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "polar"); + break; + case H5T_COMPLEX_EXPONENTIAL: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "exponential"); + break; + default: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "invalid"); + break; + } + if (dt->shared->u.cplx.homogeneous) { + fprintf(stream, "%*s%s\n", indent, "", "Base type:"); + H5O__dtype_debug(f, dt->shared->parent, stream, indent + 3, MAX(0, fwidth - 3)); + } + } else { switch (dt->shared->u.atomic.order) { case H5T_ORDER_LE: diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index 3d4ca8b69eb..18b477f35cd 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -1461,14 +1461,14 @@ H5Pget_driver(hid_t plist_id) H5P_genplist_t *plist; /* Property list pointer */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) if (NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list"); /* Get the driver */ if ((ret_value = H5P_peek_driver(plist)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver"); + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't get driver"); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5Plapl.c b/src/H5Plapl.c index 64cd2996fc4..460d0842cca 100644 --- a/src/H5Plapl.c +++ b/src/H5Plapl.c @@ -1035,14 +1035,14 @@ H5Pget_elink_fapl(hid_t lapl_id) H5P_genplist_t *plist; /* Property list pointer */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* Get the plist structure */ if (NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) - HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "can't find object for ID"); + HGOTO_ERROR(H5E_ID, H5E_BADID, H5I_INVALID_HID, "can't find object for ID"); if (H5P_get(plist, H5L_ACS_ELINK_FAPL_NAME, &ret_value) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fapl for links"); + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't get fapl for links"); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5S.c b/src/H5S.c index 3b8a825ee8c..08000fff3da 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -328,23 +328,23 @@ H5Screate(H5S_class_t type) H5S_t *new_ds = NULL; /* New dataspace structure */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* Check args */ if (type <= H5S_NO_CLASS || type > H5S_NULL) /* don't allow complex dataspace yet */ - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dataspace type"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid dataspace type"); if (NULL == (new_ds = H5S_create(type))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create dataspace"); /* Register */ if ((ret_value = H5I_register(H5I_DATASPACE, new_ds, true)) < 0) - HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID"); + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID"); done: if (ret_value < 0) if (new_ds && H5S_close(new_ds) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace"); FUNC_LEAVE_API(ret_value) } /* end H5Screate() */ diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 3697374d49c..9d6fe6a226d 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -251,10 +251,10 @@ H5_DLL hid_t H5Scopy(hid_t space_id); * Further dataspace types may be added later. * * A scalar dataspace, #H5S_SCALAR, has a single element, though that - * element may be of a complex datatype, such as a compound or array + * element may be of a composite datatype, such as a compound or array * datatype. By convention, the rank of a scalar dataspace is always \p 0 * (zero); think of it geometrically as a single, dimensionless point, - * though that point can be complex. + * though that point can be composite. * * A simple dataspace, #H5S_SIMPLE, consists of a regular array of elements. * diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 5625de3aab4..651f73b6c03 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -2655,39 +2655,39 @@ H5Sselect_project_intersection(hid_t src_space_id, hid_t dst_space_id, hid_t src H5S_t *proj_space = NULL; /* Output dataspace */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* Check args */ if (NULL == (src_space = (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace"); if (NULL == (dst_space = (H5S_t *)H5I_object_verify(dst_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace"); if (NULL == (src_intersect_space = (H5S_t *)H5I_object_verify(src_intersect_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace"); /* Check numbers of points selected matches in source and destination */ if (H5S_GET_SELECT_NPOINTS(src_space) != H5S_GET_SELECT_NPOINTS(dst_space)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "number of points selected in source space does not match that in destination space"); /* Check numbers of dimensions matches in source and source intersect spaces */ if (H5S_GET_EXTENT_NDIMS(src_space) != H5S_GET_EXTENT_NDIMS(src_intersect_space)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "rank of source space does not match rank of source intersect space"); /* Perform operation */ if (H5S_select_project_intersection(src_space, dst_space, src_intersect_space, &proj_space, false) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "can't project dataspace intersection"); + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, H5I_INVALID_HID, "can't project dataspace intersection"); /* Register */ if ((ret_value = H5I_register(H5I_DATASPACE, proj_space, true)) < 0) - HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID"); + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID"); done: if (ret_value < 0) if (proj_space && H5S_close(proj_space) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace"); FUNC_LEAVE_API(ret_value) } /* end H5Sselect_project_intersection() */ diff --git a/src/H5T.c b/src/H5T.c index 23993b3d639..4092c0fe766 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -43,6 +43,10 @@ #include "H5VLprivate.h" /* Virtual Object Layer */ #include "H5VMprivate.h" /* Vectors and arrays */ +#ifdef H5_HAVE_COMPLEX_NUMBERS +#include +#endif + /* Datatype conversion functions */ #include "H5Tconv_integer.h" #include "H5Tconv_float.h" @@ -53,6 +57,7 @@ #include "H5Tconv_enum.h" #include "H5Tconv_vlen.h" #include "H5Tconv_array.h" +#include "H5Tconv_complex.h" /****************/ /* Local Macros */ @@ -469,30 +474,33 @@ 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_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_FLOAT_COMPLEX_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_DOUBLE_COMPLEX_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LDOUBLE_COMPLEX_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; @@ -538,20 +546,23 @@ size_t H5T_HOBJREF_ALIGN_g = 0; size_t H5T_HDSETREGREF_ALIGN_g = 0; size_t H5T_REF_ALIGN_g = 0; -size_t H5T_NATIVE_SCHAR_ALIGN_g = 0; -size_t H5T_NATIVE_UCHAR_ALIGN_g = 0; -size_t H5T_NATIVE_SHORT_ALIGN_g = 0; -size_t H5T_NATIVE_USHORT_ALIGN_g = 0; -size_t H5T_NATIVE_INT_ALIGN_g = 0; -size_t H5T_NATIVE_UINT_ALIGN_g = 0; -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; +size_t H5T_NATIVE_SCHAR_ALIGN_g = 0; +size_t H5T_NATIVE_UCHAR_ALIGN_g = 0; +size_t H5T_NATIVE_SHORT_ALIGN_g = 0; +size_t H5T_NATIVE_USHORT_ALIGN_g = 0; +size_t H5T_NATIVE_INT_ALIGN_g = 0; +size_t H5T_NATIVE_UINT_ALIGN_g = 0; +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; +size_t H5T_NATIVE_FLOAT_COMPLEX_ALIGN_g = 0; +size_t H5T_NATIVE_DOUBLE_COMPLEX_ALIGN_g = 0; +size_t H5T_NATIVE_LDOUBLE_COMPLEX_ALIGN_g = 0; /* Alignment constraints for C99 types */ size_t H5T_NATIVE_INT8_ALIGN_g = 0; @@ -593,10 +604,20 @@ size_t H5T_NATIVE_UINT_FAST64_ALIGN_g = 0; 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; -double H5T_NATIVE_DOUBLE_NEG_INF_g = 0.0; +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; +double H5T_NATIVE_DOUBLE_NEG_INF_g = 0.0; +long double H5T_NATIVE_LDOUBLE_POS_INF_g = 0.0L; +long double H5T_NATIVE_LDOUBLE_NEG_INF_g = 0.0L; +#ifdef H5_HAVE_COMPLEX_NUMBERS +float _Complex H5T_NATIVE_FLOAT_COMPLEX_POS_INF_g = 0.0F + 0.0F * (float _Complex)_Complex_I; +float _Complex H5T_NATIVE_FLOAT_COMPLEX_NEG_INF_g = 0.0F + 0.0F * (float _Complex)_Complex_I; +double _Complex H5T_NATIVE_DOUBLE_COMPLEX_POS_INF_g = 0.0 + 0.0 * (double _Complex)_Complex_I; +double _Complex H5T_NATIVE_DOUBLE_COMPLEX_NEG_INF_g = 0.0 + 0.0 * (double _Complex)_Complex_I; +long double _Complex H5T_NATIVE_LDOUBLE_COMPLEX_POS_INF_g = 0.0L + 0.0L * (long double _Complex)_Complex_I; +long double _Complex H5T_NATIVE_LDOUBLE_COMPLEX_NEG_INF_g = 0.0L + 0.0L * (long double _Complex)_Complex_I; +#endif /* Declare the free list for H5T_t's and H5T_shared_t's */ H5FL_DEFINE(H5T_t); @@ -745,6 +766,47 @@ H5T__init_inf(void) } /* end for */ } /* end if */ + /* Get the long double datatype */ + if (NULL == (dst_p = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_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_LDOUBLE_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_LDOUBLE_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 */ + #ifdef H5_HAVE__FLOAT16 /* Get the _Float16 datatype */ if (NULL == (dst_p = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT16_g))) @@ -788,6 +850,22 @@ H5T__init_inf(void) } /* end if */ #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + /* + * A complex number is considered to be infinite if any of its parts + * (real or imaginary) is infinite, so simply set the real part of + * the complex number positive/negative infinity values to the + * positive/negative infinity value for the base floating-point type. + * The imaginary part should be zeroed-out bits. + */ + memcpy(&H5T_NATIVE_FLOAT_COMPLEX_POS_INF_g, &H5T_NATIVE_FLOAT_POS_INF_g, sizeof(float)); + memcpy(&H5T_NATIVE_FLOAT_COMPLEX_NEG_INF_g, &H5T_NATIVE_FLOAT_NEG_INF_g, sizeof(float)); + memcpy(&H5T_NATIVE_DOUBLE_COMPLEX_POS_INF_g, &H5T_NATIVE_DOUBLE_POS_INF_g, sizeof(double)); + memcpy(&H5T_NATIVE_DOUBLE_COMPLEX_NEG_INF_g, &H5T_NATIVE_DOUBLE_NEG_INF_g, sizeof(double)); + memcpy(&H5T_NATIVE_LDOUBLE_COMPLEX_POS_INF_g, &H5T_NATIVE_LDOUBLE_POS_INF_g, sizeof(long double)); + memcpy(&H5T_NATIVE_LDOUBLE_COMPLEX_NEG_INF_g, &H5T_NATIVE_LDOUBLE_NEG_INF_g, sizeof(long double)); +#endif + done: FUNC_LEAVE_NOAPI(ret_value) } /* end H5T__init_inf() */ @@ -834,6 +912,7 @@ H5T_init(void) H5T_t *enum_type = NULL; /* Datatype structure for enum objects */ H5T_t *vlen = NULL; /* Datatype structure for vlen objects */ H5T_t *array = NULL; /* Datatype structure for array objects */ + H5T_t *cplx = NULL; /* Datatype structure for complex number objects */ H5T_t *objref = NULL; /* Datatype structure for deprecated reference objects */ H5T_t *regref = NULL; /* Datatype structure for deprecated region references */ H5T_t *ref = NULL; /* Datatype structure for opaque references */ @@ -843,6 +922,11 @@ H5T_init(void) 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 +#ifdef H5_HAVE_COMPLEX_NUMBERS + H5T_t *native_float_complex = NULL; /* Datatype structure for native float _Complex type */ + H5T_t *native_double_complex = NULL; /* Datatype structure for native double _Complex type */ + H5T_t *native_ldouble_complex = NULL; /* Datatype structure for native long double _Complex type */ #endif herr_t ret_value = SUCCEED; /* Return value */ @@ -860,6 +944,12 @@ H5T_init(void) if (H5T__init_native_float_types() < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize floating-point types"); +#ifdef H5_HAVE_COMPLEX_NUMBERS + /* Initialize native complex number datatypes */ + if (H5T__init_native_complex_types() < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize complex number types"); +#endif + /* Initialize all other native types */ if (H5T__init_native_internal() < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize integers"); @@ -895,6 +985,14 @@ H5T_init(void) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); if (NULL == (native_ldouble = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); +#ifdef H5_HAVE_COMPLEX_NUMBERS + if (NULL == (native_float_complex = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_COMPLEX_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (native_double_complex = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_COMPLEX_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (native_ldouble_complex = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_COMPLEX_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); +#endif /*------------------------------------------------------------ * Derived native types @@ -1132,20 +1230,30 @@ H5T_init(void) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); if (NULL == (array = H5T__array_create(native_int, 1, dim))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == (cplx = H5T__complex_create(native_float))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); status = 0; status |= H5T__register_int(H5T_PERS_SOFT, "i_i", fixedpt, fixedpt, H5T__conv_i_i); status |= H5T__register_int(H5T_PERS_SOFT, "i_f", fixedpt, floatpt, H5T__conv_i_f); + status |= H5T__register_int(H5T_PERS_SOFT, "i_complex", fixedpt, cplx, H5T__conv_i_complex); + status |= H5T__register_int(H5T_PERS_SOFT, "complex_i", cplx, fixedpt, H5T__conv_complex_i); status |= H5T__register_int(H5T_PERS_SOFT, "f_f", floatpt, floatpt, H5T__conv_f_f); status |= H5T__register_int(H5T_PERS_SOFT, "f_i", floatpt, fixedpt, H5T__conv_f_i); + status |= H5T__register_int(H5T_PERS_SOFT, "f_complex", floatpt, cplx, H5T__conv_f_complex); + status |= H5T__register_int(H5T_PERS_SOFT, "complex_f", cplx, floatpt, H5T__conv_complex_f); + status |= H5T__register_int(H5T_PERS_SOFT, "complex_complex", cplx, cplx, H5T__conv_complex); status |= H5T__register_int(H5T_PERS_SOFT, "s_s", string, string, H5T__conv_s_s); status |= H5T__register_int(H5T_PERS_SOFT, "b_b", bitfield, bitfield, H5T__conv_b_b); status |= H5T__register_int(H5T_PERS_SOFT, "ibo", fixedpt, fixedpt, H5T__conv_order); status |= H5T__register_int(H5T_PERS_SOFT, "ibo(opt)", fixedpt, fixedpt, H5T__conv_order_opt); status |= H5T__register_int(H5T_PERS_SOFT, "fbo", floatpt, floatpt, H5T__conv_order); status |= H5T__register_int(H5T_PERS_SOFT, "fbo(opt)", floatpt, floatpt, H5T__conv_order_opt); + status |= H5T__register_int(H5T_PERS_SOFT, "complexbo", cplx, cplx, H5T__conv_order); + status |= H5T__register_int(H5T_PERS_SOFT, "complexbo(opt)", cplx, cplx, H5T__conv_order_opt); status |= H5T__register_int(H5T_PERS_SOFT, "struct(no-opt)", compound, compound, H5T__conv_struct); status |= H5T__register_int(H5T_PERS_SOFT, "struct(opt)", compound, compound, H5T__conv_struct_opt); + /* TODO: complex number struct conversions */ status |= H5T__register_int(H5T_PERS_SOFT, "enum", enum_type, enum_type, H5T__conv_enum); status |= H5T__register_int(H5T_PERS_SOFT, "enum_i", enum_type, fixedpt, H5T__conv_enum_numeric); status |= H5T__register_int(H5T_PERS_SOFT, "enum_f", enum_type, floatpt, H5T__conv_enum_numeric); @@ -1193,6 +1301,34 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ldbl_flt16", native_ldouble, native_float16, H5T__conv_ldouble__Float16); #endif +#endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "flt_fcomplex", native_float, native_float_complex, + H5T__conv_float_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt_dcomplex", native_float, native_double_complex, + H5T__conv_float_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt_lcomplex", native_float, native_ldouble_complex, + H5T__conv_float_lcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dbl_fcomplex", native_double, native_float_complex, + H5T__conv_double_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dbl_dcomplex", native_double, native_double_complex, + H5T__conv_double_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dbl_lcomplex", native_double, native_ldouble_complex, + H5T__conv_double_lcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ldbl_fcomplex", native_ldouble, native_float_complex, + H5T__conv_ldouble_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ldbl_dcomplex", native_ldouble, native_double_complex, + H5T__conv_ldouble_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ldbl_lcomplex", native_ldouble, native_ldouble_complex, + H5T__conv_ldouble_lcomplex); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_fcomplex", native_float16, native_float_complex, + H5T__conv__Float16_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt16_dcomplex", native_float16, native_double_complex, + H5T__conv__Float16_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt16_lcomplex", native_float16, native_ldouble_complex, + H5T__conv__Float16_lcomplex); +#endif #endif /* from long long */ @@ -1356,6 +1492,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "schar_flt16", native_schar, native_float16, H5T__conv_schar__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "schar_fcomplex", native_schar, native_float_complex, + H5T__conv_schar_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "schar_dcomplex", native_schar, native_double_complex, + H5T__conv_schar_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "schar_lcomplex", native_schar, native_ldouble_complex, + H5T__conv_schar_lcomplex); +#endif /* From unsigned char to floats */ status |= @@ -1368,6 +1512,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "uchar_flt16", native_uchar, native_float16, H5T__conv_uchar__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "uchar_fcomplex", native_uchar, native_float_complex, + H5T__conv_uchar_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uchar_dcomplex", native_uchar, native_double_complex, + H5T__conv_uchar_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uchar_lcomplex", native_uchar, native_ldouble_complex, + H5T__conv_uchar_lcomplex); +#endif /* From short to floats */ status |= @@ -1380,6 +1532,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "short_flt16", native_short, native_float16, H5T__conv_short__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "short_fcomplex", native_short, native_float_complex, + H5T__conv_short_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "short_dcomplex", native_short, native_double_complex, + H5T__conv_short_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "short_lcomplex", native_short, native_ldouble_complex, + H5T__conv_short_lcomplex); +#endif /* From unsigned short to floats */ status |= @@ -1392,6 +1552,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ushort_flt16", native_ushort, native_float16, H5T__conv_ushort__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "ushort_fcomplex", native_ushort, native_float_complex, + H5T__conv_ushort_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ushort_dcomplex", native_ushort, native_double_complex, + H5T__conv_ushort_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ushort_lcomplex", native_ushort, native_ldouble_complex, + H5T__conv_ushort_lcomplex); +#endif /* From int to floats */ status |= H5T__register_int(H5T_PERS_HARD, "int_flt", native_int, native_float, H5T__conv_int_float); @@ -1401,6 +1569,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "int_flt16", native_int, native_float16, H5T__conv_int__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "int_fcomplex", native_int, native_float_complex, + H5T__conv_int_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "int_dcomplex", native_int, native_double_complex, + H5T__conv_int_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "int_lcomplex", native_int, native_ldouble_complex, + H5T__conv_int_lcomplex); +#endif /* From unsigned int to floats */ status |= H5T__register_int(H5T_PERS_HARD, "uint_flt", native_uint, native_float, H5T__conv_uint_float); @@ -1411,6 +1587,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "uint_flt16", native_uint, native_float16, H5T__conv_uint__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "uint_fcomplex", native_uint, native_float_complex, + H5T__conv_uint_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uint_dcomplex", native_uint, native_double_complex, + H5T__conv_uint_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uint_lcomplex", native_uint, native_ldouble_complex, + H5T__conv_uint_lcomplex); +#endif /* From long to floats */ status |= H5T__register_int(H5T_PERS_HARD, "long_flt", native_long, native_float, H5T__conv_long_float); @@ -1421,6 +1605,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "long_flt16", native_long, native_float16, H5T__conv_long__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "long_fcomplex", native_long, native_float_complex, + H5T__conv_long_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "long_dcomplex", native_long, native_double_complex, + H5T__conv_long_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "long_lcomplex", native_long, native_ldouble_complex, + H5T__conv_long_lcomplex); +#endif /* From unsigned long to floats */ status |= @@ -1433,6 +1625,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ulong_flt16", native_ulong, native_float16, H5T__conv_ulong__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "ulong_fcomplex", native_ulong, native_float_complex, + H5T__conv_ulong_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ulong_dcomplex", native_ulong, native_double_complex, + H5T__conv_ulong_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ulong_lcomplex", native_ulong, native_ldouble_complex, + H5T__conv_ulong_lcomplex); +#endif /* From long long to floats */ status |= @@ -1447,6 +1647,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "llong_flt16", native_llong, native_float16, H5T__conv_llong__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "llong_fcomplex", native_llong, native_float_complex, + H5T__conv_llong_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "llong_dcomplex", native_llong, native_double_complex, + H5T__conv_llong_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "llong_lcomplex", native_llong, native_ldouble_complex, + H5T__conv_llong_lcomplex); +#endif /* From unsigned long long to floats */ status |= @@ -1461,6 +1669,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ullong_flt16", native_ullong, native_float16, H5T__conv_ullong__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "ullong_fcomplex", native_ullong, native_float_complex, + H5T__conv_ullong_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ullong_dcomplex", native_ullong, native_double_complex, + H5T__conv_ullong_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ullong_lcomplex", native_ullong, native_ldouble_complex, + H5T__conv_ullong_lcomplex); +#endif /* From floats to char */ status |= @@ -1579,6 +1795,138 @@ H5T_init(void) H5T__conv__Float16_ullong); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + /* From complex numbers to char */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_schar", native_float_complex, native_schar, + H5T__conv_fcomplex_schar); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_schar", native_double_complex, native_schar, + H5T__conv_dcomplex_schar); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_schar", native_ldouble_complex, native_schar, + H5T__conv_lcomplex_schar); + + /* From complex numbers to unsigned char */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_uchar", native_float_complex, native_uchar, + H5T__conv_fcomplex_uchar); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_uchar", native_double_complex, native_uchar, + H5T__conv_dcomplex_uchar); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_uchar", native_ldouble_complex, native_uchar, + H5T__conv_lcomplex_uchar); + + /* From complex numbers to short */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_short", native_float_complex, native_short, + H5T__conv_fcomplex_short); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_short", native_double_complex, native_short, + H5T__conv_dcomplex_short); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_short", native_ldouble_complex, native_short, + H5T__conv_lcomplex_short); + + /* From complex numbers to unsigned short */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ushort", native_float_complex, native_ushort, + H5T__conv_fcomplex_ushort); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ushort", native_double_complex, native_ushort, + H5T__conv_dcomplex_ushort); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ushort", native_ldouble_complex, native_ushort, + H5T__conv_lcomplex_ushort); + + /* From complex numbers to int */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_int", native_float_complex, native_int, + H5T__conv_fcomplex_int); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_int", native_double_complex, native_int, + H5T__conv_dcomplex_int); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_int", native_ldouble_complex, native_int, + H5T__conv_lcomplex_int); + + /* From complex numbers to unsigned int */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_uint", native_float_complex, native_uint, + H5T__conv_fcomplex_uint); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_uint", native_double_complex, native_uint, + H5T__conv_dcomplex_uint); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_uint", native_ldouble_complex, native_uint, + H5T__conv_lcomplex_uint); + + /* From complex numbers to long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_long", native_float_complex, native_long, + H5T__conv_fcomplex_long); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_long", native_double_complex, native_long, + H5T__conv_dcomplex_long); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_long", native_ldouble_complex, native_long, + H5T__conv_lcomplex_long); + + /* From complex numbers to unsigned long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ulong", native_float_complex, native_ulong, + H5T__conv_fcomplex_ulong); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ulong", native_double_complex, native_ulong, + H5T__conv_dcomplex_ulong); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ulong", native_ldouble_complex, native_ulong, + H5T__conv_lcomplex_ulong); + + /* From complex numbers to long long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_llong", native_float_complex, native_llong, + H5T__conv_fcomplex_llong); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_llong", native_double_complex, native_llong, + H5T__conv_dcomplex_llong); +#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_llong", native_ldouble_complex, native_llong, + H5T__conv_lcomplex_llong); +#endif + + /* From complex numbers to unsigned long long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ullong", native_float_complex, native_ullong, + H5T__conv_fcomplex_ullong); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ullong", native_double_complex, native_ullong, + H5T__conv_dcomplex_ullong); +#if H5T_CONV_INTERNAL_LDOUBLE_ULLONG + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ullong", native_ldouble_complex, native_ullong, + H5T__conv_lcomplex_ullong); +#endif + + /* From complex numbers to floats */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_flt", native_float_complex, native_float, + H5T__conv_fcomplex_float); + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_dbl", native_float_complex, native_double, + H5T__conv_fcomplex_double); + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ldbl", native_float_complex, native_ldouble, + H5T__conv_fcomplex_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_flt16", native_float_complex, native_float16, + H5T__conv_fcomplex__Float16); +#endif + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_flt", native_double_complex, native_float, + H5T__conv_dcomplex_float); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_dbl", native_double_complex, native_double, + H5T__conv_dcomplex_double); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ldbl", native_double_complex, native_ldouble, + H5T__conv_dcomplex_ldouble); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_flt16", native_double_complex, native_float16, + H5T__conv_dcomplex__Float16); +#endif + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_flt", native_ldouble_complex, native_float, + H5T__conv_lcomplex_float); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_dbl", native_ldouble_complex, native_double, + H5T__conv_lcomplex_double); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ldbl", native_ldouble_complex, native_ldouble, + H5T__conv_lcomplex_ldouble); +#if defined(H5_HAVE__FLOAT16) && defined(H5T_CONV_INTERNAL_LDOUBLE_FLOAT16) + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_flt16", native_ldouble_complex, native_float16, + H5T__conv_lcomplex__Float16); +#endif + + /* From complex numbers to complex numbers */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_dcomplex", native_float_complex, + native_double_complex, H5T__conv_fcomplex_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_lcomplex", native_float_complex, + native_ldouble_complex, H5T__conv_fcomplex_lcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_fcomplex", native_double_complex, + native_float_complex, H5T__conv_dcomplex_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_lcomplex", native_double_complex, + native_ldouble_complex, H5T__conv_dcomplex_lcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_fcomplex", native_ldouble_complex, + native_float_complex, H5T__conv_lcomplex_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_dcomplex", native_ldouble_complex, + native_double_complex, H5T__conv_lcomplex_dcomplex); +#endif + /* * The special no-op conversion is the fastest, so we list it last. The * data types we use are not important as long as the source and @@ -1616,6 +1964,8 @@ H5T_init(void) (void)H5T_close_real(vlen); if (array != NULL) (void)H5T_close_real(array); + if (cplx != NULL) + (void)H5T_close_real(cplx); /* Error cleanup */ if (ret_value < 0) { @@ -1765,30 +2115,33 @@ H5T_top_term_package(void) 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_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_FLOAT_COMPLEX_g = H5I_INVALID_HID; + H5T_NATIVE_DOUBLE_COMPLEX_g = H5I_INVALID_HID; + H5T_NATIVE_LDOUBLE_COMPLEX_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; @@ -1919,19 +2272,19 @@ H5Tcreate(H5T_class_t type, size_t size) H5T_t *dt = NULL; /* New datatype constructed */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* check args. We support string (fixed-size or variable-length) now. */ if (size <= 0 && size != H5T_VARIABLE) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "size must be positive"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "size must be positive"); /* create the type */ if (NULL == (dt = H5T__create(type, size))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to create type"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, "unable to create type"); /* Get an ID for the datatype */ if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype ID"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype ID"); done: FUNC_LEAVE_API(ret_value) @@ -2340,7 +2693,7 @@ H5T_detect_class(const H5T_t *dt, H5T_class_t cls, bool from_api) HGOTO_DONE(true); /* Recurse if it's VL, compound, enum or array */ - if (H5T_IS_COMPLEX(dt->shared->u.compnd.memb[i].type->shared->type)) + if (H5T_IS_COMPOSITE(dt->shared->u.compnd.memb[i].type->shared->type)) if ((nested_ret = H5T_detect_class(dt->shared->u.compnd.memb[i].type, cls, from_api)) != false) HGOTO_DONE(nested_ret); @@ -2352,6 +2705,10 @@ H5T_detect_class(const H5T_t *dt, H5T_class_t cls, bool from_api) case H5T_ENUM: HGOTO_DONE(H5T_detect_class(dt->shared->parent, cls, from_api)); break; + case H5T_COMPLEX: + assert(dt->shared->u.cplx.homogeneous); + HGOTO_DONE(H5T_detect_class(dt->shared->parent, cls, from_api)); + break; case H5T_NO_CLASS: case H5T_INTEGER: case H5T_FLOAT: @@ -3219,11 +3576,11 @@ H5Tdecode(const void *buf) H5T_t *dt; hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* Check args */ if (buf == NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "empty buffer"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "empty buffer"); /* Create datatype by decoding buffer * There is no way to get the size of the buffer, so we pass in @@ -3232,11 +3589,11 @@ H5Tdecode(const void *buf) * takes a size parameter. */ if (NULL == (dt = H5T_decode(SIZE_MAX, (const unsigned char *)buf))) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, "can't decode object"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, H5I_INVALID_HID, "can't decode object"); /* Register the type and return the ID */ if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register data type"); + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register data type"); done: FUNC_LEAVE_API(ret_value) @@ -3442,6 +3799,9 @@ H5T__create(H5T_class_t type, size_t size) case H5T_ARRAY: /* Array datatype */ HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tarray_create2()"); + case H5T_COMPLEX: /* Complex number datatype */ + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, NULL, "base type required - use H5Tcomplex_create()"); + case H5T_NO_CLASS: case H5T_REFERENCE: case H5T_NCLASSES: @@ -3743,6 +4103,7 @@ H5T__complete_copy(H5T_t *new_dt, const H5T_t *old_dt, H5T_shared_t *reopened_fo case H5T_TIME: case H5T_STRING: case H5T_BITFIELD: + case H5T_COMPLEX: case H5T_NCLASSES: default: break; @@ -4111,6 +4472,7 @@ H5T__free(H5T_t *dt) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: break; @@ -4293,12 +4655,28 @@ H5T__set_size(H5T_t *dt, size_t size) assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs)); if (dt->shared->parent) { - if (H5T__set_size(dt->shared->parent, size) < 0) + size_t new_size = size; + + if (dt->shared->type == H5T_COMPLEX) { + if (!dt->shared->u.cplx.homogeneous) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + + if ((new_size % 2) != 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, + "new datatype size is not evenly divisible by 2"); + + new_size /= 2; + } + + if (H5T__set_size(dt->shared->parent, new_size) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type"); /* Adjust size of datatype appropriately */ if (dt->shared->type == H5T_ARRAY) dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem; + else if (dt->shared->type == H5T_COMPLEX) + dt->shared->size = 2 * dt->shared->parent->shared->size; else if (dt->shared->type != H5T_VLEN) dt->shared->size = dt->shared->parent->shared->size; } @@ -4422,6 +4800,7 @@ H5T__set_size(H5T_t *dt, size_t size) case H5T_VLEN: case H5T_ARRAY: case H5T_REFERENCE: + case H5T_COMPLEX: assert("can't happen" && 0); break; @@ -4810,6 +5189,38 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, bool superset) HGOTO_DONE(1); break; + case H5T_COMPLEX: + /* Make sure the complex number datatypes are both homogeneous or + * both heterogeneous + */ + tmp = (dt1->shared->u.cplx.homogeneous > dt2->shared->u.cplx.homogeneous) - + (dt1->shared->u.cplx.homogeneous < dt2->shared->u.cplx.homogeneous); + if (tmp < 0) + HGOTO_DONE(-1); + if (tmp > 0) + HGOTO_DONE(1); + + /* Make sure the complex number datatypes are both in the same form */ + tmp = (dt1->shared->u.cplx.form > dt2->shared->u.cplx.form) - + (dt1->shared->u.cplx.form < dt2->shared->u.cplx.form); + if (tmp < 0) + HGOTO_DONE(-1); + if (tmp > 0) + HGOTO_DONE(1); + + if (dt1->shared->u.cplx.homogeneous) { + tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset); + if (tmp < 0) + HGOTO_DONE(-1); + if (tmp > 0) + HGOTO_DONE(1); + } + else + /* Heterogeneous complex number datatypes are currently unsupported */ + HGOTO_DONE(-1); + + break; + case H5T_NO_CLASS: case H5T_INTEGER: case H5T_FLOAT: @@ -4940,6 +5351,7 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, bool superset) case H5T_ENUM: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: assert("not implemented yet" && 0); @@ -5640,6 +6052,7 @@ H5T_path_match_find_type_with_volobj(const H5T_t *datatype, const H5VL_object_t case H5T_OPAQUE: case H5T_REFERENCE: /* Should have been determined by above check */ case H5T_ENUM: + case H5T_COMPLEX: case H5T_NO_CLASS: /* Error value, but simplify logic for a true/false return value */ case H5T_NCLASSES: /* Error value, but simplify logic for a true/false return value */ default: @@ -6187,6 +6600,7 @@ H5T_is_sensible(const H5T_t *dt) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: /* Assume all other datatype are sensible to store on disk */ @@ -6239,7 +6653,7 @@ H5T_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc) /* Recurse if it's VL, compound, enum or array */ /* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */ if (dt->shared->parent->shared->force_conv && - H5T_IS_COMPLEX(dt->shared->parent->shared->type)) { + H5T_IS_COMPOSITE(dt->shared->parent->shared->type)) { /* Keep the old base element size for later */ old_size = dt->shared->parent->shared->size; @@ -6280,7 +6694,7 @@ H5T_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc) /* Recurse if it's VL, compound, enum or array */ /* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */ - if (memb_type->shared->force_conv && H5T_IS_COMPLEX(memb_type->shared->type)) { + if (memb_type->shared->force_conv && H5T_IS_COMPOSITE(memb_type->shared->type)) { /* Keep the old field size for later */ old_size = memb_type->shared->size; @@ -6322,7 +6736,7 @@ H5T_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc) * them as part of the same blob)*/ /* (If the force_conv flag is _not_ set, the type cannot change in size, so don't recurse) */ if (dt->shared->parent->shared->force_conv && - H5T_IS_COMPLEX(dt->shared->parent->shared->type) && + H5T_IS_COMPOSITE(dt->shared->parent->shared->type) && (dt->shared->parent->shared->type != H5T_REFERENCE)) { if ((changed = H5T_set_loc(dt->shared->parent, file, loc)) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "Unable to set VL location"); @@ -6351,6 +6765,7 @@ H5T_set_loc(H5T_t *dt, H5VL_object_t *file, H5T_loc_t loc) case H5T_BITFIELD: case H5T_OPAQUE: case H5T_ENUM: + case H5T_COMPLEX: case H5T_NCLASSES: default: break; @@ -6446,6 +6861,7 @@ H5T__detect_vlen_ref(const H5T_t *dt) case H5T_BITFIELD: case H5T_OPAQUE: case H5T_REFERENCE: + case H5T_COMPLEX: case H5T_NCLASSES: default: break; @@ -6538,6 +6954,7 @@ H5T__upgrade_version_cb(H5T_t *dt, void *op_value) case H5T_BITFIELD: case H5T_OPAQUE: case H5T_REFERENCE: + case H5T_COMPLEX: case H5T_NCLASSES: default: break; @@ -6568,7 +6985,7 @@ H5T__upgrade_version(H5T_t *dt, unsigned new_version) assert(dt); /* Iterate over entire datatype, upgrading the version of components, if it's useful */ - if (H5T__visit(dt, (H5T_VISIT_SIMPLE | H5T_VISIT_COMPLEX_LAST), H5T__upgrade_version_cb, &new_version) < + if (H5T__visit(dt, (H5T_VISIT_SIMPLE | H5T_VISIT_COMPOSITE_LAST), H5T__upgrade_version_cb, &new_version) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_BADITER, FAIL, "iteration to upgrade datatype encoding version failed"); diff --git a/src/H5Tbit.c b/src/H5Tbit.c index c8300b85cde..503f298ae9e 100644 --- a/src/H5Tbit.c +++ b/src/H5Tbit.c @@ -231,7 +231,7 @@ H5T__bit_shift(uint8_t *buf, ssize_t shift_dist, size_t offset, size_t size) *------------------------------------------------------------------------- */ uint64_t -H5T__bit_get_d(uint8_t *buf, size_t offset, size_t size) +H5T__bit_get_d(const uint8_t *buf, size_t offset, size_t size) { uint64_t val = 0; size_t i, hs; diff --git a/src/H5Tcomplex.c b/src/H5Tcomplex.c new file mode 100644 index 00000000000..ed6c373838a --- /dev/null +++ b/src/H5Tcomplex.c @@ -0,0 +1,153 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for complex number + * datatypes in the H5T interface. + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5Tmodule.h" /* This source code file is part of the H5T module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Tpkg.h" /* Datatypes */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/*********************/ +/* Public Variables */ +/*********************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/*------------------------------------------------------------------------- + * Function: H5Tcomplex_create + * + * Purpose: Create a new complex number datatype based on the specified + * base datatype ID. + * + * Return: Success: ID of new complex number datatype + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Tcomplex_create(hid_t base_type_id) +{ + H5T_t *base = NULL; /* base datatype */ + H5T_t *dt = NULL; /* new datatype */ + hid_t ret_value = H5I_INVALID_HID; /* return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + + if (NULL == (base = (H5T_t *)H5I_object_verify(base_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid base datatype ID"); + + if (NULL == (dt = H5T__complex_create(base))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, + "can't create complex number datatype from base datatype"); + + if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype"); + +done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5T__complex_create + * + * Purpose: Create a new complex number datatype based on the specified + * base datatype. + * + * Return: Success: new complex number datatype + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T__complex_create(const H5T_t *base) +{ + H5T_t *dt = NULL; /* New complex number datatype */ + H5T_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check args */ + assert(base); + + /* Currently, only floating-point base datatypes are supported. */ + if (base->shared->type != H5T_FLOAT) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "base datatype is not a H5T_FLOAT datatype"); + if (base->shared->size == 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid base datatype size"); + if (base->shared->size > SIZE_MAX / 2) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, + "base datatype size too large - new datatype size would overflow"); + + /* Build new type */ + if (NULL == (dt = H5T__alloc())) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "memory allocation failed"); + dt->shared->type = H5T_COMPLEX; + dt->shared->size = 2 * base->shared->size; + + if (NULL == (dt->shared->parent = H5T_copy(base, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy base datatype"); + + /* Inherit encoding version from base type */ + dt->shared->version = base->shared->version; + + /* Set complex number-specific fields */ + dt->shared->u.cplx.form = H5T_COMPLEX_RECTANGULAR; /* Only rectangular form is currently supported */ + dt->shared->u.cplx.homogeneous = true; + + ret_value = dt; + +done: + if (!ret_value) + if (dt && H5T_close(dt) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, NULL, "can't close datatype"); + + FUNC_LEAVE_NOAPI(ret_value) +} diff --git a/src/H5Tcompound.c b/src/H5Tcompound.c index eb39dd4e98a..701929c3695 100644 --- a/src/H5Tcompound.c +++ b/src/H5Tcompound.c @@ -503,6 +503,13 @@ H5T__pack(const H5T_t *dt) /* Adjust size of datatype appropriately */ if (dt->shared->type == H5T_ARRAY) dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem; + else if (dt->shared->type == H5T_COMPLEX) { + if (dt->shared->u.cplx.homogeneous) + dt->shared->size = 2 * dt->shared->parent->shared->size; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + } else if (dt->shared->type != H5T_VLEN) dt->shared->size = dt->shared->parent->shared->size; } /* end if */ diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 0a5e89ee99c..2ac1c2360b9 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -28,21 +28,13 @@ #include "H5private.h" /* Generic Functions */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5Tconv.h" /* Datatype Conversions */ #include "H5Tpkg.h" /* Datatypes */ /****************/ /* Local Macros */ /****************/ -/* Swap two elements (I & J) of an array using a temporary variable */ -#define H5_SWAP_BYTES(ARRAY, I, J) \ - do { \ - uint8_t _tmp; \ - _tmp = ARRAY[I]; \ - ARRAY[I] = ARRAY[J]; \ - ARRAY[J] = _tmp; \ - } while (0) - /******************/ /* Local Typedefs */ /******************/ @@ -185,27 +177,47 @@ H5T_get_force_conv(const H5T_t *dt) *------------------------------------------------------------------------- */ herr_t -H5T__reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order) +H5T__reverse_order(uint8_t *rev, uint8_t *s, const H5T_t *dtype) { - size_t i; + H5T_order_t order; + size_t size; FUNC_ENTER_PACKAGE_NOERR assert(s); - assert(size); + assert(dtype); + assert(H5T_IS_ATOMIC(dtype->shared) || H5T_COMPLEX == dtype->shared->type); + + size = dtype->shared->size; + + if (H5T_IS_ATOMIC(dtype->shared)) + order = dtype->shared->u.atomic.order; + else + order = dtype->shared->parent->shared->u.atomic.order; if (H5T_ORDER_VAX == order) { - for (i = 0; i < size; i += 2) { + for (size_t i = 0; i < size; i += 2) { rev[i] = s[(size - 2) - i]; rev[i + 1] = s[(size - 1) - i]; } } else if (H5T_ORDER_BE == order) { - for (i = 0; i < size; i++) - rev[size - (i + 1)] = s[i]; + if (H5T_IS_ATOMIC(dtype->shared)) { + for (size_t i = 0; i < size; i++) + rev[size - (i + 1)] = s[i]; + } + else { + size_t part_size = size / 2; + for (size_t i = 0; i < part_size; i++) + rev[part_size - (i + 1)] = s[i]; + rev += part_size; + s += part_size; + for (size_t i = 0; i < part_size; i++) + rev[part_size - (i + 1)] = s[i]; + } } else { - for (i = 0; i < size; i++) + for (size_t i = 0; i < size; i++) rev[i] = s[i]; } @@ -255,12 +267,12 @@ H5T__conv_noop(const H5T_t H5_ATTR_UNUSED *src, const H5T_t H5_ATTR_UNUSED *dst, /*------------------------------------------------------------------------- * Function: H5T__conv_order * - * Purpose: Convert one type to another when byte order is the only - * difference. + * Purpose: Convert one type to another when byte order is the only + * difference. * - * Note: This is a soft conversion function. + * Note: This is a soft conversion function. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ @@ -269,10 +281,13 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *_buf, void H5_ATTR_UNUSED *background) { - uint8_t *buf = (uint8_t *)_buf; - size_t i; - size_t j, md; - herr_t ret_value = SUCCEED; /* Return value */ + H5T_order_t src_order, dst_order; + uint8_t *buf = (uint8_t *)_buf; + size_t src_offset, dst_offset; + size_t src_size, dst_size; + size_t i; + size_t j, md; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -281,12 +296,38 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, /* Capability query */ if (NULL == src || NULL == dst) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - if (src->shared->size != dst->shared->size || 0 != src->shared->u.atomic.offset || - 0 != dst->shared->u.atomic.offset || - !((H5T_ORDER_BE == src->shared->u.atomic.order && - H5T_ORDER_LE == dst->shared->u.atomic.order) || - (H5T_ORDER_LE == src->shared->u.atomic.order && - H5T_ORDER_BE == dst->shared->u.atomic.order))) + + src_size = src->shared->size; + dst_size = dst->shared->size; + if (src_size != dst_size) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + if (src->shared->parent) { + if (!H5T_IS_ATOMIC(src->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + src_offset = src->shared->parent->shared->u.atomic.offset; + src_order = src->shared->parent->shared->u.atomic.order; + } + else { + src_offset = src->shared->u.atomic.offset; + src_order = src->shared->u.atomic.order; + } + if (dst->shared->parent) { + if (!H5T_IS_ATOMIC(dst->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + dst_offset = dst->shared->parent->shared->u.atomic.offset; + dst_order = dst->shared->parent->shared->u.atomic.order; + } + else { + dst_offset = dst->shared->u.atomic.offset; + dst_order = dst->shared->u.atomic.order; + } + + if (0 != src_offset || 0 != dst_offset) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + if (!((H5T_ORDER_BE == src_order && H5T_ORDER_LE == dst_order) || + (H5T_ORDER_LE == src_order && H5T_ORDER_BE == dst_order))) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); switch (src->shared->type) { case H5T_INTEGER: @@ -307,6 +348,23 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, } /* end if */ break; + case H5T_COMPLEX: { + const H5T_shared_t *src_base_sh = src->shared->parent->shared; + const H5T_shared_t *dst_base_sh = dst->shared->parent->shared; + + if (src_base_sh->u.atomic.u.f.sign != dst_base_sh->u.atomic.u.f.sign || + src_base_sh->u.atomic.u.f.epos != dst_base_sh->u.atomic.u.f.epos || + src_base_sh->u.atomic.u.f.esize != dst_base_sh->u.atomic.u.f.esize || + src_base_sh->u.atomic.u.f.ebias != dst_base_sh->u.atomic.u.f.ebias || + src_base_sh->u.atomic.u.f.mpos != dst_base_sh->u.atomic.u.f.mpos || + src_base_sh->u.atomic.u.f.msize != dst_base_sh->u.atomic.u.f.msize || + src_base_sh->u.atomic.u.f.norm != dst_base_sh->u.atomic.u.f.norm || + src_base_sh->u.atomic.u.f.pad != dst_base_sh->u.atomic.u.f.pad) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + break; + } + case H5T_NO_CLASS: case H5T_TIME: case H5T_STRING: @@ -328,11 +386,41 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, if (NULL == src) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - buf_stride = buf_stride ? buf_stride : src->shared->size; - md = src->shared->size / 2; - for (i = 0; i < nelmts; i++, buf += buf_stride) - for (j = 0; j < md; j++) - H5_SWAP_BYTES(buf, j, src->shared->size - (j + 1)); + src_size = src->shared->size; + buf_stride = buf_stride ? buf_stride : src_size; + md = src_size / 2; + + /* Complex number types are composed of two floating-point + * elements, each of which is half the size of the datatype + * and have to be converted separately. While halving the + * source datatype size and doubling the number elements to + * be converted works in some cases, structure padding can + * cause issues with that approach, so we special-case + * conversions on complex numbers here. + */ + if (H5T_COMPLEX == src->shared->type) { + size_t part_size = src_size / 2; + + md = part_size / 2; + for (i = 0; i < nelmts; i++, buf += buf_stride) { + uint8_t *cur_part = buf; + + /* Convert real part of complex number element */ + for (j = 0; j < md; j++) + H5_SWAP_BYTES(cur_part, j, part_size - (j + 1)); + + /* Convert imaginary part of complex number element */ + cur_part += part_size; + for (j = 0; j < md; j++) + H5_SWAP_BYTES(cur_part, j, part_size - (j + 1)); + } + } + else { + for (i = 0; i < nelmts; i++, buf += buf_stride) + for (j = 0; j < md; j++) + H5_SWAP_BYTES(buf, j, src_size - (j + 1)); + } + break; case H5T_CONV_FREE: @@ -350,13 +438,13 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, /*------------------------------------------------------------------------- * Function: H5T__conv_order_opt * - * Purpose: Convert one type to another when byte order is the only - * difference. This is the optimized version of H5T__conv_order() - * for a handful of different sizes. + * Purpose: Convert one type to another when byte order is the only + * difference. This is the optimized version of + * H5T__conv_order() for a handful of different sizes. * - * Note: This is a soft conversion function. + * Note: This is a soft conversion function. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ @@ -365,9 +453,12 @@ H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *_buf, void H5_ATTR_UNUSED *background) { - uint8_t *buf = (uint8_t *)_buf; - size_t i; - herr_t ret_value = SUCCEED; /* Return value */ + H5T_order_t src_order, dst_order; + uint8_t *buf = (uint8_t *)_buf; + size_t src_offset, dst_offset; + size_t src_size, dst_size; + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -376,19 +467,43 @@ H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, /* Capability query */ if (NULL == src || NULL == dst) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - if (src->shared->size != dst->shared->size || 0 != src->shared->u.atomic.offset || - 0 != dst->shared->u.atomic.offset) + + src_size = src->shared->size; + dst_size = dst->shared->size; + if (src_size != dst_size) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + if (src->shared->parent) { + if (!H5T_IS_ATOMIC(src->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + src_offset = src->shared->parent->shared->u.atomic.offset; + src_order = src->shared->parent->shared->u.atomic.order; + } + else { + src_offset = src->shared->u.atomic.offset; + src_order = src->shared->u.atomic.order; + } + if (dst->shared->parent) { + if (!H5T_IS_ATOMIC(dst->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + dst_offset = dst->shared->parent->shared->u.atomic.offset; + dst_order = dst->shared->parent->shared->u.atomic.order; + } + else { + dst_offset = dst->shared->u.atomic.offset; + dst_order = dst->shared->u.atomic.order; + } + + if (0 != src_offset || 0 != dst_offset) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); if ((src->shared->type == H5T_REFERENCE && dst->shared->type != H5T_REFERENCE) || (dst->shared->type == H5T_REFERENCE && src->shared->type != H5T_REFERENCE)) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); - if (src->shared->type != H5T_REFERENCE && !((H5T_ORDER_BE == src->shared->u.atomic.order && - H5T_ORDER_LE == dst->shared->u.atomic.order) || - (H5T_ORDER_LE == src->shared->u.atomic.order && - H5T_ORDER_BE == dst->shared->u.atomic.order))) + if (src->shared->type != H5T_REFERENCE && + !((H5T_ORDER_BE == src_order && H5T_ORDER_LE == dst_order) || + (H5T_ORDER_LE == src_order && H5T_ORDER_BE == dst_order))) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); - if (src->shared->size != 1 && src->shared->size != 2 && src->shared->size != 4 && - src->shared->size != 8 && src->shared->size != 16) + if (src_size != 1 && src_size != 2 && src_size != 4 && src_size != 8 && src_size != 16) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); switch (src->shared->type) { case H5T_INTEGER: @@ -417,6 +532,10 @@ H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, case H5T_ENUM: case H5T_VLEN: case H5T_ARRAY: + /* Complex numbers require some special-case logic for + * proper handling. Defer to H5T__conv_order for these types. + */ + case H5T_COMPLEX: case H5T_NCLASSES: default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); diff --git a/src/H5Tconv.h b/src/H5Tconv.h index 4dae848269d..03e74c18d8d 100644 --- a/src/H5Tconv.h +++ b/src/H5Tconv.h @@ -25,6 +25,15 @@ /* Length of debugging name buffer */ #define H5T_NAMELEN 32 +/* Swap two elements (I & J) of an array using a temporary variable */ +#define H5_SWAP_BYTES(ARRAY, I, J) \ + do { \ + uint8_t _tmp; \ + _tmp = ARRAY[I]; \ + ARRAY[I] = ARRAY[J]; \ + ARRAY[J] = _tmp; \ + } while (0) + /****************************/ /* Library Private Typedefs */ /****************************/ @@ -184,7 +193,7 @@ H5_DLL herr_t H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_ size_t bkg_stride, void *_buf, void *bkg); /* Utility functions */ -H5_DLL herr_t H5T__reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order); +H5_DLL herr_t H5T__reverse_order(uint8_t *rev, uint8_t *s, const H5T_t *dtype); /* Debugging functions */ H5_DLL herr_t H5T__print_path_stats(H5T_path_t *path, int *nprint /*in,out*/); diff --git a/src/H5Tconv_bitfield.c b/src/H5Tconv_bitfield.c index 486036ad260..92d763d3636 100644 --- a/src/H5Tconv_bitfield.c +++ b/src/H5Tconv_bitfield.c @@ -105,7 +105,9 @@ H5T__conv_b_b(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ } /* Allocate space for order-reversed source buffer */ - src_rev = (uint8_t *)H5MM_calloc(src->shared->size); + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "unable to allocate temporary buffer"); /* The conversion loop */ H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); @@ -161,8 +163,7 @@ H5T__conv_b_b(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ if (src->shared->u.atomic.prec > dst->shared->u.atomic.prec) { /*overflow*/ if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + H5T__reverse_order(src_rev, s, src); /*reverse order first*/ 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, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); diff --git a/src/H5Tconv_complex.c b/src/H5Tconv_complex.c new file mode 100644 index 00000000000..4a5bfe66663 --- /dev/null +++ b/src/H5Tconv_complex.c @@ -0,0 +1,2265 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Purpose: Datatype conversion functions for complex number datatypes + */ + +/****************/ +/* Module Setup */ +/****************/ +#include "H5Tmodule.h" /* This source code file is part of the H5T module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5Eprivate.h" +#include "H5Tconv.h" +#include "H5Tconv_macros.h" +#include "H5Tconv_complex.h" +#include "H5Tconv_integer.h" +#include "H5Tconv_float.h" + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +static herr_t H5T__conv_complex_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, void *buf); + +/*------------------------------------------------------------------------- + * Function: H5T__conv_complex + * + * Purpose: Convert one complex number type to another. This is the + * catch-all function for complex number conversions and is + * probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_complex(const H5T_t *src_p, const H5T_t *dst_p, 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) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_PACKAGE + + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (!H5T_IS_ATOMIC(src_p->shared->parent->shared)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid source complex number datatype"); + if (!H5T_IS_ATOMIC(dst_p->shared->parent->shared)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid destination complex number datatype"); + if (!src_p->shared->u.cplx.homogeneous || !dst_p->shared->u.cplx.homogeneous) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "source and destination complex number datatypes must be homogeneous"); + src_atomic = src_p->shared->parent->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for source datatype"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for destination datatype"); + if (dst_p->shared->size > TEMP_FLOAT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large"); + if (8 * sizeof(int64_t) - 1 < src_atomic.u.f.esize || + 8 * sizeof(int64_t) - 1 < dst_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; + + break; + } + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); + + if (H5T__conv_complex_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); + + break; + + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_complex() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_complex_loop + * + * Purpose: Implements the body of the conversion loop when converting + * complex number values to another complex number type. + * + * NOTE: The conversion logic in this function is essentially + * identical to the logic in the H5T__conv_f_f_loop function. + * However, conversion has to be performed on both the real + * and imaginary parts of each complex number element. Since + * complex numbers have the same representation as an array + * of two elements of the base floating-point type, this could + * be simulated in some cases with the H5T__conv_f_f_loop + * function by doubling the number of elements to be converted + * and halving the sizes involved. However, overlapping + * elements or a non-zero `buf_stride` value would complicate + * the buffer pointer advancements since each part of the + * complex number value has to be processed before advancing + * the buffer pointer. Application conversion exception + * callbacks also pose a problem since they would expect to + * receive an entire complex number rather than part of one. + * Therefore, the H5T__conv_f_f_loop logic is mostly + * duplicated here and fixes to one function should be made to + * the other, if appropriate. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +/* TODO: cleanup and organize */ +static herr_t +H5T__conv_complex_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, + size_t buf_stride, void *buf) +{ + H5T_conv_float_specval_t realval_type; /* floating-point value type (regular, +/-Inf, +/-0, NaN) */ + H5T_conv_float_specval_t imagval_type; /* floating-point value type (regular, +/-Inf, +/-0, NaN) */ + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + hssize_t expo_max; /* maximum possible dst exponent */ + ssize_t src_delta, dst_delta; /* source & destination stride */ + uint8_t *s, *sp, *d, *dp; /* source and dest traversal ptrs */ + uint8_t *src_rev = NULL; /* order-reversed source buffer */ + uint8_t dbuf[2 * TEMP_FLOAT_CONV_BUFFER_SIZE]; /* temp destination buffer */ + size_t src_part_size; /* size of each complex number part */ + size_t dst_part_size; /* size of each complex number part */ + size_t olap; /* num overlapping elements */ + int direction; /* forward or backward traversal */ + herr_t ret_value = SUCCEED; + + assert(src_p); + assert(src_p->shared->type == H5T_COMPLEX); + assert(src_p->shared->u.cplx.homogeneous); + assert(dst_p); + assert(dst_p->shared->type == H5T_COMPLEX); + assert(dst_p->shared->u.cplx.homogeneous); + assert(conv_ctx); + assert(buf); + + FUNC_ENTER_PACKAGE + + src_atomic = src_p->shared->parent->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + src_part_size = src_p->shared->size / 2; + dst_part_size = dst_p->shared->size / 2; + expo_max = ((hssize_t)1 << dst_atomic.u.f.esize) - 1; + + /* + * Do we process the values from beginning to end or vice versa? Also, + * how many of the elements have the source and destination areas + * overlapping? + */ + if (src_p->shared->size == dst_p->shared->size || buf_stride) { + sp = dp = (uint8_t *)buf; + direction = 1; + olap = nelmts; + } + else if (src_p->shared->size >= dst_p->shared->size) { + double olap_d = + ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); + olap = (size_t)olap_d; + sp = dp = (uint8_t *)buf; + direction = 1; + } + else { + double olap_d = + ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); + olap = (size_t)olap_d; + sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; + dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; + direction = -1; + } + + /* Direction & size of buffer traversal */ + H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); + H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t); + H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t); + src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size); + dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size); + + /* Allocate space for order-reversed source buffer */ + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src_p->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer"); + + /* The conversion loop */ + for (size_t elmtno = 0; elmtno < nelmts; elmtno++) { + H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED; /* return of conversion exception callback function */ + ssize_t real_mant_msb = 0; /* most significant bit set in mantissa */ + ssize_t imag_mant_msb = 0; /* most significant bit set in mantissa */ + int64_t real_expo, imag_expo; /* exponent */ + size_t real_implied; /* destination implied bits */ + size_t imag_implied; /* destination implied bits */ + size_t mpos; /* offset to useful mant in src */ + size_t real_msize = 0, imag_msize = 0; /* useful size of mantissa in src */ + size_t real_mrsh, imag_mrsh; /* amount to right shift mantissa */ + bool reverse = true; /* if reversed the order of destination */ + bool real_denormalized = false; /* is either source or destination denormalized? */ + bool imag_denormalized = false; /* is either source or destination denormalized? */ + bool real_carry = false; /* carry after rounding mantissa */ + bool imag_carry = false; /* carry after rounding mantissa */ + + /* + * If the source and destination buffers overlap then use a + * temporary buffer for the destination. + */ + s = sp; + if (direction > 0) + d = elmtno < olap ? dbuf : dp; + else + d = elmtno + olap >= nelmts ? dbuf : dp; + if (d == dbuf) + memset(dbuf, 0, sizeof(dbuf)); + +#ifndef NDEBUG + if (d == dbuf) { + assert((dp >= sp && dp < sp + src_p->shared->size) || + (sp >= dp && sp < dp + dst_p->shared->size)); + } + else { + assert((dp < sp && dp + dst_p->shared->size <= sp) || + (sp < dp && sp + src_p->shared->size <= dp)); + } +#endif + + /* + * Put the data in little endian order so our loops aren't so + * complicated. We'll do all the conversion stuff assuming + * little endian and then we'll fix the order at the end. + */ + if (H5T_ORDER_BE == src_atomic.order) { + uint8_t *cur_part = s; + /* Swap real part of complex number element */ + for (size_t j = 0; j < src_part_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, src_part_size - (j + 1)); + /* Swap imaginary part of complex number element */ + cur_part += src_part_size; + for (size_t j = 0; j < src_part_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, src_part_size - (j + 1)); + } + else if (H5T_ORDER_VAX == src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + + /* Check for special cases: +0, -0, +Inf, -Inf, NaN */ + realval_type = H5T__conv_float_find_special(s, &src_atomic, NULL); + imagval_type = H5T__conv_float_find_special(s + (src_p->shared->size / 2), &src_atomic, NULL); + + /* A complex number is zero if both parts are +/-0 */ + if ((realval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO || + realval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO) && + (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO || + imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO)) { + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size, src_atomic.u.f.sign, + (size_t)1); + H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false); + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + goto padding; + } + else if (realval_type != H5T_CONV_FLOAT_SPECVAL_REGULAR || + imagval_type != H5T_CONV_FLOAT_SPECVAL_REGULAR) { + /* If user's exception handler is present, use it */ + if (conv_ctx->u.conv.cb_struct.func) { + H5T_conv_except_t except_type; /* type of conversion exception that occurred */ + + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + /* + * A complex number is infinity if either part is infinity, + * even if the other part is NaN. If a part is infinity, + * since we can only throw one type of conversion exception, + * arbitrarily choose the exception type to throw based + * on the infinity type for the real part (if it's infinity), + * followed by the infinity type for the imaginary part. For + * now, it will be assumed that the conversion exception + * callback will inspect and handle both parts of the complex + * number value. + */ + if (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF) + except_type = H5T_CONV_EXCEPT_PINF; + else if (realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) + except_type = H5T_CONV_EXCEPT_NINF; + else if (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF) + except_type = H5T_CONV_EXCEPT_PINF; + else if (imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) + except_type = H5T_CONV_EXCEPT_NINF; + else { + assert(realval_type == H5T_CONV_FLOAT_SPECVAL_NAN || + imagval_type == H5T_CONV_FLOAT_SPECVAL_NAN); + except_type = H5T_CONV_EXCEPT_NAN; + } + + except_ret = (conv_ctx->u.conv.cb_struct.func)(except_type, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); + } + + if (except_ret == H5T_CONV_UNHANDLED) { + if (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || + realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF || + imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || + imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) { + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size, + src_atomic.u.f.sign, (size_t)1); + + if (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || + realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) { + H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true); + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + /* If the destination has no implied mantissa bit, we'll need to set + * the 1st bit of mantissa to 1. The Intel-Linux "long double" is + * this case. */ + if (H5T_NORM_NONE == dst_atomic.u.f.norm) + H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - 1, (size_t)1, true); + } + if (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || + imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) { + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + /* If the destination has no implied mantissa bit, we'll need to set + * the 1st bit of mantissa to 1. The Intel-Linux "long double" is + * this case. */ + if (H5T_NORM_NONE == dst_atomic.u.f.norm) + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - 1, + (size_t)1, true); + } + } + else { + /* There are many NaN values, so we just set all bits of the significand. */ + if (realval_type == H5T_CONV_FLOAT_SPECVAL_NAN) { + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true); + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, true); + } + if (imagval_type == H5T_CONV_FLOAT_SPECVAL_NAN) { + H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size, + src_atomic.u.f.sign, (size_t)1); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, true); + } + } + } + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + + goto padding; + } + + /* + * Get the exponent as an unsigned quantity from the section of + * the source bit field where it's located. Don't worry about + * the exponent bias yet. + */ + real_expo = (int64_t)H5T__bit_get_d(s, src_atomic.u.f.epos, src_atomic.u.f.esize); + imag_expo = (int64_t)H5T__bit_get_d(s + src_part_size, src_atomic.u.f.epos, src_atomic.u.f.esize); + + if (real_expo == 0) + real_denormalized = true; + if (imag_expo == 0) + imag_denormalized = true; + + /* Determine size of mantissa for real and imaginary parts */ + if (0 == real_expo || H5T_NORM_NONE == src_atomic.u.f.norm) { + if ((real_mant_msb = + H5T__bit_find(s, src_atomic.u.f.mpos, src_atomic.u.f.msize, H5T_BIT_MSB, true)) > 0) + real_msize = (size_t)real_mant_msb; + else if (0 == real_mant_msb) { + real_msize = 1; + H5T__bit_set(s, src_atomic.u.f.mpos, (size_t)1, false); + } + } + else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) + real_msize = src_atomic.u.f.msize; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + + if (0 == imag_expo || H5T_NORM_NONE == src_atomic.u.f.norm) { + if ((imag_mant_msb = H5T__bit_find(s + src_part_size, src_atomic.u.f.mpos, src_atomic.u.f.msize, + H5T_BIT_MSB, true)) > 0) + imag_msize = (size_t)imag_mant_msb; + else if (0 == imag_mant_msb) { + imag_msize = 1; + H5T__bit_set(s + src_part_size, src_atomic.u.f.mpos, (size_t)1, false); + } + } + else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) + imag_msize = src_atomic.u.f.msize; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + + /* + * The sign for the destination is the same as the sign for the + * source in all cases. + */ + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.sign, s + src_part_size, src_atomic.u.f.sign, + (size_t)1); + + /* + * Calculate the true source exponent by adjusting according to + * the source exponent bias. + */ + if (0 == real_expo || H5T_NORM_NONE == src_atomic.u.f.norm) { + assert(real_mant_msb >= 0); + real_expo -= + (int64_t)((src_atomic.u.f.ebias - 1) + (src_atomic.u.f.msize - (size_t)real_mant_msb)); + } + else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) + real_expo -= (int64_t)src_atomic.u.f.ebias; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + + if (0 == imag_expo || H5T_NORM_NONE == src_atomic.u.f.norm) { + assert(imag_mant_msb >= 0); + imag_expo -= + (int64_t)((src_atomic.u.f.ebias - 1) + (src_atomic.u.f.msize - (size_t)imag_mant_msb)); + } + else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) + imag_expo -= (int64_t)src_atomic.u.f.ebias; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + + /* + * If the destination is not normalized then right shift the + * mantissa by one. + */ + real_mrsh = 0; + imag_mrsh = 0; + if (H5T_NORM_NONE == dst_atomic.u.f.norm) { + real_mrsh++; + imag_mrsh++; + } + + /* + * Calculate the destination exponent by adding the destination + * bias and clipping by the minimum and maximum possible + * destination exponent values. + */ + real_expo += (int64_t)dst_atomic.u.f.ebias; + imag_expo += (int64_t)dst_atomic.u.f.ebias; + + if (real_expo < -(hssize_t)(dst_atomic.u.f.msize)) { + /* The exponent is way too small. Result is zero. */ + real_expo = 0; + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + real_msize = 0; + } + else if (real_expo <= 0) { + /* + * The exponent is too small to fit in the exponent field, + * but by shifting the mantissa to the right we can + * accommodate that value. The mantissa of course is no + * longer normalized. + */ + real_mrsh += (size_t)(1 - real_expo); + real_expo = 0; + real_denormalized = true; + } + else if (real_expo >= expo_max) { + /* + * The exponent is too large to fit in the available region + * or it results in the maximum possible value. Use positive + * or negative infinity instead unless the application + * specifies something else. Before calling the overflow + * handler make sure the source buffer we hand it is in the + * original byte order. + */ + if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } + + if (except_ret == H5T_CONV_UNHANDLED) { + real_expo = expo_max; + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + real_msize = 0; + } + else if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + + if (imag_expo < -(hssize_t)(dst_atomic.u.f.msize)) { + /* The exponent is way too small. Result is zero. */ + imag_expo = 0; + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + imag_msize = 0; + } + else if (imag_expo <= 0) { + /* + * The exponent is too small to fit in the exponent field, + * but by shifting the mantissa to the right we can + * accommodate that value. The mantissa of course is no + * longer normalized. + */ + imag_mrsh += (size_t)(1 - imag_expo); + imag_expo = 0; + imag_denormalized = true; + } + else if (imag_expo >= expo_max) { + /* + * The exponent is too large to fit in the available region + * or it results in the maximum possible value. Use positive + * or negative infinity instead unless the application + * specifies something else. Before calling the overflow + * handler make sure the source buffer we hand it is in the + * original byte order. + */ + if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } + + if (except_ret == H5T_CONV_UNHANDLED) { + imag_expo = expo_max; + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + imag_msize = 0; + } + else if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + + /* + * If the destination mantissa is smaller than the source + * mantissa then round the source mantissa. Rounding may cause a + * carry in which case the exponent has to be re-evaluated for + * overflow. That is, if `carry' is clear then the implied + * mantissa bit is `1', else it is `10' binary. + */ + real_implied = 1; + imag_implied = 1; + mpos = src_atomic.u.f.mpos; + if (real_msize > 0 && real_mrsh <= dst_atomic.u.f.msize && + real_mrsh + real_msize > dst_atomic.u.f.msize) { + real_mant_msb = (ssize_t)(real_mrsh + real_msize - dst_atomic.u.f.msize); + assert(real_mant_msb >= 0 && (size_t)real_mant_msb <= real_msize); + /* If the 1st bit being cut off is set and source isn't denormalized. */ + if (H5T__bit_get_d(s, (mpos + (size_t)real_mant_msb) - 1, (size_t)1) && !real_denormalized) { + /* Don't do rounding if exponent is 111...110 and mantissa is 111...11. + * To do rounding and increment exponent in this case will create an infinity value. */ + if ((H5T__bit_find(s, mpos + (size_t)real_mant_msb, real_msize - (size_t)real_mant_msb, + H5T_BIT_LSB, false) >= 0 || + real_expo < expo_max - 1)) { + real_carry = H5T__bit_inc(s, mpos + (size_t)real_mant_msb - 1, + 1 + real_msize - (size_t)real_mant_msb); + if (real_carry) + real_implied = 2; + } + } + else if (H5T__bit_get_d(s, (mpos + (size_t)real_mant_msb) - 1, (size_t)1) && real_denormalized) + /* For either source or destination, denormalized value doesn't increment carry. */ + H5T__bit_inc(s, mpos + (size_t)real_mant_msb - 1, 1 + real_msize - (size_t)real_mant_msb); + } + else + real_carry = false; + + if (imag_msize > 0 && imag_mrsh <= dst_atomic.u.f.msize && + imag_mrsh + imag_msize > dst_atomic.u.f.msize) { + imag_mant_msb = (ssize_t)(imag_mrsh + imag_msize - dst_atomic.u.f.msize); + assert(imag_mant_msb >= 0 && (size_t)imag_mant_msb <= imag_msize); + /* If the 1st bit being cut off is set and source isn't denormalized. */ + if (H5T__bit_get_d(s + src_part_size, (mpos + (size_t)imag_mant_msb) - 1, (size_t)1) && + !imag_denormalized) { + /* Don't do rounding if exponent is 111...110 and mantissa is 111...11. + * To do rounding and increment exponent in this case will create an infinity value. */ + if ((H5T__bit_find(s + src_part_size, mpos + (size_t)imag_mant_msb, + imag_msize - (size_t)imag_mant_msb, H5T_BIT_LSB, false) >= 0 || + imag_expo < expo_max - 1)) { + imag_carry = H5T__bit_inc(s + src_part_size, mpos + (size_t)imag_mant_msb - 1, + 1 + imag_msize - (size_t)imag_mant_msb); + if (imag_carry) + imag_implied = 2; + } + } + else if (H5T__bit_get_d(s + src_part_size, (mpos + (size_t)imag_mant_msb) - 1, (size_t)1) && + imag_denormalized) + /* For either source or destination, denormalized value doesn't increment carry. */ + H5T__bit_inc(s + src_part_size, mpos + (size_t)imag_mant_msb - 1, + 1 + imag_msize - (size_t)imag_mant_msb); + } + else + imag_carry = false; + + /* Write the mantissa to the destination */ + if (real_mrsh > dst_atomic.u.f.msize + 1) { + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + } + else if (real_mrsh == dst_atomic.u.f.msize + 1) { + H5T__bit_set(d, dst_atomic.u.f.mpos + 1, dst_atomic.u.f.msize - 1, false); + H5T__bit_set(d, dst_atomic.u.f.mpos, (size_t)1, true); + } + else if (real_mrsh == dst_atomic.u.f.msize) { + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + H5T__bit_set_d(d, dst_atomic.u.f.mpos, MIN(2, dst_atomic.u.f.msize), (hsize_t)real_implied); + } + else { + if (real_mrsh > 0) { + H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - real_mrsh, real_mrsh, false); + H5T__bit_set_d(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - real_mrsh, (size_t)2, + (hsize_t)real_implied); + } + if (real_mrsh + real_msize >= dst_atomic.u.f.msize) { + H5T__bit_copy(d, dst_atomic.u.f.mpos, s, + (mpos + real_msize + real_mrsh - dst_atomic.u.f.msize), + dst_atomic.u.f.msize - real_mrsh); + } + else { + H5T__bit_copy(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - (real_mrsh + real_msize), s, + mpos, real_msize); + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize - (real_mrsh + real_msize), false); + } + } + + if (imag_mrsh > dst_atomic.u.f.msize + 1) { + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + } + else if (imag_mrsh == dst_atomic.u.f.msize + 1) { + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos + 1, dst_atomic.u.f.msize - 1, false); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, (size_t)1, true); + } + else if (imag_mrsh == dst_atomic.u.f.msize) { + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + H5T__bit_set_d(d + dst_part_size, dst_atomic.u.f.mpos, MIN(2, dst_atomic.u.f.msize), + (hsize_t)imag_implied); + } + else { + if (imag_mrsh > 0) { + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - imag_mrsh, + imag_mrsh, false); + H5T__bit_set_d(d + dst_part_size, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - imag_mrsh, + (size_t)2, (hsize_t)imag_implied); + } + if (imag_mrsh + imag_msize >= dst_atomic.u.f.msize) { + H5T__bit_copy(d + dst_part_size, dst_atomic.u.f.mpos, s + src_part_size, + (mpos + imag_msize + imag_mrsh - dst_atomic.u.f.msize), + dst_atomic.u.f.msize - imag_mrsh); + } + else { + H5T__bit_copy(d + dst_part_size, + dst_atomic.u.f.mpos + dst_atomic.u.f.msize - (imag_mrsh + imag_msize), + s + src_part_size, mpos, imag_msize); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, + dst_atomic.u.f.msize - (imag_mrsh + imag_msize), false); + } + } + + /* Write the exponent */ + if (real_carry) { + real_expo++; + if (real_expo >= expo_max) { + /* + * The exponent is too large to fit in the available + * region or it results in the maximum possible value. + * Use positive or negative infinity instead unless the + * application specifies something else. Before calling + * the overflow handler make sure the source buffer we + * hand it is in the original byte order. + */ + if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } + + if (except_ret == H5T_CONV_UNHANDLED) { + real_expo = expo_max; + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + } + else if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + } + + if (imag_carry) { + imag_expo++; + if (imag_expo >= expo_max) { + /* + * The exponent is too large to fit in the available + * region or it results in the maximum possible value. + * Use positive or negative infinity instead unless the + * application specifies something else. Before calling + * the overflow handler make sure the source buffer we + * hand it is in the original byte order. + */ + if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } + + if (except_ret == H5T_CONV_UNHANDLED) { + imag_expo = expo_max; + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + } + else if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + } + + real_carry = false; + imag_carry = false; + + H5_CHECK_OVERFLOW(real_expo, hssize_t, hsize_t); + H5T__bit_set_d(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, (hsize_t)real_expo); + H5_CHECK_OVERFLOW(imag_expo, hssize_t, hsize_t); + H5T__bit_set_d(d + dst_part_size, dst_atomic.u.f.epos, dst_atomic.u.f.esize, (hsize_t)imag_expo); + +padding: + /* + * Set external padding areas + */ + if (dst_atomic.offset > 0) { + assert(H5T_PAD_ZERO == dst_atomic.lsb_pad || H5T_PAD_ONE == dst_atomic.lsb_pad); + H5T__bit_set(d, (size_t)0, dst_atomic.offset, (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad)); + H5T__bit_set(d + dst_part_size, (size_t)0, dst_atomic.offset, + (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad)); + } + { + size_t type_size = dst_p->shared->parent->shared->size; + + if (dst_atomic.offset + dst_atomic.prec != 8 * type_size) { + assert(H5T_PAD_ZERO == dst_atomic.msb_pad || H5T_PAD_ONE == dst_atomic.msb_pad); + H5T__bit_set(d, dst_atomic.offset + dst_atomic.prec, + 8 * type_size - (dst_atomic.offset + dst_atomic.prec), + (bool)(H5T_PAD_ONE == dst_atomic.msb_pad)); + H5T__bit_set(d + dst_part_size, dst_atomic.offset + dst_atomic.prec, + 8 * type_size - (dst_atomic.offset + dst_atomic.prec), + (bool)(H5T_PAD_ONE == dst_atomic.msb_pad)); + } + } + + /* Put the destination in the correct byte order. See note at beginning of loop. */ + if (H5T_ORDER_BE == dst_atomic.order && reverse) { + uint8_t *cur_part = d; + /* Swap real part of complex number element */ + for (size_t j = 0; j < dst_part_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, dst_part_size - (j + 1)); + /* Swap imaginary part of complex number element */ + cur_part += dst_part_size; + for (size_t j = 0; j < dst_part_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, dst_part_size - (j + 1)); + } + else if (H5T_ORDER_VAX == dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + +next: + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d == dbuf) + H5MM_memcpy(dp, d, dst_p->shared->size); + + /* Advance source & destination pointers by delta amounts */ + sp += src_delta; + dp += dst_delta; + } /* end conversion loop */ + +done: + H5MM_free(src_rev); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_complex_loop() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_complex_i + * + * Purpose: Convert complex number values to integer values. This is + * the catch-all function for complex number -> integer + * conversions and is probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_complex_i(const H5T_t *src_p, const H5T_t *dst_p, 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) +{ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_PACKAGE + + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (!H5T_IS_ATOMIC(src_p->shared->parent->shared)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid complex number datatype"); + src_atomic = src_p->shared->parent->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for source datatype"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for destination datatype"); + if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large"); + if (8 * sizeof(hssize_t) - 1 < src_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; + + break; + } + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); + + if (H5T__conv_f_i_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); + + break; + + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_complex_i() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_complex_f + * + * Purpose: Convert complex number values to floating-point values. + * This is the catch-all function for complex number -> float + * conversions and is probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_complex_f(const H5T_t *src_p, const H5T_t *dst_p, 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) +{ + bool equal_cplx_conv = false; /* if converting between complex and matching float */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_PACKAGE + + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (!H5T_IS_ATOMIC(src_p->shared->parent->shared)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid complex number datatype"); + src_atomic = src_p->shared->parent->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for source datatype"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for destination datatype"); + if (dst_p->shared->size > TEMP_FLOAT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large"); + if (8 * sizeof(int64_t) - 1 < src_atomic.u.f.esize || + 8 * sizeof(int64_t) - 1 < dst_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; + + break; + } + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); + + /* Are we converting between a floating-point type and a complex number + * type consisting of the same floating-point type? + */ + /* TODO: cache result */ + equal_cplx_conv = (0 == H5T_cmp(src_p->shared->parent, dst_p, false)); + if (!equal_cplx_conv) { + /* If floating-point types differ, use generic f_f loop */ + if (H5T__conv_f_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); + } + else { + /* If floating-point types are the same, use specialized loop */ + if (H5T__conv_complex_f_matched(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); + } + + break; + + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_complex_f() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_complex_f_matched + * + * Purpose: Implements the body of the conversion loop when converting + * between a floating-point type and a complex number type + * consisting of the same floating-point type. Encapsulates + * common code that is shared between the H5T__conv_complex_f + * and H5T__conv_f_complex functions. Values can be directly + * converted between the types after checking for conversion + * exceptions. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_complex_f_matched(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, void *buf) +{ + H5T_conv_float_specval_t specval_type; /* floating-point value type (regular, +/-Inf, +/-0, NaN) */ + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + ssize_t src_delta, dst_delta; /* source & destination stride */ + uint8_t *s, *sp, *d, *dp; /* source and dest traversal ptrs */ + uint8_t *src_rev = NULL; /* order-reversed source buffer */ + uint8_t dbuf[TEMP_FLOAT_CONV_BUFFER_SIZE]; /* temp destination buffer */ + size_t olap; /* num overlapping elements */ + int direction; /* forward or backward traversal */ + herr_t ret_value = SUCCEED; + + assert(src_p); + assert(src_p->shared->type == H5T_FLOAT || src_p->shared->type == H5T_COMPLEX); + assert(dst_p); + assert(dst_p->shared->type == H5T_FLOAT || dst_p->shared->type == H5T_COMPLEX); + assert(conv_ctx); + assert(buf); + + FUNC_ENTER_PACKAGE + + if (src_p->shared->type == H5T_COMPLEX) + src_atomic = src_p->shared->parent->shared->u.atomic; + else + src_atomic = src_p->shared->u.atomic; + if (dst_p->shared->type == H5T_COMPLEX) + dst_atomic = dst_p->shared->parent->shared->u.atomic; + else + dst_atomic = dst_p->shared->u.atomic; + +#ifndef NDEBUG + { + /* Make sure the floating-point types match */ + const H5T_t *src_base = (src_p->shared->type == H5T_FLOAT) ? src_p : src_p->shared->parent; + const H5T_t *dst_base = (dst_p->shared->type == H5T_FLOAT) ? dst_p : dst_p->shared->parent; + assert(0 == (H5T_cmp(src_base, dst_base, false))); + } +#endif + + /* + * Do we process the values from beginning to end or vice versa? Also, + * how many of the elements have the source and destination areas + * overlapping? + */ + if (src_p->shared->size == dst_p->shared->size || buf_stride) { + sp = dp = (uint8_t *)buf; + direction = 1; + olap = nelmts; + } + else if (src_p->shared->size >= dst_p->shared->size) { + double olap_d = + ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); + olap = (size_t)olap_d; + sp = dp = (uint8_t *)buf; + direction = 1; + } + else { + double olap_d = + ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); + olap = (size_t)olap_d; + sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; + dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; + direction = -1; + } + + /* Direction & size of buffer traversal */ + H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); + H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t); + H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t); + src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size); + dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size); + + /* Allocate space for order-reversed source buffer */ + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src_p->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer"); + + /* The conversion loop */ + for (size_t elmtno = 0; elmtno < nelmts; elmtno++) { + H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED; /* return of conversion exception callback function */ + bool reverse = true; /* if reversed the order of destination */ + + /* + * If the source and destination buffers overlap then use a + * temporary buffer for the destination. + */ + s = sp; + if (direction > 0) + d = elmtno < olap ? dbuf : dp; + else + d = elmtno + olap >= nelmts ? dbuf : dp; + if (d == dbuf) + memset(dbuf, 0, sizeof(dbuf)); + +#ifndef NDEBUG + if (d == dbuf) { + assert((dp >= sp && dp < sp + src_p->shared->size) || + (sp >= dp && sp < dp + dst_p->shared->size)); + } + else { + assert((dp < sp && dp + dst_p->shared->size <= sp) || + (sp < dp && sp + src_p->shared->size <= dp)); + } +#endif + + /* + * Put the data in little endian order so our loops aren't so + * complicated. We'll do all the conversion stuff assuming + * little endian and then we'll fix the order at the end. + */ + if (H5T_ORDER_BE == src_atomic.order) { + size_t half_size = src_p->shared->size / 2; + + if (H5T_FLOAT == src_p->shared->type) { + for (size_t j = 0; j < half_size; j++) + H5_SWAP_BYTES(s, j, src_p->shared->size - (j + 1)); + } + else { + uint8_t *cur_part = s; + /* Swap real part of complex number element */ + for (size_t j = 0; j < half_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, half_size - (j + 1)); + /* Swap imaginary part of complex number element */ + cur_part += half_size; + for (size_t j = 0; j < half_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, half_size - (j + 1)); + } + } + else if (H5T_ORDER_VAX == src_atomic.order) { + if (H5T_FLOAT == src_p->shared->type) { + uint8_t tmp1, tmp2; + size_t tsize = src_p->shared->size; + assert(0 == tsize % 2); + + for (size_t i = 0; i < tsize; i += 4) { + tmp1 = s[i]; + tmp2 = s[i + 1]; + + s[i] = s[(tsize - 2) - i]; + s[i + 1] = s[(tsize - 1) - i]; + + s[(tsize - 2) - i] = tmp1; + s[(tsize - 1) - i] = tmp2; + } + } + else + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + } + + /* Check for special cases: +0, -0, +Inf, -Inf, NaN */ + specval_type = H5T__conv_float_find_special(s, &src_atomic, NULL); + if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO || + specval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO) { + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false); + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + goto padding; + } + else if (specval_type != H5T_CONV_FLOAT_SPECVAL_REGULAR) { + /* If user's exception handler is present, use it */ + if (conv_ctx->u.conv.cb_struct.func) { + H5T_conv_except_t except_type; /* type of conversion exception that occurred */ + + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSINF) + except_type = H5T_CONV_EXCEPT_PINF; + else if (specval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) + except_type = H5T_CONV_EXCEPT_NINF; + else + except_type = H5T_CONV_EXCEPT_NAN; + + except_ret = (conv_ctx->u.conv.cb_struct.func)(except_type, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); + } + + if (except_ret == H5T_CONV_UNHANDLED) { + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true); + if (specval_type == H5T_CONV_FLOAT_SPECVAL_NAN) + /* There are many NaN values, so we just set all bits of the significand. */ + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, true); + else { + /* +/-Inf */ + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + /* If the destination has no implied mantissa bit, we'll need to set + * the 1st bit of mantissa to 1. The Intel-Linux "long double" is + * this case. */ + if (H5T_NORM_NONE == dst_atomic.u.f.norm) + H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - 1, (size_t)1, true); + } + } + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + + goto padding; + } + + /* Direct copy between complex number and floating-point type */ + if (H5T_FLOAT == src_p->shared->type) + memcpy(d, s, src_p->shared->size); + else + memcpy(d, s, src_p->shared->size / 2); + +padding: + /* + * Set external padding areas + */ + if (dst_atomic.offset > 0) { + assert(H5T_PAD_ZERO == dst_atomic.lsb_pad || H5T_PAD_ONE == dst_atomic.lsb_pad); + H5T__bit_set(d, (size_t)0, dst_atomic.offset, (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad)); + } + { + size_t type_size; + + if (dst_p->shared->type == H5T_FLOAT) + type_size = dst_p->shared->size; + else + type_size = dst_p->shared->parent->shared->size; + + if (dst_atomic.offset + dst_atomic.prec != 8 * type_size) { + assert(H5T_PAD_ZERO == dst_atomic.msb_pad || H5T_PAD_ONE == dst_atomic.msb_pad); + H5T__bit_set(d, dst_atomic.offset + dst_atomic.prec, + 8 * type_size - (dst_atomic.offset + dst_atomic.prec), + (bool)(H5T_PAD_ONE == dst_atomic.msb_pad)); + } + } + + /* + * Put the destination in the correct byte order. See note at + * beginning of loop. Only the "real" part of a complex number + * element is swapped. By the C standard, the "imaginary" part + * should just be zeroed when converting a real value to a + * complex value. + */ + if (H5T_ORDER_BE == dst_atomic.order && reverse) { + size_t half_size = dst_p->shared->size / 2; + + if (H5T_FLOAT == dst_p->shared->type) { + for (size_t j = 0; j < half_size; j++) + H5_SWAP_BYTES(d, j, dst_p->shared->size - (j + 1)); + } + else { + for (size_t j = 0; j < half_size / 2; j++) + H5_SWAP_BYTES(d, j, half_size - (j + 1)); + } + } + else if (H5T_ORDER_VAX == dst_atomic.order && reverse) { + if (H5T_FLOAT == dst_p->shared->type) { + uint8_t tmp1, tmp2; + size_t tsize = dst_p->shared->size / 2; + assert(0 == tsize % 2); + + for (size_t i = 0; i < tsize; i += 4) { + tmp1 = d[i]; + tmp2 = d[i + 1]; + + d[i] = d[(tsize - 2) - i]; + d[i + 1] = d[(tsize - 1) - i]; + + d[(tsize - 2) - i] = tmp1; + d[(tsize - 1) - i] = tmp2; + } + } + else + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + } + +next: + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d == dbuf) { + if (H5T_FLOAT == dst_p->shared->type) + H5MM_memcpy(dp, d, dst_p->shared->size); + else + H5MM_memcpy(dp, d, dst_p->shared->size / 2); + } + + /* Ensure imaginary part of complex number is zeroed */ + if (H5T_COMPLEX == dst_p->shared->type) + memset(dp + (dst_p->shared->size / 2), 0, dst_p->shared->size / 2); + + /* Advance source & destination pointers by delta amounts */ + sp += src_delta; + dp += dst_delta; + } /* end conversion loop */ + +done: + H5MM_free(src_rev); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_complex_f_matched() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_complex_struct + * + * Purpose: Convert a complex number type to the equivalent compound + * type representation. A compound type must match one of the + * the following representations exactly to be considered + * equivalent. + * + * H5T_COMPOUND { + * "r"; OFFSET 0 + * "i"; OFFSET SIZEOF("r") + * } + * + * H5T_COMPOUND { + * "re"; OFFSET 0 + * "im"; OFFSET SIZEOF("re") + * } + * + * H5T_COMPOUND { + * "real"; OFFSET 0 + * "imag"; OFFSET SIZEOF("real") + * } + * + * H5T_COMPOUND { + * "real"; OFFSET 0 + * "imaginary"; OFFSET SIZEOF("real") + * } + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_complex_struct(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, + void *_buf, void *bkg) +{ + (void)src; + (void)dst; + (void)cdata; + (void)conv_ctx; + (void)nelmts; + (void)buf_stride; + (void)bkg_stride; + (void)_buf; + (void)bkg; + return FAIL; /* TODO */ +} + +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_schar + * + * Purpose: Converts `float _Complex' to `signed char' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_schar(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, SCHAR, float _Complex, signed char, SCHAR_MIN, SCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_uchar + * + * Purpose: Converts `float _Complex' to `unsigned char' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_uchar(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, UCHAR, float _Complex, unsigned char, 0, UCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_short + * + * Purpose: Converts `float _Complex' to `short' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_short(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, SHORT, float _Complex, short, SHRT_MIN, SHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ushort + * + * Purpose: Converts `float _Complex' to `unsigned short' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_ushort(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, USHORT, float _Complex, unsigned short, 0, USHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_int + * + * Purpose: Converts `float _Complex' to `int' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_int(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, INT, float _Complex, int, INT_MIN, INT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_uint + * + * Purpose: Converts `float _Complex' to `unsigned int' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_uint(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, UINT, float _Complex, unsigned int, 0, UINT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_long + * + * Purpose: Converts `float _Complex' to `long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_long(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, LONG, float _Complex, long, LONG_MIN, LONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ulong + * + * Purpose: Converts `float _Complex' to `unsigned long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_ulong(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, ULONG, float _Complex, unsigned long, 0, ULONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_llong + * + * Purpose: Converts `float _Complex' to `long long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_llong(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, LLONG, float _Complex, long long, LLONG_MIN, LLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ullong + * + * Purpose: Converts `float _Complex' to `unsigned long long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_ullong(const H5T_t *st, const 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_Zx(FLOAT_COMPLEX, ULLONG, float _Complex, unsigned long long, 0, ULLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +#ifdef H5_HAVE__FLOAT16 +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex__Float16 + * + * Purpose: Converts `float _Complex' to `_Float16' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex__Float16(const H5T_t *st, const 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_Zf(FLOAT_COMPLEX, FLOAT16, float _Complex, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} +#endif + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_float + * + * Purpose: Converts `float _Complex' to `float' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_float(const H5T_t *st, const 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_zf(FLOAT_COMPLEX, FLOAT, float _Complex, float, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_double + * + * Purpose: Converts `float _Complex' to `double' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_double(const H5T_t *st, const 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_zF(FLOAT_COMPLEX, DOUBLE, float _Complex, double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ldouble + * + * Purpose: Converts `float _Complex' to `long double' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_ldouble(const H5T_t *st, const 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_zF(FLOAT_COMPLEX, LDOUBLE, float _Complex, long double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_dcomplex + * + * Purpose: Converts `float _Complex' to `double _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_dcomplex(const H5T_t *st, const 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_zZ(FLOAT_COMPLEX, DOUBLE_COMPLEX, float _Complex, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_lcomplex + * + * Purpose: Converts `float _Complex' to `long double _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_fcomplex_lcomplex(const H5T_t *st, const 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_zZ(FLOAT_COMPLEX, LDOUBLE_COMPLEX, float _Complex, long double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_schar + * + * Purpose: Converts `double _Complex' to `signed char' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_schar(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, SCHAR, double _Complex, signed char, SCHAR_MIN, SCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_uchar + * + * Purpose: Converts `double _Complex' to `unsigned char' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_uchar(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, UCHAR, double _Complex, unsigned char, 0, UCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_short + * + * Purpose: Converts `double _Complex' to `short' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_short(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, SHORT, double _Complex, short, SHRT_MIN, SHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ushort + * + * Purpose: Converts `double _Complex' to `unsigned short' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_ushort(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, USHORT, double _Complex, unsigned short, 0, USHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_int + * + * Purpose: Converts `double _Complex' to `int' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_int(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, INT, double _Complex, int, INT_MIN, INT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_uint + * + * Purpose: Converts `double _Complex' to `unsigned int' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_uint(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, UINT, double _Complex, unsigned int, 0, UINT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_long + * + * Purpose: Converts `double _Complex' to `long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_long(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, LONG, double _Complex, long, LONG_MIN, LONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ulong + * + * Purpose: Converts `double _Complex' to `unsigned long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_ulong(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, ULONG, double _Complex, unsigned long, 0, ULONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_llong + * + * Purpose: Converts `double _Complex' to `long long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_llong(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, LLONG, double _Complex, long long, LLONG_MIN, LLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ullong + * + * Purpose: Converts `double _Complex' to `unsigned long long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_ullong(const H5T_t *st, const 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_Zx(DOUBLE_COMPLEX, ULLONG, double _Complex, unsigned long long, 0, ULLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +#ifdef H5_HAVE__FLOAT16 +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex__Float16 + * + * Purpose: Converts `double _Complex' to `_Float16' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex__Float16(const H5T_t *st, const 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_Zf(DOUBLE_COMPLEX, FLOAT16, double _Complex, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} +#endif + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_float + * + * Purpose: Converts `double _Complex' to `float' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_float(const H5T_t *st, const 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_Zf(DOUBLE_COMPLEX, FLOAT, double _Complex, float, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_double + * + * Purpose: Converts `double _Complex' to `double' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_double(const H5T_t *st, const 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_zf(DOUBLE_COMPLEX, DOUBLE, double _Complex, double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ldouble + * + * Purpose: Converts `double _Complex' to `long double' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_ldouble(const H5T_t *st, const 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_zF(DOUBLE_COMPLEX, LDOUBLE, double _Complex, long double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_fcomplex + * + * Purpose: Converts `double _Complex' to `float _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_fcomplex(const H5T_t *st, const 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_Zz(DOUBLE_COMPLEX, FLOAT_COMPLEX, double _Complex, float _Complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_lcomplex + * + * Purpose: Converts `double _Complex' to `long double _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_dcomplex_lcomplex(const H5T_t *st, const 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_zZ(DOUBLE_COMPLEX, LDOUBLE_COMPLEX, double _Complex, long double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_schar + * + * Purpose: Converts `long double _Complex' to `signed char' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_schar(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, SCHAR, long double _Complex, signed char, SCHAR_MIN, SCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_uchar + * + * Purpose: Converts `long double _Complex' to `unsigned char' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_uchar(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, UCHAR, long double _Complex, unsigned char, 0, UCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_short + * + * Purpose: Converts `long double _Complex' to `short' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_short(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, SHORT, long double _Complex, short, SHRT_MIN, SHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_ushort + * + * Purpose: Converts `long double _Complex' to `unsigned short' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_ushort(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, USHORT, long double _Complex, unsigned short, 0, USHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_int + * + * Purpose: Converts `long double _Complex' to `int' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_int(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, INT, long double _Complex, int, INT_MIN, INT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_uint + * + * Purpose: Converts `long double _Complex' to `unsigned int' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_uint(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, UINT, long double _Complex, unsigned int, 0, UINT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_long + * + * Purpose: Converts `long double _Complex' to `long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_long(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, LONG, long double _Complex, long, LONG_MIN, LONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_ulong + * + * Purpose: Converts `long double _Complex' to `unsigned long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_ulong(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, ULONG, long double _Complex, unsigned long, 0, ULONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_llong + * + * Purpose: Converts `long double _Complex' to `long long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG +herr_t +H5T__conv_lcomplex_llong(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, LLONG, long double _Complex, long long, LLONG_MIN, LLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} +#endif /* H5T_CONV_INTERNAL_LDOUBLE_LLONG */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_ullong + * + * Purpose: Converts `long double _Complex' to `unsigned long long' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +#ifdef H5T_CONV_INTERNAL_LDOUBLE_ULLONG +herr_t +H5T__conv_lcomplex_ullong(const H5T_t *st, const 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_Zx(LDOUBLE_COMPLEX, ULLONG, long double _Complex, unsigned long long, 0, ULLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} +#endif /* H5T_CONV_INTERNAL_LDOUBLE_ULLONG */ + +#ifdef H5_HAVE__FLOAT16 +#ifdef H5T_CONV_INTERNAL_LDOUBLE_FLOAT16 +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex__Float16 + * + * Purpose: Converts `long double _Complex' to `_Float16' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex__Float16(const H5T_t *st, const 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_Zf(LDOUBLE_COMPLEX, FLOAT16, long double _Complex, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} +#endif +#endif + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_float + * + * Purpose: Converts `long double _Complex' to `float' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_float(const H5T_t *st, const 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_Zf(LDOUBLE_COMPLEX, FLOAT, long double _Complex, float, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_double + * + * Purpose: Converts `long double _Complex' to `double' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_double(const H5T_t *st, const 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_Zf(LDOUBLE_COMPLEX, DOUBLE, long double _Complex, double, -DBL_MAX, DBL_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_ldouble + * + * Purpose: Converts `long double _Complex' to `long double' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_ldouble(const H5T_t *st, const 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_zf(LDOUBLE_COMPLEX, LDOUBLE, long double _Complex, long double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_fcomplex + * + * Purpose: Converts `long double _Complex' to `float _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_fcomplex(const H5T_t *st, const 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_Zz(LDOUBLE_COMPLEX, FLOAT_COMPLEX, long double _Complex, float _Complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_dcomplex + * + * Purpose: Converts `long double _Complex' to `double _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_lcomplex_dcomplex(const H5T_t *st, const 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_Zz(LDOUBLE_COMPLEX, DOUBLE_COMPLEX, long double _Complex, double _Complex, -DBL_MAX, DBL_MAX); +} +#endif /* H5_HAVE_COMPLEX_NUMBERS */ diff --git a/src/H5Tconv_complex.h b/src/H5Tconv_complex.h new file mode 100644 index 00000000000..28b0b7ba01e --- /dev/null +++ b/src/H5Tconv_complex.h @@ -0,0 +1,210 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +#ifndef H5Tconv_complex_H +#define H5Tconv_complex_H + +/* Private headers needed by this file */ +#include "H5Tpkg.h" + +/***********************/ +/* Function Prototypes */ +/***********************/ + +/* Helper functions shared between conversion modules */ +H5_DLL herr_t H5T__conv_complex_f_matched(const H5T_t *src_p, const H5T_t *dst_p, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + void *buf); + +/****************************************/ +/* Soft (emulated) conversion functions */ +/****************************************/ + +/* Conversion functions between complex number datatypes */ +H5_DLL herr_t H5T__conv_complex(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); + +/* Conversion functions from complex number datatype to another datatype class */ +H5_DLL herr_t H5T__conv_complex_i(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_complex_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_complex_struct(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *_buf, void *bkg); + +/*********************************************/ +/* Hard (compiler cast) conversion functions */ +/*********************************************/ + +#ifdef H5_HAVE_COMPLEX_NUMBERS +/* Conversion functions for 'float _Complex' */ +H5_DLL herr_t H5T__conv_fcomplex_schar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_uchar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_short(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_ushort(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_int(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_uint(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_long(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_ulong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_llong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_ullong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE__FLOAT16 +H5_DLL herr_t H5T__conv_fcomplex__Float16(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif +H5_DLL herr_t H5T__conv_fcomplex_float(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_dcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_fcomplex_lcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); + +/* Conversion functions for 'double _Complex' */ +H5_DLL herr_t H5T__conv_dcomplex_schar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_uchar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_short(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_ushort(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_int(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_uint(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_long(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_ulong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_llong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_ullong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE__FLOAT16 +H5_DLL herr_t H5T__conv_dcomplex__Float16(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif +H5_DLL herr_t H5T__conv_dcomplex_float(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_fcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_dcomplex_lcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); + +/* Conversion functions for 'long double _Complex' */ +H5_DLL herr_t H5T__conv_lcomplex_schar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_uchar(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_short(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_ushort(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_int(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_uint(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_long(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_ulong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_llong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_ullong(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE__FLOAT16 +H5_DLL herr_t H5T__conv_lcomplex__Float16(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif +H5_DLL herr_t H5T__conv_lcomplex_float(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_fcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_lcomplex_dcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* H5_HAVE_COMPLEX_NUMBERS */ + +#endif /* H5Tconv_complex_H */ diff --git a/src/H5Tconv_float.c b/src/H5Tconv_float.c index 806a7261677..71221e8c331 100644 --- a/src/H5Tconv_float.c +++ b/src/H5Tconv_float.c @@ -24,6 +24,8 @@ /***********/ #include "H5Tconv.h" #include "H5Tconv_macros.h" +#include "H5Tconv_complex.h" +#include "H5Tconv_integer.h" #include "H5Tconv_float.h" /*------------------------------------------------------------------------- @@ -42,54 +44,34 @@ H5T__conv_f_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { - /* Traversal-related variables */ - H5T_atomic_t src; /*atomic source info */ - H5T_atomic_t dst; /*atomic destination info */ - ssize_t src_delta, dst_delta; /*source & destination stride */ - int direction; /*forward or backward traversal */ - size_t elmtno; /*element number */ - size_t half_size; /*half the type size */ - size_t tsize; /*type size for swapping bytes */ - size_t olap; /*num overlapping elements */ - ssize_t bitno = 0; /*bit number */ - uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ - uint8_t *src_rev = NULL; /*order-reversed source buffer */ - uint8_t dbuf[64] = {0}; /*temp destination buffer */ - uint8_t tmp1, tmp2; /*temp variables for swapping bytes*/ - - /* Conversion-related variables */ - int64_t expo; /*exponent */ - hssize_t expo_max; /*maximum possible dst exponent */ - size_t msize = 0; /*useful size of mantissa in src*/ - size_t mpos; /*offset to useful mant is src */ - uint64_t sign; /*source sign bit value */ - size_t mrsh; /*amount to right shift mantissa*/ - bool carry = false; /*carry after rounding mantissa */ - size_t i; /*miscellaneous counters */ - size_t implied; /*destination implied bits */ - bool denormalized = false; /*is either source or destination denormalized?*/ - H5T_conv_ret_t except_ret; /*return of callback function */ - bool reverse; /*if reverse the order of destination */ - herr_t ret_value = SUCCEED; /*return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE switch (cdata->command) { - case H5T_CONV_INIT: + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + if (NULL == src_p || NULL == dst_p) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; - if (H5T_ORDER_LE != src.order && H5T_ORDER_BE != src.order && H5T_ORDER_VAX != src.order) + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); - if (H5T_ORDER_LE != dst.order && H5T_ORDER_BE != dst.order && H5T_ORDER_VAX != dst.order) + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); - if (dst_p->shared->size > sizeof(dbuf)) + if (dst_p->shared->size > TEMP_FLOAT_CONV_BUFFER_SIZE) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); - if (8 * sizeof(expo) - 1 < src.u.f.esize || 8 * sizeof(expo) - 1 < dst.u.f.esize) + if (8 * sizeof(int64_t) - 1 < src_atomic.u.f.esize || + 8 * sizeof(int64_t) - 1 < dst_atomic.u.f.esize) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); cdata->need_bkg = H5T_BKG_NO; + break; + } case H5T_CONV_FREE: break; @@ -100,524 +82,625 @@ H5T__conv_f_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const if (NULL == conv_ctx) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; - expo_max = ((hssize_t)1 << dst.u.f.esize) - 1; - - /* - * Do we process the values from beginning to end or vice versa? Also, - * how many of the elements have the source and destination areas - * overlapping? - */ - if (src_p->shared->size == dst_p->shared->size || buf_stride) { - sp = dp = (uint8_t *)buf; - direction = 1; - olap = nelmts; - } - else if (src_p->shared->size >= dst_p->shared->size) { - double olap_d = - ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); - olap = (size_t)olap_d; - sp = dp = (uint8_t *)buf; - direction = 1; - } - else { - double olap_d = - ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); - olap = (size_t)olap_d; - sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; - dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; - direction = -1; - } + if (H5T__conv_f_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); - /* - * Direction & size of buffer traversal. - */ - H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); - H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t); - H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t); - src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size); - dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size); - - /* Allocate space for order-reversed source buffer */ - src_rev = (uint8_t *)H5MM_calloc(src_p->shared->size); - - /* The conversion loop */ - for (elmtno = 0; elmtno < nelmts; elmtno++) { - /* Set these variables to default */ - except_ret = H5T_CONV_UNHANDLED; - reverse = true; - - /* - * If the source and destination buffers overlap then use a - * temporary buffer for the destination. - */ - if (direction > 0) { - s = sp; - d = elmtno < olap ? dbuf : dp; - } - else { - s = sp; - d = elmtno + olap >= nelmts ? dbuf : dp; - } -#ifndef NDEBUG - /* I don't quite trust the overlap calculations yet */ - if (d == dbuf) { - assert((dp >= sp && dp < sp + src_p->shared->size) || - (sp >= dp && sp < dp + dst_p->shared->size)); - } - else { - assert((dp < sp && dp + dst_p->shared->size <= sp) || - (sp < dp && sp + src_p->shared->size <= dp)); - } -#endif + break; - /* - * Put the data in little endian order so our loops aren't so - * complicated. We'll do all the conversion stuff assuming - * little endian and then we'll fix the order at the end. - */ - if (H5T_ORDER_BE == src.order) { - half_size = src_p->shared->size / 2; - for (i = 0; i < half_size; i++) { - tmp1 = s[src_p->shared->size - (i + 1)]; - s[src_p->shared->size - (i + 1)] = s[i]; - s[i] = tmp1; - } - } - else if (H5T_ORDER_VAX == src.order) { - tsize = src_p->shared->size; - assert(0 == tsize % 2); + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } - for (i = 0; i < tsize; i += 4) { - tmp1 = s[i]; - tmp2 = s[i + 1]; +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_f_f() */ - s[i] = s[(tsize - 2) - i]; - s[i + 1] = s[(tsize - 1) - i]; +/*------------------------------------------------------------------------- + * Function: H5T__conv_f_f_loop + * + * Purpose: Implements the body of the conversion loop when converting + * floating-point values to another floating-point type + * (including complex number types). Encapsulates common + * code that is shared between the H5T__conv_f_f conversion + * function and other functions where the logic is nearly + * identical, such as H5T__conv_f_complex and + * H5T__conv_complex_f. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_f_f_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, + size_t buf_stride, void *buf) +{ + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + hssize_t expo_max; /* maximum possible dst exponent */ + ssize_t src_delta, dst_delta; /* source & destination stride */ + uint8_t *s, *sp, *d, *dp; /* source and dest traversal ptrs */ + uint8_t *src_rev = NULL; /* order-reversed source buffer */ + uint8_t dbuf[TEMP_FLOAT_CONV_BUFFER_SIZE]; /* temp destination buffer */ + size_t olap; /* num overlapping elements */ + int direction; /* forward or backward traversal */ + herr_t ret_value = SUCCEED; + + assert(src_p); + assert(src_p->shared->type == H5T_FLOAT || src_p->shared->type == H5T_COMPLEX); + assert(dst_p); + assert(dst_p->shared->type == H5T_FLOAT || dst_p->shared->type == H5T_COMPLEX); + assert(conv_ctx); + assert(buf); - s[(tsize - 2) - i] = tmp1; - s[(tsize - 1) - i] = tmp2; - } - } + FUNC_ENTER_PACKAGE - /* - * Find the sign bit value of the source. - */ - sign = H5T__bit_get_d(s, src.u.f.sign, (size_t)1); + if (src_p->shared->type == H5T_COMPLEX) + src_atomic = src_p->shared->parent->shared->u.atomic; + else + src_atomic = src_p->shared->u.atomic; + if (dst_p->shared->type == H5T_COMPLEX) + dst_atomic = dst_p->shared->parent->shared->u.atomic; + else + dst_atomic = dst_p->shared->u.atomic; - /* - * Check for special cases: +0, -0, +Inf, -Inf, NaN - */ - if (H5T__bit_find(s, src.u.f.mpos, src.u.f.msize, H5T_BIT_LSB, true) < 0) { - if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, true) < 0) { - /* +0 or -0 */ - H5T__bit_copy(d, dst.u.f.sign, s, src.u.f.sign, (size_t)1); - H5T__bit_set(d, dst.u.f.epos, dst.u.f.esize, false); - H5T__bit_set(d, dst.u.f.mpos, dst.u.f.msize, false); - goto padding; - } - else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { - /* +Inf or -Inf */ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - if (sign) - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - else - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - H5T__bit_copy(d, dst.u.f.sign, s, src.u.f.sign, (size_t)1); - 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); - /*If the destination no implied mantissa bit, we'll need to set - *the 1st bit of mantissa to 1. The Intel-Linux long double is - *this case.*/ - if (H5T_NORM_NONE == dst.u.f.norm) - H5T__bit_set(d, dst.u.f.mpos + dst.u.f.msize - 1, (size_t)1, true); - } - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - - goto padding; - } - } - else if (H5T_NORM_NONE == src.u.f.norm && - H5T__bit_find(s, src.u.f.mpos, src.u.f.msize - 1, H5T_BIT_LSB, true) < 0 && - H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { - /*This is a special case for the source of no implied mantissa bit. - *If the exponent bits are all 1s and only the 1st bit of mantissa - *is set to 1. It's infinity. The Intel-Linux "long double" is this case.*/ - /* +Inf or -Inf */ - if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - if (sign) - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - else - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } + expo_max = ((hssize_t)1 << dst_atomic.u.f.esize) - 1; - if (except_ret == H5T_CONV_UNHANDLED) { - H5T__bit_copy(d, dst.u.f.sign, s, src.u.f.sign, (size_t)1); - 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); - /*If the destination no implied mantissa bit, we'll need to set - *the 1st bit of mantissa to 1. The Intel-Linux long double is - *this case.*/ - if (H5T_NORM_NONE == dst.u.f.norm) - H5T__bit_set(d, dst.u.f.mpos + dst.u.f.msize - 1, (size_t)1, true); - } - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); +#ifndef NDEBUG + /* Are we converting between a floating-point type and a complex number + * type consisting of the same floating-point type? This function is + * only intended for converting between different floating-point types + * and will produce incorrect results otherwise. + */ + if ((src_p->shared->type == H5T_COMPLEX && dst_p->shared->type == H5T_FLOAT) || + (src_p->shared->type == H5T_FLOAT && dst_p->shared->type == H5T_COMPLEX)) { + const H5T_t *src_base = (src_p->shared->type == H5T_FLOAT) ? src_p : src_p->shared->parent; + const H5T_t *dst_base = (dst_p->shared->type == H5T_FLOAT) ? dst_p : dst_p->shared->parent; + assert(0 != (H5T_cmp(src_base, dst_base, false))); + } +#endif - goto padding; - /* Temporary solution to handle VAX special values. - * Note that even though we don't support VAX anymore, we - * still need to handle legacy VAX files so this code must - * remain in place. - */ - } - else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { - /* NaN */ - if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_NAN, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, - src_rev, d, conv_ctx->u.conv.cb_struct.user_data); - } + /* + * Do we process the values from beginning to end or vice versa? Also, + * how many of the elements have the source and destination areas + * overlapping? + */ + if (src_p->shared->size == dst_p->shared->size || buf_stride) { + sp = dp = (uint8_t *)buf; + direction = 1; + olap = nelmts; + } + else if (src_p->shared->size >= dst_p->shared->size) { + double olap_d = + ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); + olap = (size_t)olap_d; + sp = dp = (uint8_t *)buf; + direction = 1; + } + else { + double olap_d = + ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); + olap = (size_t)olap_d; + sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; + dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; + direction = -1; + } + + /* Direction & size of buffer traversal */ + H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); + H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t); + H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t); + src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size); + dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size); + + /* Allocate space for order-reversed source buffer */ + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src_p->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer"); + + /* The conversion loop */ + for (size_t elmtno = 0; elmtno < nelmts; elmtno++) { + H5T_conv_float_specval_t specval_type; /* floating-point value type (regular, +/-Inf, +/-0, NaN) */ + H5T_conv_ret_t except_ret = + H5T_CONV_UNHANDLED; /* return of conversion exception callback function */ + ssize_t bitno = 0; /* bit number */ + int64_t expo; /* exponent */ + size_t implied; /* destination implied bits */ + size_t mpos; /* offset to useful mant in src */ + size_t msize = 0; /* useful size of mantissa in src */ + size_t mrsh; /* amount to right shift mantissa */ + bool reverse = true; /* if reversed the order of destination */ + bool denormalized = false; /* is either source or destination denormalized? */ + bool carry = false; /* carry after rounding mantissa */ + + /* + * If the source and destination buffers overlap then use a + * temporary buffer for the destination. + */ + s = sp; + if (direction > 0) + d = elmtno < olap ? dbuf : dp; + else + d = elmtno + olap >= nelmts ? dbuf : dp; + if (d == dbuf) + memset(dbuf, 0, sizeof(dbuf)); - if (except_ret == H5T_CONV_UNHANDLED) { - /* There are many NaN values, so we just set all bits of - * the significand. */ - H5T__bit_copy(d, dst.u.f.sign, s, src.u.f.sign, (size_t)1); - 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, true); - } - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); +#ifndef NDEBUG + if (d == dbuf) { + assert((dp >= sp && dp < sp + src_p->shared->size) || + (sp >= dp && sp < dp + dst_p->shared->size)); + } + else { + assert((dp < sp && dp + dst_p->shared->size <= sp) || + (sp < dp && sp + src_p->shared->size <= dp)); + } +#endif - goto padding; + /* + * Put the data in little endian order so our loops aren't so + * complicated. We'll do all the conversion stuff assuming + * little endian and then we'll fix the order at the end. + */ + if (H5T_ORDER_BE == src_atomic.order) { + size_t half_size = src_p->shared->size / 2; + + if (H5T_FLOAT == src_p->shared->type) { + for (size_t j = 0; j < half_size; j++) + H5_SWAP_BYTES(s, j, src_p->shared->size - (j + 1)); + } + else { + uint8_t *cur_part = s; + /* Swap real part of complex number element */ + for (size_t j = 0; j < half_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, half_size - (j + 1)); + /* Swap imaginary part of complex number element */ + cur_part += half_size; + for (size_t j = 0; j < half_size / 2; j++) + H5_SWAP_BYTES(cur_part, j, half_size - (j + 1)); + } + } + else if (H5T_ORDER_VAX == src_atomic.order) { + if (H5T_FLOAT == src_p->shared->type) { + uint8_t tmp1, tmp2; + size_t tsize = src_p->shared->size; + assert(0 == tsize % 2); + + for (size_t i = 0; i < tsize; i += 4) { + tmp1 = s[i]; + tmp2 = s[i + 1]; + + s[i] = s[(tsize - 2) - i]; + s[i + 1] = s[(tsize - 1) - i]; + + s[(tsize - 2) - i] = tmp1; + s[(tsize - 1) - i] = tmp2; } + } + else + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + } + + /* Check for special cases: +0, -0, +Inf, -Inf, NaN */ + specval_type = H5T__conv_float_find_special(s, &src_atomic, NULL); + if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO || + specval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO) { + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, false); + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + goto padding; + } + else if (specval_type != H5T_CONV_FLOAT_SPECVAL_REGULAR) { + /* If user's exception handler is present, use it */ + if (conv_ctx->u.conv.cb_struct.func) { + H5T_conv_except_t except_type; /* type of conversion exception that occurred */ + + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSINF) + except_type = H5T_CONV_EXCEPT_PINF; + else if (specval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) + except_type = H5T_CONV_EXCEPT_NINF; + else + except_type = H5T_CONV_EXCEPT_NAN; - /* - * Get the exponent as an unsigned quantity from the section of - * the source bit field where it's located. Don't worry about - * the exponent bias yet. - */ - expo = (int64_t)H5T__bit_get_d(s, src.u.f.epos, src.u.f.esize); - - if (expo == 0) - denormalized = true; + except_ret = (conv_ctx->u.conv.cb_struct.func)(except_type, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); + } - /* - * Set markers for the source mantissa, excluding the leading `1' - * (might be implied). - */ - implied = 1; - mpos = src.u.f.mpos; - mrsh = 0; - if (0 == expo || H5T_NORM_NONE == src.u.f.norm) { - if ((bitno = H5T__bit_find(s, src.u.f.mpos, src.u.f.msize, H5T_BIT_MSB, true)) > 0) { - msize = (size_t)bitno; - } - else if (0 == bitno) { - msize = 1; - H5T__bit_set(s, src.u.f.mpos, (size_t)1, false); - } - } - else if (H5T_NORM_IMPLIED == src.u.f.norm) { - msize = src.u.f.msize; - } + if (except_ret == H5T_CONV_UNHANDLED) { + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + H5T__bit_set(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, true); + if (specval_type == H5T_CONV_FLOAT_SPECVAL_NAN) + /* There are many NaN values, so we just set all bits of the significand. */ + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, true); else { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "normalization method not implemented yet"); + /* +/-Inf */ + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + /* If the destination has no implied mantissa bit, we'll need to set + * the 1st bit of mantissa to 1. The Intel-Linux "long double" is + * this case. */ + if (H5T_NORM_NONE == dst_atomic.u.f.norm) + H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - 1, (size_t)1, true); } + } + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + + goto padding; + } + + /* + * Get the exponent as an unsigned quantity from the section of + * the source bit field where it's located. Don't worry about + * the exponent bias yet. + */ + expo = (int64_t)H5T__bit_get_d(s, src_atomic.u.f.epos, src_atomic.u.f.esize); + + if (expo == 0) + denormalized = true; + + /* + * Set markers for the source mantissa, excluding the leading `1' + * (might be implied). + */ + implied = 1; + mpos = src_atomic.u.f.mpos; + mrsh = 0; + if (0 == expo || H5T_NORM_NONE == src_atomic.u.f.norm) { + if ((bitno = H5T__bit_find(s, src_atomic.u.f.mpos, src_atomic.u.f.msize, H5T_BIT_MSB, true)) > + 0) { + msize = (size_t)bitno; + } + else if (0 == bitno) { + msize = 1; + H5T__bit_set(s, src_atomic.u.f.mpos, (size_t)1, false); + } + } + else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) { + msize = src_atomic.u.f.msize; + } + else { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + } + + /* + * The sign for the destination is the same as the sign for the + * source in all cases. + */ + H5T__bit_copy(d, dst_atomic.u.f.sign, s, src_atomic.u.f.sign, (size_t)1); + + /* + * Calculate the true source exponent by adjusting according to + * the source exponent bias. + */ + if (0 == expo || H5T_NORM_NONE == src_atomic.u.f.norm) { + assert(bitno >= 0); + expo -= (int64_t)((src_atomic.u.f.ebias - 1) + (src_atomic.u.f.msize - (size_t)bitno)); + } + else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) { + expo -= (int64_t)src_atomic.u.f.ebias; + } + else { + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + } + + /* + * If the destination is not normalized then right shift the + * mantissa by one. + */ + if (H5T_NORM_NONE == dst_atomic.u.f.norm) + mrsh++; + + /* + * Calculate the destination exponent by adding the destination + * bias and clipping by the minimum and maximum possible + * destination exponent values. + */ + expo += (int64_t)dst_atomic.u.f.ebias; + + if (expo < -(hssize_t)(dst_atomic.u.f.msize)) { + /* The exponent is way too small. Result is zero. */ + expo = 0; + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + msize = 0; + } + else if (expo <= 0) { + /* + * The exponent is too small to fit in the exponent field, + * but by shifting the mantissa to the right we can + * accommodate that value. The mantissa of course is no + * longer normalized. + */ + mrsh += (size_t)(1 - expo); + expo = 0; + denormalized = true; + } + else if (expo >= expo_max) { + /* + * The exponent is too large to fit in the available region + * or it results in the maximum possible value. Use positive + * or negative infinity instead unless the application + * specifies something else. Before calling the overflow + * handler make sure the source buffer we hand it is in the + * original byte order. + */ + if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); - /* - * The sign for the destination is the same as the sign for the - * source in all cases. - */ - H5T__bit_copy(d, dst.u.f.sign, s, src.u.f.sign, (size_t)1); + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } - /* - * Calculate the true source exponent by adjusting according to - * the source exponent bias. - */ - if (0 == expo || H5T_NORM_NONE == src.u.f.norm) { - assert(bitno >= 0); - expo -= (int64_t)((src.u.f.ebias - 1) + (src.u.f.msize - (size_t)bitno)); - } - else if (H5T_NORM_IMPLIED == src.u.f.norm) { - expo -= (int64_t)src.u.f.ebias; - } - else { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "normalization method not implemented yet"); + if (except_ret == H5T_CONV_UNHANDLED) { + expo = expo_max; + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + msize = 0; + } + else if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + + /* + * If the destination mantissa is smaller than the source + * mantissa then round the source mantissa. Rounding may cause a + * carry in which case the exponent has to be re-evaluated for + * overflow. That is, if `carry' is clear then the implied + * mantissa bit is `1', else it is `10' binary. + */ + if (msize > 0 && mrsh <= dst_atomic.u.f.msize && mrsh + msize > dst_atomic.u.f.msize) { + bitno = (ssize_t)(mrsh + msize - dst_atomic.u.f.msize); + assert(bitno >= 0 && (size_t)bitno <= msize); + /* If the 1st bit being cut off is set and source isn't denormalized. */ + if (H5T__bit_get_d(s, (mpos + (size_t)bitno) - 1, (size_t)1) && !denormalized) { + /* Don't do rounding if exponent is 111...110 and mantissa is 111...11. + * To do rounding and increment exponent in this case will create an infinity value. */ + if ((H5T__bit_find(s, mpos + (size_t)bitno, msize - (size_t)bitno, H5T_BIT_LSB, false) >= 0 || + expo < expo_max - 1)) { + carry = H5T__bit_inc(s, mpos + (size_t)bitno - 1, 1 + msize - (size_t)bitno); + if (carry) + implied = 2; } + } + else if (H5T__bit_get_d(s, (mpos + (size_t)bitno) - 1, (size_t)1) && denormalized) + /* For either source or destination, denormalized value doesn't increment carry. */ + H5T__bit_inc(s, mpos + (size_t)bitno - 1, 1 + msize - (size_t)bitno); + } + else + carry = false; + + /* + * Write the mantissa to the destination + */ + if (mrsh > dst_atomic.u.f.msize + 1) { + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + } + else if (mrsh == dst_atomic.u.f.msize + 1) { + H5T__bit_set(d, dst_atomic.u.f.mpos + 1, dst_atomic.u.f.msize - 1, false); + H5T__bit_set(d, dst_atomic.u.f.mpos, (size_t)1, true); + } + else if (mrsh == dst_atomic.u.f.msize) { + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + H5T__bit_set_d(d, dst_atomic.u.f.mpos, MIN(2, dst_atomic.u.f.msize), (hsize_t)implied); + } + else { + if (mrsh > 0) { + H5T__bit_set(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - mrsh, mrsh, false); + H5T__bit_set_d(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - mrsh, (size_t)2, + (hsize_t)implied); + } + if (mrsh + msize >= dst_atomic.u.f.msize) { + H5T__bit_copy(d, dst_atomic.u.f.mpos, s, (mpos + msize + mrsh - dst_atomic.u.f.msize), + dst_atomic.u.f.msize - mrsh); + } + else { + H5T__bit_copy(d, dst_atomic.u.f.mpos + dst_atomic.u.f.msize - (mrsh + msize), s, mpos, msize); + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize - (mrsh + msize), false); + } + } + /* Write the exponent */ + if (carry) { + expo++; + if (expo >= expo_max) { /* - * If the destination is not normalized then right shift the - * mantissa by one. - */ - if (H5T_NORM_NONE == dst.u.f.norm) - mrsh++; - - /* - * Calculate the destination exponent by adding the destination - * bias and clipping by the minimum and maximum possible - * destination exponent values. + * The exponent is too large to fit in the available + * region or it results in the maximum possible value. + * Use positive or negative infinity instead unless the + * application specifies something else. Before calling + * the overflow handler make sure the source buffer we + * hand it is in the original byte order. */ - expo += (int64_t)dst.u.f.ebias; - - if (expo < -(hssize_t)(dst.u.f.msize)) { - /* The exponent is way too small. Result is zero. */ - expo = 0; - H5T__bit_set(d, dst.u.f.mpos, dst.u.f.msize, false); - msize = 0; - } - else if (expo <= 0) { - /* - * The exponent is too small to fit in the exponent field, - * but by shifting the mantissa to the right we can - * accommodate that value. The mantissa of course is no - * longer normalized. - */ - mrsh += (size_t)(1 - expo); - expo = 0; - denormalized = true; - } - else if (expo >= expo_max) { - /* - * The exponent is too large to fit in the available region - * or it results in the maximum possible value. Use positive - * or negative infinity instead unless the application - * specifies something else. Before calling the overflow - * handler make sure the source buffer we hand it is in the - * original byte order. - */ - if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); - 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, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); - } + if (conv_ctx->u.conv.cb_struct.func) { /* If user's exception handler is present, use it */ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); - if (except_ret == H5T_CONV_UNHANDLED) { - expo = expo_max; - H5T__bit_set(d, dst.u.f.mpos, dst.u.f.msize, false); - msize = 0; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - reverse = false; - goto next; - } - } - - /* - * If the destination mantissa is smaller than the source - * mantissa then round the source mantissa. Rounding may cause a - * carry in which case the exponent has to be re-evaluated for - * overflow. That is, if `carry' is clear then the implied - * mantissa bit is `1', else it is `10' binary. - */ - if (msize > 0 && mrsh <= dst.u.f.msize && mrsh + msize > dst.u.f.msize) { - bitno = (ssize_t)(mrsh + msize - dst.u.f.msize); - assert(bitno >= 0 && (size_t)bitno <= msize); - /* If the 1st bit being cut off is set and source isn't denormalized.*/ - if (H5T__bit_get_d(s, (mpos + (size_t)bitno) - 1, (size_t)1) && !denormalized) { - /* Don't do rounding if exponent is 111...110 and mantissa is 111...11. - * To do rounding and increment exponent in this case will create an infinity value.*/ - if ((H5T__bit_find(s, mpos + (size_t)bitno, msize - (size_t)bitno, H5T_BIT_LSB, - false) >= 0 || - expo < expo_max - 1)) { - carry = H5T__bit_inc(s, mpos + (size_t)bitno - 1, 1 + msize - (size_t)bitno); - if (carry) - implied = 2; - } - } - else if (H5T__bit_get_d(s, (mpos + (size_t)bitno) - 1, (size_t)1) && denormalized) - /* For either source or destination, denormalized value doesn't increment carry.*/ - H5T__bit_inc(s, mpos + (size_t)bitno - 1, 1 + msize - (size_t)bitno); + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } - else - carry = false; - /* - * Write the mantissa to the destination - */ - if (mrsh > dst.u.f.msize + 1) { - H5T__bit_set(d, dst.u.f.mpos, dst.u.f.msize, false); - } - else if (mrsh == dst.u.f.msize + 1) { - H5T__bit_set(d, dst.u.f.mpos + 1, dst.u.f.msize - 1, false); - H5T__bit_set(d, dst.u.f.mpos, (size_t)1, true); - } - else if (mrsh == dst.u.f.msize) { - H5T__bit_set(d, dst.u.f.mpos, dst.u.f.msize, false); - H5T__bit_set_d(d, dst.u.f.mpos, MIN(2, dst.u.f.msize), (hsize_t)implied); + if (except_ret == H5T_CONV_UNHANDLED) { + expo = expo_max; + H5T__bit_set(d, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); } - else { - if (mrsh > 0) { - H5T__bit_set(d, dst.u.f.mpos + dst.u.f.msize - mrsh, mrsh, false); - H5T__bit_set_d(d, dst.u.f.mpos + dst.u.f.msize - mrsh, (size_t)2, (hsize_t)implied); - } - if (mrsh + msize >= dst.u.f.msize) { - H5T__bit_copy(d, dst.u.f.mpos, s, (mpos + msize + mrsh - dst.u.f.msize), - dst.u.f.msize - mrsh); - } - else { - H5T__bit_copy(d, dst.u.f.mpos + dst.u.f.msize - (mrsh + msize), s, mpos, msize); - H5T__bit_set(d, dst.u.f.mpos, dst.u.f.msize - (mrsh + msize), false); - } + else if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto next; } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + } - /* Write the exponent */ - if (carry) { - expo++; - if (expo >= expo_max) { - /* - * The exponent is too large to fit in the available - * region or it results in the maximum possible value. - * Use positive or negative infinity instead unless the - * application specifies something else. Before - * calling the overflow handler make sure the source - * buffer we hand it is in the original byte order. - */ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - 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, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - expo = expo_max; - H5T__bit_set(d, dst.u.f.mpos, dst.u.f.msize, false); - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - reverse = false; - goto next; - } - } - } - /*reset CARRY*/ - carry = false; + carry = false; - H5_CHECK_OVERFLOW(expo, hssize_t, hsize_t); - H5T__bit_set_d(d, dst.u.f.epos, dst.u.f.esize, (hsize_t)expo); + H5_CHECK_OVERFLOW(expo, hssize_t, hsize_t); + H5T__bit_set_d(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, (hsize_t)expo); padding: + /* + * Set external padding areas + */ + if (dst_atomic.offset > 0) { + assert(H5T_PAD_ZERO == dst_atomic.lsb_pad || H5T_PAD_ONE == dst_atomic.lsb_pad); + H5T__bit_set(d, (size_t)0, dst_atomic.offset, (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad)); + } + { + size_t type_size; + + if (dst_p->shared->type == H5T_FLOAT) + type_size = dst_p->shared->size; + else + type_size = dst_p->shared->parent->shared->size; - /* - * Set external padding areas - */ - if (dst.offset > 0) { - assert(H5T_PAD_ZERO == dst.lsb_pad || H5T_PAD_ONE == dst.lsb_pad); - H5T__bit_set(d, (size_t)0, dst.offset, (bool)(H5T_PAD_ONE == dst.lsb_pad)); - } - if (dst.offset + dst.prec != 8 * dst_p->shared->size) { - assert(H5T_PAD_ZERO == dst.msb_pad || H5T_PAD_ONE == dst.msb_pad); - H5T__bit_set(d, dst.offset + dst.prec, 8 * dst_p->shared->size - (dst.offset + dst.prec), - (bool)(H5T_PAD_ONE == dst.msb_pad)); - } - - /* - * Put the destination in the correct byte order. See note at - * beginning of loop. - */ - if (H5T_ORDER_BE == dst.order && reverse) { - half_size = dst_p->shared->size / 2; - for (i = 0; i < half_size; i++) { - uint8_t tmp = d[dst_p->shared->size - (i + 1)]; - d[dst_p->shared->size - (i + 1)] = d[i]; - d[i] = tmp; - } - } - else if (H5T_ORDER_VAX == dst.order && reverse) { - tsize = dst_p->shared->size; - assert(0 == tsize % 2); - - for (i = 0; i < tsize; i += 4) { - tmp1 = d[i]; - tmp2 = d[i + 1]; - - d[i] = d[(tsize - 2) - i]; - d[i + 1] = d[(tsize - 1) - i]; - - d[(tsize - 2) - i] = tmp1; - d[(tsize - 1) - i] = tmp2; - } + if (dst_atomic.offset + dst_atomic.prec != 8 * type_size) { + assert(H5T_PAD_ZERO == dst_atomic.msb_pad || H5T_PAD_ONE == dst_atomic.msb_pad); + H5T__bit_set(d, dst_atomic.offset + dst_atomic.prec, + 8 * type_size - (dst_atomic.offset + dst_atomic.prec), + (bool)(H5T_PAD_ONE == dst_atomic.msb_pad)); + } + } + + /* + * Put the destination in the correct byte order. See note at + * beginning of loop. Only the "real" part of a complex number + * element is swapped. By the C standard, the "imaginary" part + * should just be zeroed when converting a real value to a + * complex value. + */ + if (H5T_ORDER_BE == dst_atomic.order && reverse) { + size_t half_size = dst_p->shared->size / 2; + + if (H5T_FLOAT == dst_p->shared->type) { + for (size_t j = 0; j < half_size; j++) + H5_SWAP_BYTES(d, j, dst_p->shared->size - (j + 1)); + } + else { + for (size_t j = 0; j < half_size / 2; j++) + H5_SWAP_BYTES(d, j, half_size - (j + 1)); + } + } + else if (H5T_ORDER_VAX == dst_atomic.order && reverse) { + if (H5T_FLOAT == dst_p->shared->type) { + uint8_t tmp1, tmp2; + size_t tsize = dst_p->shared->size / 2; + assert(0 == tsize % 2); + + for (size_t i = 0; i < tsize; i += 4) { + tmp1 = d[i]; + tmp2 = d[i + 1]; + + d[i] = d[(tsize - 2) - i]; + d[i + 1] = d[(tsize - 1) - i]; + + d[(tsize - 2) - i] = tmp1; + d[(tsize - 1) - i] = tmp2; } + } + else + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + } - /* - * If we had used a temporary buffer for the destination then we - * should copy the value to the true destination buffer. - */ next: - if (d == dbuf) - H5MM_memcpy(dp, d, dst_p->shared->size); + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d == dbuf) { + if (H5T_FLOAT == dst_p->shared->type) + H5MM_memcpy(dp, d, dst_p->shared->size); + else + H5MM_memcpy(dp, d, dst_p->shared->size / 2); + } - /* Advance source & destination pointers by delta amounts */ - sp += src_delta; - dp += dst_delta; - } + /* Ensure imaginary part of complex number is zeroed */ + if (H5T_COMPLEX == dst_p->shared->type) + memset(dp + (dst_p->shared->size / 2), 0, dst_p->shared->size / 2); - break; - - default: - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); - } /* end switch */ + /* Advance source & destination pointers by delta amounts */ + sp += src_delta; + dp += dst_delta; + } /* end conversion loop */ done: - if (src_rev) - H5MM_free(src_rev); + H5MM_free(src_rev); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__conv_f_f() */ +} /* end H5T__conv_f_f_loop() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_float_find_special + * + * Purpose: Helper function to inspect the bits of a floating-point + * value during data conversions and determine if that value + * is a special value (+/-Inf, +/-0, NaN). + * + * If `sign_out` is non-NULL, it is set to the value of the + * sign bit of the floating-point value. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +H5T_conv_float_specval_t +H5T__conv_float_find_special(const uint8_t *src_buf, const H5T_atomic_t *src_atomic, uint64_t *sign_out) +{ + uint64_t sign; /* sign bit value */ + H5T_conv_float_specval_t ret_value = H5T_CONV_FLOAT_SPECVAL_REGULAR; + + FUNC_ENTER_PACKAGE_NOERR + + assert(src_buf); + assert(src_atomic); + + /* Find the sign bit value of the source. */ + sign = H5T__bit_get_d(src_buf, src_atomic->u.f.sign, (size_t)1); + + /* Is the mantissa all 0 bits? */ + if (H5T__bit_find(src_buf, src_atomic->u.f.mpos, src_atomic->u.f.msize, H5T_BIT_LSB, true) < 0) { + /* Is the exponent all 0 bits? */ + if (H5T__bit_find(src_buf, src_atomic->u.f.epos, src_atomic->u.f.esize, H5T_BIT_LSB, true) < 0) + /* +0 or -0 */ + ret_value = sign ? H5T_CONV_FLOAT_SPECVAL_NEGZERO : H5T_CONV_FLOAT_SPECVAL_POSZERO; + /* Is the exponent all 1 bits? */ + else if (H5T__bit_find(src_buf, src_atomic->u.f.epos, src_atomic->u.f.esize, H5T_BIT_LSB, false) < 0) + /* +Inf or -Inf */ + ret_value = sign ? H5T_CONV_FLOAT_SPECVAL_NEGINF : H5T_CONV_FLOAT_SPECVAL_POSINF; + } + else { + bool exp_all_ones = + (H5T__bit_find(src_buf, src_atomic->u.f.epos, src_atomic->u.f.esize, H5T_BIT_LSB, false) < 0); + + /* For a source value with no implied mantissa bit, if the exponent bits + * are all 1s and only the 1st bit of the mantissa is set to 1, the value + * is infinity. The Intel-Linux "long double" is this case. + */ + if (H5T_NORM_NONE == src_atomic->u.f.norm && exp_all_ones && + H5T__bit_find(src_buf, src_atomic->u.f.mpos, src_atomic->u.f.msize - 1, H5T_BIT_LSB, true) < 0) + ret_value = sign ? H5T_CONV_FLOAT_SPECVAL_NEGINF : H5T_CONV_FLOAT_SPECVAL_POSINF; + else if (exp_all_ones) + ret_value = H5T_CONV_FLOAT_SPECVAL_NAN; + } + + if (sign_out) + *sign_out = sign; + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T__conv_float_find_special() */ /*------------------------------------------------------------------------- * Function: H5T__conv_f_i @@ -635,49 +718,33 @@ H5T__conv_f_i(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { - /* Traversal-related variables */ - H5T_atomic_t src; /*atomic source info */ - H5T_atomic_t dst; /*atomic destination info */ - int direction; /*forward or backward traversal */ - size_t elmtno; /*element number */ - size_t half_size; /*half the type size */ - size_t tsize; /*type size for swapping bytes */ - size_t olap; /*num overlapping elements */ - uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ - uint8_t *src_rev = NULL; /*order-reversed source buffer */ - uint8_t dbuf[64] = {0}; /*temp destination buffer */ - uint8_t tmp1, tmp2; /*temp variables for swapping bytes*/ - - /* Conversion-related variables */ - hssize_t expo; /*source exponent */ - hssize_t sign; /*source sign bit value */ - uint8_t *int_buf = NULL; /*buffer for temporary value */ - size_t buf_size; /*buffer size for temporary value */ - size_t i; /*miscellaneous counters */ - 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 */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE switch (cdata->command) { - case H5T_CONV_INIT: + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + if (NULL == src_p || NULL == dst_p) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; - if (H5T_ORDER_LE != src.order && H5T_ORDER_BE != src.order && H5T_ORDER_VAX != src.order) + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); - if (dst_p->shared->size > sizeof(dbuf)) + if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); - if (8 * sizeof(expo) - 1 < src.u.f.esize) + if (8 * sizeof(hssize_t) - 1 < src_atomic.u.f.esize) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); cdata->need_bkg = H5T_BKG_NO; + break; + } case H5T_CONV_FREE: break; @@ -688,602 +755,629 @@ H5T__conv_f_i(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const if (NULL == conv_ctx) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; + if (H5T__conv_f_i_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); - /* - * Do we process the values from beginning to end or vice versa? Also, - * how many of the elements have the source and destination areas - * overlapping? - */ - if (src_p->shared->size == dst_p->shared->size || buf_stride) { - sp = dp = (uint8_t *)buf; - direction = 1; - olap = nelmts; - } - else if (src_p->shared->size >= dst_p->shared->size) { - double olap_d = - ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); - olap = (size_t)olap_d; - sp = dp = (uint8_t *)buf; - direction = 1; + break; + + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } /* end switch */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_f_i() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_f_i_loop + * + * Purpose: Implements the body of the conversion loop when converting + * floating-point values (including complex number values) to + * integer values. Encapsulates common code that is shared + * between the H5T__conv_f_i conversion function and other + * functions where the logic is nearly identical, such as + * H5T__conv_complex_i. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_f_i_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, + size_t buf_stride, void *buf) +{ + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + ssize_t src_delta, dst_delta; /* source & destination stride */ + uint8_t *s, *sp, *d, *dp; /* source and dest traversal ptrs */ + uint8_t *int_buf = NULL; /* buffer for temporary value */ + uint8_t *src_rev = NULL; /* order-reversed source buffer */ + uint8_t dbuf[TEMP_INT_CONV_BUFFER_SIZE]; /* temp destination buffer */ + size_t int_buf_size; /* buffer size for temporary value */ + size_t src_base_size; /* size of source base datatype */ + size_t olap; /* num overlapping elements */ + int direction; /* forward or backward traversal */ + herr_t ret_value = SUCCEED; + + assert(src_p); + assert(src_p->shared->type == H5T_FLOAT || src_p->shared->type == H5T_COMPLEX); + assert(dst_p); + assert(dst_p->shared->type == H5T_INTEGER); + assert(conv_ctx); + assert(buf); + + FUNC_ENTER_PACKAGE + + if (src_p->shared->type == H5T_COMPLEX) + src_atomic = src_p->shared->parent->shared->u.atomic; + else + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + + /* + * Do we process the values from beginning to end or vice versa? Also, + * how many of the elements have the source and destination areas + * overlapping? + */ + if (src_p->shared->size == dst_p->shared->size || buf_stride) { + sp = dp = (uint8_t *)buf; + direction = 1; + olap = nelmts; + } + else if (src_p->shared->size >= dst_p->shared->size) { + double olap_d = + ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); + olap = (size_t)olap_d; + sp = dp = (uint8_t *)buf; + direction = 1; + } + else { + double olap_d = + ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); + olap = (size_t)olap_d; + sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; + dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; + direction = -1; + } + + /* Direction & size of buffer traversal */ + H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); + H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t); + H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t); + src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size); + dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size); + + /* Allocate enough space for the buffer holding temporary converted value */ + src_base_size = + (H5T_FLOAT == src_p->shared->type) ? src_p->shared->size : src_p->shared->parent->shared->size; + if (dst_atomic.prec / 8 > src_base_size) + int_buf_size = (dst_atomic.prec + 7) / 8; + else + int_buf_size = src_base_size; + if (NULL == (int_buf = H5MM_calloc(int_buf_size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer"); + + /* Allocate space for order-reversed source buffer */ + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src_p->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer"); + + /* The conversion loop */ + for (size_t elmtno = 0; elmtno < nelmts; elmtno++) { + H5T_conv_float_specval_t specval_type; /* floating-point value type (regular, +/-Inf, +/-0, NaN) */ + H5T_conv_ret_t except_ret = + H5T_CONV_UNHANDLED; /* return of conversion exception callback function */ + uint64_t sign; /* source sign bit value */ + hssize_t expo; /* source exponent */ + hssize_t shift_val; /* shift value when shifting mantissa by exponent */ + ssize_t msb_pos_s; /* first bit(MSB) in an integer */ + ssize_t new_msb_pos; /* MSB position after shifting mantissa by exponent */ + bool truncated = false; /* if fraction value is dropped */ + bool reverse = true; /* if reversed the order of destination */ + + /* + * If the source and destination buffers overlap then use a + * temporary buffer for the destination. + */ + s = sp; + if (direction > 0) + d = elmtno < olap ? dbuf : dp; + else + d = elmtno + olap >= nelmts ? dbuf : dp; + if (d == dbuf) + memset(dbuf, 0, sizeof(dbuf)); + +#ifndef NDEBUG + if (d == dbuf) { + assert((dp >= sp && dp < sp + src_p->shared->size) || + (sp >= dp && sp < dp + dst_p->shared->size)); + } + else { + assert((dp < sp && dp + dst_p->shared->size <= sp) || + (sp < dp && sp + src_p->shared->size <= dp)); + } +#endif + + /* + * Put the data in little endian order so our loops aren't so + * complicated. We'll do all the conversion stuff assuming + * little endian and then we'll fix the order at the end. + */ + if (H5T_ORDER_BE == src_atomic.order) { + size_t half_size = src_p->shared->size / 2; + + if (H5T_FLOAT == src_p->shared->type) { + for (size_t i = 0; i < half_size; i++) + H5_SWAP_BYTES(s, i, src_p->shared->size - (i + 1)); } else { - double olap_d = - ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); - olap = (size_t)olap_d; - sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; - dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; - direction = -1; + uint8_t *cur_part = s; + /* Swap real part of complex number element */ + for (size_t i = 0; i < half_size / 2; i++) + H5_SWAP_BYTES(cur_part, i, half_size - (i + 1)); + /* Swap imaginary part of complex number element */ + cur_part += half_size; + for (size_t i = 0; i < half_size / 2; i++) + H5_SWAP_BYTES(cur_part, i, half_size - (i + 1)); + } + } + else if (H5T_ORDER_VAX == src_atomic.order) { + if (H5T_FLOAT == src_p->shared->type) { + uint8_t tmp1, tmp2; + size_t tsize = src_p->shared->size; + assert(0 == tsize % 2); + + for (size_t i = 0; i < tsize; i += 4) { + tmp1 = s[i]; + tmp2 = s[i + 1]; + + s[i] = s[(tsize - 2) - i]; + s[i + 1] = s[(tsize - 1) - i]; + + s[(tsize - 2) - i] = tmp1; + s[(tsize - 1) - i] = tmp2; + } } - - /* Allocate enough space for the buffer holding temporary - * converted value - */ - 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); + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + } + + /* zero-set all destination bits */ + H5T__bit_set(d, dst_atomic.offset, dst_atomic.prec, false); + + /* Check for special cases: +0, -0, +Inf, -Inf, NaN */ + specval_type = H5T__conv_float_find_special(s, &src_atomic, &sign); + if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO || + specval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO) { + /* +0 or -0; Set all bits to zero */ + goto padding; + } + else if (specval_type != H5T_CONV_FLOAT_SPECVAL_REGULAR) { + /* If user's exception handler is present, use it */ + if (conv_ctx->u.conv.cb_struct.func) { + H5T_conv_except_t except_type; /* type of conversion exception that occurred */ + + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSINF) + except_type = H5T_CONV_EXCEPT_PINF; + else if (specval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) + except_type = H5T_CONV_EXCEPT_NINF; + else + except_type = H5T_CONV_EXCEPT_NAN; - /* The conversion loop */ - for (elmtno = 0; elmtno < nelmts; elmtno++) { - /* Set these variables to default */ - except_ret = H5T_CONV_UNHANDLED; - truncated = false; - reverse = true; + except_ret = (conv_ctx->u.conv.cb_struct.func)(except_type, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, + conv_ctx->u.conv.cb_struct.user_data); + } - /* - * If the source and destination buffers overlap then use a - * temporary buffer for the destination. - */ - if (direction > 0) { - s = sp; - d = elmtno < olap ? dbuf : dp; + if (except_ret == H5T_CONV_UNHANDLED) { + if (specval_type == H5T_CONV_FLOAT_SPECVAL_NAN) + goto padding; /* Just set all bits to zero. */ + else if (specval_type == H5T_CONV_FLOAT_SPECVAL_POSINF) { + if (H5T_SGN_NONE == dst_atomic.u.i.sign) + H5T__bit_set(d, dst_atomic.offset, dst_atomic.prec, true); + else if (H5T_SGN_2 == dst_atomic.u.i.sign) + H5T__bit_set(d, dst_atomic.offset, dst_atomic.prec - 1, true); } - else { - s = sp; - d = elmtno + olap >= nelmts ? dbuf : dp; - } -#ifndef NDEBUG - /* I don't quite trust the overlap calculations yet */ - if (d == dbuf) { - assert((dp >= sp && dp < sp + src_p->shared->size) || - (sp >= dp && sp < dp + dst_p->shared->size)); - } - else { - assert((dp < sp && dp + dst_p->shared->size <= sp) || - (sp < dp && sp + src_p->shared->size <= dp)); + else if (specval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF) { + if (H5T_SGN_2 == dst_atomic.u.i.sign) + H5T__bit_set(d, dst_atomic.prec - 1, (size_t)1, true); } -#endif - /* - * Put the data in little endian order so our loops aren't so - * complicated. We'll do all the conversion stuff assuming - * little endian and then we'll fix the order at the end. - */ - if (H5T_ORDER_BE == src.order) { - half_size = src_p->shared->size / 2; - for (i = 0; i < half_size; i++) { - tmp1 = s[src_p->shared->size - (i + 1)]; - s[src_p->shared->size - (i + 1)] = s[i]; - s[i] = tmp1; + } + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + + goto padding; + } + + /* + * Get the exponent as an unsigned quantity from the section of + * the source bit field where it's located. Not expecting + * exponent to be greater than the maximal value of hssize_t. + */ + expo = (hssize_t)H5T__bit_get_d(s, src_atomic.u.f.epos, src_atomic.u.f.esize); + + /* + * Calculate the true source exponent by adjusting according to + * the source exponent bias. + */ + if (0 == expo || H5T_NORM_NONE == src_atomic.u.f.norm) + expo -= (hssize_t)(src_atomic.u.f.ebias - 1); + else if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) + expo -= (hssize_t)src_atomic.u.f.ebias; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + + /* + * Get the mantissa as bit vector from the section of + * the source bit field where it's located. + * Keep the little-endian order in the buffer. + * A sequence 0x01020304 will be like in the buffer, + * 04 03 02 01 + * | | | | + * V V V V + * buf[0] buf[1] buf[2] buf[3] + */ + H5T__bit_copy(int_buf, (size_t)0, s, src_atomic.u.f.mpos, src_atomic.u.f.msize); + + /* + * Restore the implicit bit for mantissa if it's implied. + * Equivalent to mantissa |= (hsize_t)1 << src_atomic.u.f.msize. + */ + if (H5T_NORM_IMPLIED == src_atomic.u.f.norm) + H5T__bit_inc(int_buf, src_atomic.u.f.msize, 8 * int_buf_size - src_atomic.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_atomic.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. + */ + shift_val = expo - (ssize_t)src_atomic.u.f.msize; + H5T__bit_shift(int_buf, shift_val, (size_t)0, int_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 fractional value is dropped off + * during conversion. Set exception type to be "truncate" + */ + if ((size_t)expo < src_atomic.u.f.msize && conv_ctx->u.conv.cb_struct.func) + truncated = true; + + if (H5T_SGN_NONE == dst_atomic.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 + * destination will be set to the maximum possible value. When the + * source is negative, underflow happens. Set the destination to be + * zero (do nothing). If user's exception handler is set, call it and + * let user handle it. + */ + if (sign) { /* source is negative */ + /* If user's exception handler is present, use it */ + if (conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + + if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); } - else if (H5T_ORDER_VAX == src.order) { - tsize = src_p->shared->size; - assert(0 == tsize % 2); + } + else { /* source is positive */ + if (new_msb_pos >= (ssize_t)dst_atomic.prec) { + /* overflow - if user's exception handler is present, use it */ + if (conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); - for (i = 0; i < tsize; i += 4) { - tmp1 = s[i]; - tmp2 = s[i + 1]; + 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, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } - s[i] = s[(tsize - 2) - i]; - s[i + 1] = s[(tsize - 1) - i]; + if (except_ret == H5T_CONV_UNHANDLED) + H5T__bit_set(d, dst_atomic.offset, dst_atomic.prec, true); + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + else { + /* If user's exception handler is present, use it */ + if (truncated && conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } - s[(tsize - 2) - i] = tmp1; - s[(tsize - 1) - i] = tmp2; + if (except_ret == H5T_CONV_UNHANDLED) { + /* copy source value into it if case is ignored by user handler */ + if (new_msb_pos >= 0) + H5T__bit_copy(d, dst_atomic.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; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); } + } + } + else if (H5T_SGN_2 == dst_atomic.u.i.sign) { /* Destination is signed */ + if (sign) { /* source is negative */ + if ((new_msb_pos >= 0) && ((size_t)new_msb_pos < dst_atomic.prec - 1)) { + /* If user's exception handler is present, use it */ + if (truncated && conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); - /*zero-set all destination bits*/ - H5T__bit_set(d, dst.offset, dst.prec, false); + except_ret = (conv_ctx->u.conv.cb_struct.func)( + H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } - /* - * Find the sign bit value of the source. - */ - sign = (hssize_t)H5T__bit_get_d(s, src.u.f.sign, (size_t)1); + 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, dst_atomic.prec); + H5T__bit_neg(int_buf, (size_t)0, dst_atomic.prec); - /* - * Check for special cases: +0, -0, +Inf, -Inf, NaN - */ - if (H5T__bit_find(s, src.u.f.mpos, src.u.f.msize, H5T_BIT_LSB, true) < 0) { - if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, true) < 0) { - /* +0 or -0 */ - /* Set all bits to zero */ - goto padding; + /* copy source value into destination */ + H5T__bit_copy(d, dst_atomic.offset, int_buf, (size_t)0, dst_atomic.prec - 1); + H5T__bit_set(d, (dst_atomic.offset + dst_atomic.prec - 1), (size_t)1, true); + } + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + else { + /* if underflows and no callback, do nothing except turn on + * the sign bit because 0x80...00 is the biggest negative value. + * If user's exception handler is present, use it + */ + if (conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + 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, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } - else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { - /* +Infinity or -Infinity */ - if (sign) { /* -Infinity */ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - if (H5T_SGN_2 == dst.u.i.sign) - H5T__bit_set(d, dst.prec - 1, (size_t)1, true); - } - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - } - else { /* +Infinity */ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - if (H5T_SGN_NONE == dst.u.i.sign) - H5T__bit_set(d, dst.offset, dst.prec, true); - else if (H5T_SGN_2 == dst.u.i.sign) - H5T__bit_set(d, dst.offset, dst.prec - 1, true); - } - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - } - goto padding; + + if (except_ret == H5T_CONV_UNHANDLED) + H5T__bit_set(d, (dst_atomic.offset + dst_atomic.prec - 1), (size_t)1, true); + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); } - else if (H5T_NORM_NONE == src.u.f.norm && - H5T__bit_find(s, src.u.f.mpos, src.u.f.msize - 1, H5T_BIT_LSB, true) < 0 && - H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { - /*This is a special case for the source of no implied mantissa bit. - *If the exponent bits are all 1s and only the 1st bit of mantissa - *is set to 1. It's infinity. The Intel-Linux "long double" is this case.*/ - /* +Infinity or -Infinity */ - if (sign) { /* -Infinity */ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_NINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - if (H5T_SGN_2 == dst.u.i.sign) - H5T__bit_set(d, dst.prec - 1, (size_t)1, true); - } - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); + } + else { /* source is positive */ + if (new_msb_pos >= (ssize_t)dst_atomic.prec - 1) { + /* overflow - if user's exception handler is present, use it */ + if (conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + + 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, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } - else { /* +Infinity */ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_PINF, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - if (H5T_SGN_NONE == dst.u.i.sign) - H5T__bit_set(d, dst.offset, dst.prec, true); - else if (H5T_SGN_2 == dst.u.i.sign) - H5T__bit_set(d, dst.offset, dst.prec - 1, true); - } - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); + + if (except_ret == H5T_CONV_UNHANDLED) + H5T__bit_set(d, dst_atomic.offset, dst_atomic.prec - 1, true); + else if (except_ret == H5T_CONV_HANDLED) { + /* No need to reverse the order of destination because user handles it */ + reverse = false; + goto next; } - goto padding; + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); } - else if (H5T__bit_find(s, src.u.f.epos, src.u.f.esize, H5T_BIT_LSB, false) < 0) { - /* NaN */ - if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, src_p->shared->u.atomic.order); + else if (new_msb_pos < (ssize_t)dst_atomic.prec - 1) { + /* If user's exception handler is present, use it */ + if (truncated && conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_NAN, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, - src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, + conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); } if (except_ret == H5T_CONV_UNHANDLED) { - /*Just set all bits to zero.*/ - goto padding; + /* copy source value into it if case is ignored by user handler */ + if (new_msb_pos >= 0) + H5T__bit_copy(d, dst_atomic.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*/ + /* No need to reverse the order of destination because user handles it */ reverse = false; goto next; } else if (except_ret == H5T_CONV_ABORT) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); - - goto padding; } + } + } - /* - * Get the exponent as an unsigned quantity from the section of - * the source bit field where it's located. Not expecting - * exponent to be greater than the maximal value of hssize_t. - */ - expo = (hssize_t)H5T__bit_get_d(s, src.u.f.epos, src.u.f.esize); +padding: + /* Set padding areas in destination. */ + if (dst_atomic.offset > 0) { + assert(H5T_PAD_ZERO == dst_atomic.lsb_pad || H5T_PAD_ONE == dst_atomic.lsb_pad); + H5T__bit_set(d, (size_t)0, dst_atomic.offset, (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad)); + } + if (dst_atomic.offset + dst_atomic.prec != 8 * dst_p->shared->size) { + assert(H5T_PAD_ZERO == dst_atomic.msb_pad || H5T_PAD_ONE == dst_atomic.msb_pad); + H5T__bit_set(d, dst_atomic.offset + dst_atomic.prec, + 8 * dst_p->shared->size - (dst_atomic.offset + dst_atomic.prec), + (bool)(H5T_PAD_ONE == dst_atomic.msb_pad)); + } + + /* + * Put the destination in the correct byte order. See note at + * beginning of loop. + */ + if (H5T_ORDER_BE == dst_atomic.order && reverse) + for (size_t i = 0; i < dst_p->shared->size / 2; i++) + H5_SWAP_BYTES(d, i, dst_p->shared->size - (i + 1)); - /* - * Calculate the true source exponent by adjusting according to - * the source exponent bias. - */ - if (0 == expo || H5T_NORM_NONE == src.u.f.norm) { - expo -= (hssize_t)(src.u.f.ebias - 1); - } - else if (H5T_NORM_IMPLIED == src.u.f.norm) { - expo -= (hssize_t)src.u.f.ebias; - } - else { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "normalization method not implemented yet"); - } +next: + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d == dbuf) + H5MM_memcpy(dp, d, dst_p->shared->size); - /* - * Get the mantissa as bit vector from the section of - * the source bit field where it's located. - * Keep the little-endian order in the buffer. - * A sequence 0x01020304 will be like in the buffer, - * 04 03 02 01 - * | | | | - * V V V V - * buf[0] buf[1] buf[2] buf[3] - */ - H5T__bit_copy(int_buf, (size_t)0, s, src.u.f.mpos, src.u.f.msize); + /* Advance source & destination pointers by delta amounts */ + sp += src_delta; + dp += dst_delta; - /* - * Restore the implicit bit for mantissa if it's implied. - * Equivalent to mantissa |= (hsize_t)1<u.conv.cb_struct.func) - truncated = true; - - 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 - * destination will be set to the maximum possible value. When the - * source is negative, underflow happens. Set the destination to be - * zero(do nothing). If user's exception handler is set, call it and - * let user handle it. - */ - if (sign) { /*source is negative*/ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - 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, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - } - } - else { /*source is positive*/ - 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*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - 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, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) - H5T__bit_set(d, dst.offset, dst.prec, true); - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - } - else { - if (truncated && conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - /*copy source value into it if case is ignored by user handler*/ - 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; - goto next; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - } - } - } - else if (H5T_SGN_2 == dst.u.i.sign) { /*Destination is signed*/ - if (sign) { /*source is negative*/ - 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*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - 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, 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); - H5T__bit_set(d, (dst.offset + dst.prec - 1), (size_t)1, true); - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - } - else { - /* if underflows and no callback, do nothing except turn on - * the sign bit because 0x80...00 is the biggest negative value. - */ - if (conv_ctx->u.conv.cb_struct - .func) { /*If user's exception handler is present, use it*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - 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, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) - H5T__bit_set(d, (dst.offset + dst.prec - 1), (size_t)1, true); - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - } - } - else { /*source is positive*/ - 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*/ - /*reverse order first*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - 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, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) - H5T__bit_set(d, dst.offset, dst.prec - 1, true); - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - } - 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*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_TRUNCATE, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, - conv_ctx->u.conv.cb_struct.user_data); - } - - if (except_ret == H5T_CONV_UNHANDLED) { - /*copy source value into it if case is ignored by user handler*/ - 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, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - /*No need to reverse the order of destination because user handles it*/ - reverse = false; - goto next; - } - } - } - } + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ -padding: - /* - * Set padding areas in destination. - */ - if (dst.offset > 0) { - assert(H5T_PAD_ZERO == dst.lsb_pad || H5T_PAD_ONE == dst.lsb_pad); - H5T__bit_set(d, (size_t)0, dst.offset, (bool)(H5T_PAD_ONE == dst.lsb_pad)); - } - if (dst.offset + dst.prec != 8 * dst_p->shared->size) { - assert(H5T_PAD_ZERO == dst.msb_pad || H5T_PAD_ONE == dst.msb_pad); - H5T__bit_set(d, dst.offset + dst.prec, 8 * dst_p->shared->size - (dst.offset + dst.prec), - (bool)(H5T_PAD_ONE == dst.msb_pad)); - } + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (!H5T_IS_ATOMIC(dst_p->shared->parent->shared)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid complex number datatype"); + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for source datatype"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for destination datatype"); + if (dst_p->shared->size > TEMP_FLOAT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large"); + if (8 * sizeof(int64_t) - 1 < src_atomic.u.f.esize || + 8 * sizeof(int64_t) - 1 < dst_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; - /* - * Put the destination in the correct byte order. See note at - * beginning of loop. - */ - if (H5T_ORDER_BE == dst.order && reverse) { - half_size = dst_p->shared->size / 2; - for (i = 0; i < half_size; i++) { - tmp1 = d[dst_p->shared->size - (i + 1)]; - d[dst_p->shared->size - (i + 1)] = d[i]; - d[i] = tmp1; - } - } + break; + } -next: - /* - * If we had used a temporary buffer for the destination then we - * should copy the value to the true destination buffer. - */ - if (d == dbuf) - H5MM_memcpy(dp, d, dst_p->shared->size); - if (buf_stride) { - sp += direction * (ssize_t)buf_stride; - dp += direction * (ssize_t)buf_stride; - } - else { - sp += direction * (ssize_t)src_p->shared->size; - dp += direction * (ssize_t)dst_p->shared->size; - } + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - memset(int_buf, 0, buf_size); + /* Are we converting between a floating-point type and a complex number + * type consisting of the same floating-point type? + */ + /* TODO: cache result */ + equal_cplx_conv = (0 == H5T_cmp(src_p, dst_p->shared->parent, false)); + if (!equal_cplx_conv) { + /* If floating-point types differ, use generic f_f loop */ + if (H5T__conv_f_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); + } + else { + /* If floating-point types are the same, use specialized loop */ + if (H5T__conv_complex_f_matched(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); } break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); - } /* end switch */ + } done: - if (int_buf) - H5MM_xfree(int_buf); - if (src_rev) - H5MM_free(src_rev); - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__conv_f_i() */ +} /* end H5T__conv_f_complex() */ #ifdef H5_HAVE__FLOAT16 /*------------------------------------------------------------------------- @@ -1512,6 +1606,59 @@ H5T__conv__Float16_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, { H5T_CONV_fF(FLOAT16, LDOUBLE, H5__Float16, long double, -, -); } + +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv__Float16_fcomplex + * + * Purpose: Converts `_Float16' to `float _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv__Float16_fcomplex(const H5T_t *st, const 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_fZ(FLOAT16, FLOAT_COMPLEX, H5__Float16, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv__Float16_dcomplex + * + * Purpose: Converts `_Float16' to `double _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv__Float16_dcomplex(const H5T_t *st, const 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_fZ(FLOAT16, DOUBLE_COMPLEX, H5__Float16, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv__Float16_lcomplex + * + * Purpose: Converts `_Float16' to `long double _Complex' + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv__Float16_lcomplex(const H5T_t *st, const 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_fZ(FLOAT16, LDOUBLE_COMPLEX, H5__Float16, long double _Complex, -, -); +} +#endif #endif /*------------------------------------------------------------------------- @@ -1773,6 +1920,62 @@ H5T__conv_float_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, co H5T_CONV_fF(FLOAT, LDOUBLE, float, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_float_fcomplex + * + * Purpose: Convert native `float' to native `float _Complex' using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_float_fcomplex(const H5T_t *st, const 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_fz(FLOAT, FLOAT_COMPLEX, float, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_float_dcomplex + * + * Purpose: Convert native `float' to native `double _Complex' using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_float_dcomplex(const H5T_t *st, const 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_fZ(FLOAT, DOUBLE_COMPLEX, float, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_float_lcomplex + * + * Purpose: Convert native `float' to native `long double _Complex' + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_float_lcomplex(const H5T_t *st, const 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_fZ(FLOAT, LDOUBLE_COMPLEX, float, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_double_schar * @@ -2032,6 +2235,62 @@ H5T__conv_double_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, c H5T_CONV_fF(DOUBLE, LDOUBLE, double, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_double_fcomplex + * + * Purpose: Convert native `double' to native `float _Complex' using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_double_fcomplex(const H5T_t *st, const 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_Fz(DOUBLE, FLOAT_COMPLEX, double, float _Complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_double_dcomplex + * + * Purpose: Convert native `double' to native `double _Complex' using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_double_dcomplex(const H5T_t *st, const 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_fz(DOUBLE, DOUBLE_COMPLEX, double, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_double_lcomplex + * + * Purpose: Convert native `double' to native `long double _Complex' + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_double_lcomplex(const H5T_t *st, const 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_fZ(DOUBLE, LDOUBLE_COMPLEX, double, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_ldouble_schar * @@ -2296,3 +2555,59 @@ H5T__conv_ldouble_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, c { H5T_CONV_Ff(LDOUBLE, DOUBLE, long double, double, -DBL_MAX, DBL_MAX); } + +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_ldouble_fcomplex + * + * Purpose: Convert native `long double' to native `float _Complex' + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ldouble_fcomplex(const H5T_t *st, const 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_Fz(LDOUBLE, FLOAT_COMPLEX, long double, float _Complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ldouble_dcomplex + * + * Purpose: Convert native `long double' to native `double _Complex' + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ldouble_dcomplex(const H5T_t *st, const 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_Fz(LDOUBLE, DOUBLE_COMPLEX, long double, double _Complex, -DBL_MAX, DBL_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ldouble_lcomplex + * + * Purpose: Convert native `long double' to native `long double _Complex' + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ldouble_lcomplex(const H5T_t *st, const 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_fz(LDOUBLE, LDOUBLE_COMPLEX, long double, long double _Complex, -, -); +} +#endif diff --git a/src/H5Tconv_float.h b/src/H5Tconv_float.h index df349d26874..609af1a35b3 100644 --- a/src/H5Tconv_float.h +++ b/src/H5Tconv_float.h @@ -16,10 +16,39 @@ /* Private headers needed by this file */ #include "H5Tpkg.h" +/*************************/ +/* Module private macros */ +/*************************/ + +#define TEMP_FLOAT_CONV_BUFFER_SIZE 64 + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +typedef enum { + H5T_CONV_FLOAT_SPECVAL_REGULAR, + H5T_CONV_FLOAT_SPECVAL_POSZERO, + H5T_CONV_FLOAT_SPECVAL_NEGZERO, + H5T_CONV_FLOAT_SPECVAL_POSINF, + H5T_CONV_FLOAT_SPECVAL_NEGINF, + H5T_CONV_FLOAT_SPECVAL_NAN, +} H5T_conv_float_specval_t; + /***********************/ /* Function Prototypes */ /***********************/ +/* Helper functions shared between conversion modules */ +H5_DLL herr_t H5T__conv_f_f_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, void *buf); +H5_DLL herr_t H5T__conv_f_i_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, void *buf); + +H5_DLL H5T_conv_float_specval_t H5T__conv_float_find_special(const uint8_t *src_buf, + const H5T_atomic_t *src_atomic, + uint64_t *sign_out); + /****************************************/ /* Soft (emulated) conversion functions */ /****************************************/ @@ -33,6 +62,9 @@ H5_DLL herr_t H5T__conv_f_f(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cda H5_DLL herr_t H5T__conv_f_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *_buf, void *bkg); +H5_DLL herr_t H5T__conv_f_complex(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); /*********************************************/ /* Hard (compiler cast) conversion functions */ @@ -79,6 +111,17 @@ H5_DLL herr_t H5T__conv__Float16_double(const H5T_t *st, const H5T_t *dt, H5T_cd H5_DLL herr_t H5T__conv__Float16_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv__Float16_fcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv__Float16_dcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv__Float16_lcomplex(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif #endif /* Conversion functions for 'float' */ @@ -123,6 +166,17 @@ H5_DLL herr_t H5T__conv_float_double(const H5T_t *src, const H5T_t *dst, H5T_cda H5_DLL herr_t H5T__conv_float_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_float_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_float_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_float_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'double' */ H5_DLL herr_t H5T__conv_double_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -166,6 +220,17 @@ H5_DLL herr_t H5T__conv_double_float(const H5T_t *src, const H5T_t *dst, H5T_cda H5_DLL herr_t H5T__conv_double_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_double_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_double_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_double_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'long double' */ H5_DLL herr_t H5T__conv_ldouble_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -211,5 +276,16 @@ H5_DLL herr_t H5T__conv_ldouble_float(const H5T_t *src, const H5T_t *dst, H5T_cd H5_DLL herr_t H5T__conv_ldouble_double(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_ldouble_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ldouble_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ldouble_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif #endif /* H5Tconv_float_H */ diff --git a/src/H5Tconv_integer.c b/src/H5Tconv_integer.c index 9128f777a79..536116bdbf3 100644 --- a/src/H5Tconv_integer.c +++ b/src/H5Tconv_integer.c @@ -118,7 +118,9 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst->shared->size); /* Allocate space for order-reversed source buffer */ - src_rev = (uint8_t *)H5MM_calloc(src->shared->size); + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "unable to allocate temporary buffer"); /* The conversion loop */ for (elmtno = 0; elmtno < nelmts; elmtno++) { @@ -198,8 +200,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); 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, src_rev, d, @@ -234,8 +236,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow - source is negative*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); 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, src_rev, d, @@ -262,8 +264,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow - source is positive*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); 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, src_rev, d, @@ -295,8 +297,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); 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, src_rev, d, @@ -343,8 +345,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); 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, src_rev, d, @@ -386,8 +388,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); 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, src_rev, d, @@ -475,425 +477,529 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ } /* end H5T__conv_i_i() */ /*------------------------------------------------------------------------- - * Function: H5T__conv_i_f + * Function: H5T__conv_i_f_loop * - * Purpose: Convert one integer type to a floating-point type. This is - * the catch-all function for integer-float conversions and - * is probably not particularly fast. + * Purpose: Implements the body of the conversion loop when converting + * integer values to floating-point values (including complex + * number values). Encapsulates common code that is shared + * between the H5T__conv_i_f conversion function and other + * functions where the logic is nearly identical, such as + * H5T__conv_i_complex. * * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ herr_t -H5T__conv_i_f(const H5T_t *src_p, const H5T_t *dst_p, 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_i_f_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, + size_t buf_stride, void *buf) { - /* Traversal-related variables */ - H5T_atomic_t src; /*atomic source info */ - H5T_atomic_t dst; /*atomic destination info */ - int direction; /*forward or backward traversal */ - size_t elmtno; /*element number */ - size_t half_size; /*half the type size */ - size_t tsize; /*type size for swapping bytes */ - size_t olap; /*num overlapping elements */ - uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ - uint8_t *src_rev = NULL; /*order-reversed source buffer */ - uint8_t dbuf[64] = {0}; /*temp destination buffer */ - uint8_t tmp1, tmp2; /*temp variables for swapping bytes*/ - - /* Conversion-related variables */ - hsize_t expo; /*destination exponent */ - hsize_t expo_max; /*maximal possible exponent value */ - size_t sign; /*source sign bit value */ - bool is_max_neg; /*source is maximal negative value*/ - bool do_round; /*whether there is roundup */ - 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' */ - H5T_conv_ret_t except_ret; /*return of callback function */ - bool reverse; /*if reverse the order of destination */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_PACKAGE + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + hsize_t expo_max; /* maximal possible exponent value */ + ssize_t src_delta, dst_delta; /* source & destination stride */ + uint8_t *s, *sp, *d, *dp; /* source and dest traversal ptrs */ + uint8_t *int_buf = NULL; /* buffer for temporary value */ + uint8_t *src_rev = NULL; /* order-reversed source buffer */ + size_t int_buf_size; /* buffer size for temporary value */ + size_t olap; /* num overlapping elements */ + int direction; /* forward or backward traversal */ + herr_t ret_value = SUCCEED; - switch (cdata->command) { - case H5T_CONV_INIT: - if (NULL == src_p || NULL == dst_p) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; - if (H5T_ORDER_LE != dst.order && H5T_ORDER_BE != dst.order && H5T_ORDER_VAX != dst.order) - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); - if (dst_p->shared->size > sizeof(dbuf)) - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); - if (8 * sizeof(expo) - 1 < src.u.f.esize) - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); - cdata->need_bkg = H5T_BKG_NO; - break; - - case H5T_CONV_FREE: - break; + assert(src_p); + assert(src_p->shared->type == H5T_INTEGER); + assert(dst_p); + assert(dst_p->shared->type == H5T_FLOAT || dst_p->shared->type == H5T_COMPLEX); + assert(conv_ctx); + assert(buf); - case H5T_CONV_CONV: - if (NULL == src_p || NULL == dst_p) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - if (NULL == conv_ctx) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); + FUNC_ENTER_PACKAGE - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; + src_atomic = src_p->shared->u.atomic; + if (dst_p->shared->type == H5T_COMPLEX) + dst_atomic = dst_p->shared->parent->shared->u.atomic; + else + dst_atomic = dst_p->shared->u.atomic; + + /* + * Do we process the values from beginning to end or vice versa? Also, + * how many of the elements have the source and destination areas + * overlapping? + */ + if (src_p->shared->size == dst_p->shared->size || buf_stride) { + sp = dp = (uint8_t *)buf; + direction = 1; + olap = nelmts; + } + else if (src_p->shared->size >= dst_p->shared->size) { + double olap_d = + ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); + olap = (size_t)olap_d; + sp = dp = (uint8_t *)buf; + direction = 1; + } + else { + double olap_d = + ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); + olap = (size_t)olap_d; + sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; + dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; + direction = -1; + } + + /* Direction & size of buffer traversal */ + H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); + H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t); + H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t); + src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size); + dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size); + + /* Allocate enough space for the buffer holding temporary converted value */ + int_buf_size = + ((src_atomic.prec > dst_atomic.u.f.msize ? src_atomic.prec : dst_atomic.u.f.msize) + 7) / 8; + if (NULL == (int_buf = H5MM_calloc(int_buf_size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer"); + + /* Allocate space for order-reversed source buffer */ + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src_p->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "couldn't allocate temporary buffer"); + + /* The conversion loop */ + for (size_t elmtno = 0; elmtno < nelmts; elmtno++) { + H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED; /* return of conversion exception callback function */ + hsize_t expo; /* destination exponent */ + uint8_t dbuf[TEMP_INT_CONV_BUFFER_SIZE] = {0}; /* temp destination buffer */ + ssize_t sfirst = 0; /* a signed version of `first' */ + size_t first; /* first bit(MSB) in an integer */ + size_t sign = 0; /* source sign bit value */ + bool reverse = true; /* if reversed the order of destination */ + bool is_max_neg = false; /* source is maximal negative value? */ + bool do_round = false; /* whether there is roundup */ + + /* + * If the source and destination buffers overlap then use a + * temporary buffer for the destination. + */ + if (direction > 0) { + s = sp; + d = elmtno < olap ? dbuf : dp; + } + else { + s = sp; + d = elmtno + olap >= nelmts ? dbuf : dp; + } +#ifndef NDEBUG + if (d == dbuf) { + assert((dp >= sp && dp < sp + src_p->shared->size) || + (sp >= dp && sp < dp + dst_p->shared->size)); + } + else { + assert((dp < sp && dp + dst_p->shared->size <= sp) || + (sp < dp && sp + src_p->shared->size <= dp)); + } +#endif - /* - * Do we process the values from beginning to end or vice versa? Also, - * how many of the elements have the source and destination areas - * overlapping? - */ - if (src_p->shared->size == dst_p->shared->size || buf_stride) { - sp = dp = (uint8_t *)buf; - direction = 1; - olap = nelmts; - } - else if (src_p->shared->size >= dst_p->shared->size) { - double olap_d = - ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); - olap = (size_t)olap_d; - sp = dp = (uint8_t *)buf; - direction = 1; + /* Put the data in little endian order so our loops aren't so + * complicated. We'll do all the conversion stuff assuming + * little endian and then we'll fix the order at the end. + */ + if (H5T_ORDER_BE == src_atomic.order) + for (size_t i = 0; i < src_p->shared->size / 2; i++) + H5_SWAP_BYTES(s, i, src_p->shared->size - (i + 1)); + + /* Zero-set all destination bits */ + H5T__bit_set(d, dst_atomic.offset, dst_atomic.prec, false); + + /* Copy source into a temporary buffer */ + H5T__bit_copy(int_buf, (size_t)0, s, src_atomic.offset, src_atomic.prec); + + /* Find the sign bit value of the source */ + if (H5T_SGN_2 == src_atomic.u.i.sign) + sign = (size_t)H5T__bit_get_d(int_buf, src_atomic.prec - 1, (size_t)1); + + /* What is the bit position(starting from 0 as first one) for the most significant + * bit(MSB) of S which is set? + */ + if (H5T_SGN_2 == src_atomic.u.i.sign) { + sfirst = H5T__bit_find(int_buf, (size_t)0, src_atomic.prec - 1, H5T_BIT_MSB, true); + if (sign && sfirst < 0) + /* The case 0x80...00, which is negative with maximal value */ + is_max_neg = 1; + } + else if (H5T_SGN_NONE == src_atomic.u.i.sign) + sfirst = H5T__bit_find(int_buf, (size_t)0, src_atomic.prec, H5T_BIT_MSB, true); + + /* Handle special cases here. Integer is zero */ + if (!sign && sfirst < 0) + goto padding; + + /* Convert source integer if it's negative */ + if (H5T_SGN_2 == src_atomic.u.i.sign && sign) { + if (!is_max_neg) { + /* Equivalent to ~(i - 1) */ + H5T__bit_dec(int_buf, (size_t)0, int_buf_size * 8); + H5T__bit_neg(int_buf, (size_t)0, int_buf_size * 8); + sfirst = H5T__bit_find(int_buf, (size_t)0, src_atomic.prec - 1, H5T_BIT_MSB, true); } else { - double olap_d = - ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); - olap = (size_t)olap_d; - sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; - dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; - direction = -1; + /* If it's maximal negative number 0x80...000, treat it as if it overflowed + * (create a carry) to help conversion. i.e. a character type number 0x80 + * is treated as 0x100. + */ + sfirst = (ssize_t)(src_atomic.prec - 1); + is_max_neg = 0; } + if (sfirst < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "zero bit not found"); - /* Allocate enough space for the buffer holding temporary - * converted value + /* Sign bit has been negated if bit vector isn't 0x80...00. Set all bits in front of + * sign bit to 0 in the temporary buffer because they're all negated from the previous + * step. */ - 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 */ - src_rev = (uint8_t *)H5MM_calloc(src_p->shared->size); - - /* The conversion loop */ - for (elmtno = 0; elmtno < nelmts; elmtno++) { - /* Set these variables to default */ - except_ret = H5T_CONV_UNHANDLED; - reverse = true; + H5T__bit_set(int_buf, src_atomic.prec, (int_buf_size * 8) - src_atomic.prec, 0); + + /* Set sign bit in destination */ + H5T__bit_set_d(d, dst_atomic.u.f.sign, (size_t)1, (hsize_t)sign); + } + + first = (size_t)sfirst; + + /* Calculate the true destination exponent by adjusting according to + * the destination exponent bias. Implied and non-implied normalization + * should be the same. + */ + if (H5T_NORM_NONE == dst_atomic.u.f.norm || H5T_NORM_IMPLIED == dst_atomic.u.f.norm) + expo = first + dst_atomic.u.f.ebias; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "normalization method not implemented yet"); + + /* Handle mantissa part here */ + if (H5T_NORM_IMPLIED == dst_atomic.u.f.norm) + H5T__bit_set(int_buf, first, (size_t)1, 0); /* Imply first bit */ + else if (H5T_NORM_NONE == dst_atomic.u.f.norm) + first++; + + /* Roundup for mantissa */ + if (first > dst_atomic.u.f.msize) { + /* If the bit sequence is bigger than the mantissa part, there'll be some + * precision loss. Let user's handler deal with the case if it's present + */ + if (conv_ctx->u.conv.cb_struct.func) { + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src_p); + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + } - /* Make sure these variables are reset to 0. */ - sign = 0; /*source sign bit value */ - is_max_neg = 0; /*source is maximal negative value*/ - do_round = 0; /*whether there is roundup */ - sfirst = 0; + if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto padding; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); - /* - * If the source and destination buffers overlap then use a - * temporary buffer for the destination. - */ - if (direction > 0) { - s = sp; - d = elmtno < olap ? dbuf : dp; - } - else { - s = sp; - d = elmtno + olap >= nelmts ? dbuf : dp; - } -#ifndef NDEBUG - /* I don't quite trust the overlap calculations yet */ - if (d == dbuf) { - assert((dp >= sp && dp < sp + src_p->shared->size) || - (sp >= dp && sp < dp + dst_p->shared->size)); - } - else { - assert((dp < sp && dp + dst_p->shared->size <= sp) || - (sp < dp && sp + src_p->shared->size <= dp)); - } -#endif + /* If user's exception handler does deal with it, we do it by dropping off the + * extra bits at the end and do rounding. If we have .50...0(decimal) after radix + * point, we do roundup when the least significant digit before radix is odd, we do + * rounddown if it's even. + */ - /* Put the data in little endian order so our loops aren't so - * complicated. We'll do all the conversion stuff assuming - * little endian and then we'll fix the order at the end. - */ - if (H5T_ORDER_BE == src.order) { - half_size = src_p->shared->size / 2; - for (i = 0; i < half_size; i++) { - tmp1 = s[src_p->shared->size - (i + 1)]; - s[src_p->shared->size - (i + 1)] = s[i]; - s[i] = tmp1; - } + /* Check 1st dropoff bit, see if it's set. */ + if (H5T__bit_get_d(int_buf, ((first - dst_atomic.u.f.msize) - 1), (size_t)1)) { + /* Check all bits after 1st dropoff bit, see if any of them is set. */ + if (((first - dst_atomic.u.f.msize) - 1) > 0 && + H5T__bit_get_d(int_buf, (size_t)0, ((first - dst_atomic.u.f.msize) - 1))) + do_round = 1; + else { /* The .50...0 case */ + /* Check if the least significant bit is odd. */ + if (H5T__bit_get_d(int_buf, (first - dst_atomic.u.f.msize), (size_t)1)) + do_round = 1; } + } - /* Zero-set all destination bits*/ - H5T__bit_set(d, dst.offset, dst.prec, false); - - /* Copy source into a temporary buffer */ - H5T__bit_copy(int_buf, (size_t)0, s, src.offset, src.prec); + /* Right shift to drop off extra bits */ + H5T__bit_shift(int_buf, (ssize_t)(dst_atomic.u.f.msize - first), (size_t)0, int_buf_size * 8); - /* Find the sign bit value of the source */ - if (H5T_SGN_2 == src.u.i.sign) - sign = (size_t)H5T__bit_get_d(int_buf, src.prec - 1, (size_t)1); + if (do_round) { + H5T__bit_inc(int_buf, (size_t)0, int_buf_size * 8); + do_round = 0; - /* What is the bit position(starting from 0 as first one) for the most significant - * bit(MSB) of S which is set? + /* If integer is like 0x0ff...fff and we need to round up the + * last f, we get 0x100...000. Treat this special case here. */ - if (H5T_SGN_2 == src.u.i.sign) { - sfirst = H5T__bit_find(int_buf, (size_t)0, src.prec - 1, H5T_BIT_MSB, true); - if (sign && sfirst < 0) - /* The case 0x80...00, which is negative with maximal value */ - is_max_neg = 1; - } - else if (H5T_SGN_NONE == src.u.i.sign) - sfirst = H5T__bit_find(int_buf, (size_t)0, src.prec, H5T_BIT_MSB, true); - - /* Handle special cases here. Integer is zero */ - if (!sign && sfirst < 0) - goto padding; - - /* Convert source integer if it's negative */ - if (H5T_SGN_2 == src.u.i.sign && sign) { - if (!is_max_neg) { - /* Equivalent to ~(i - 1) */ - H5T__bit_dec(int_buf, (size_t)0, buf_size * 8); - H5T__bit_neg(int_buf, (size_t)0, buf_size * 8); - sfirst = H5T__bit_find(int_buf, (size_t)0, src.prec - 1, H5T_BIT_MSB, true); + if (H5T__bit_get_d(int_buf, dst_atomic.u.f.msize, (size_t)1)) { + if (H5T_NORM_IMPLIED == dst_atomic.u.f.norm) { + /* The bit at this 1's position was impled already, so this + * number should be 0x200...000. We need to increment the + * exponent in this case. + */ + expo++; } - else { - /* If it's maximal negative number 0x80...000, treat it as if it overflowed - * (create a carry) to help conversion. i.e. a character type number 0x80 - * is treated as 0x100. + else if (H5T_NORM_NONE == dst_atomic.u.f.norm) { + /* Right shift 1 bit to let the carried 1 fit in the mantissa, + * and increment exponent by 1. */ - sfirst = (ssize_t)(src.prec - 1); - is_max_neg = 0; + H5T__bit_shift(int_buf, (ssize_t)-1, (size_t)0, int_buf_size * 8); + expo++; } - if (sfirst < 0) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "zero bit not found"); + } + } + } + else { + /* The bit sequence can fit mantissa part. Left shift to fit in from high-order of + * bit position. */ + H5T__bit_shift(int_buf, (ssize_t)(dst_atomic.u.f.msize - first), (size_t)0, dst_atomic.u.f.msize); + } + + /* Check if the exponent is too big */ + expo_max = (hsize_t)(pow(2.0, (double)dst_atomic.u.f.esize) - 1); + + if (expo > expo_max) { /* overflows */ + if (conv_ctx->u.conv.cb_struct.func) { + /* user's exception handler. Reverse back source order */ + H5T__reverse_order(src_rev, s, src_p); + 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, + src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + + if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + else if (except_ret == H5T_CONV_HANDLED) { + reverse = false; + goto padding; + } + } - /* Sign bit has been negated if bit vector isn't 0x80...00. Set all bits in front of - * sign bit to 0 in the temporary buffer because they're all negated from the previous - * step. - */ - H5T__bit_set(int_buf, src.prec, (buf_size * 8) - src.prec, 0); + 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; + memset(int_buf, 0, int_buf_size); + } + } - /* Set sign bit in destination */ - H5T__bit_set_d(d, dst.u.f.sign, (size_t)1, (hsize_t)sign); - } /* end if */ + if (except_ret == H5T_CONV_UNHANDLED) { + /* Set exponent in destination */ + H5T__bit_set_d(d, dst_atomic.u.f.epos, dst_atomic.u.f.esize, expo); - first = (size_t)sfirst; + /* Copy mantissa into destination */ + H5T__bit_copy(d, dst_atomic.u.f.mpos, int_buf, (size_t)0, + (int_buf_size * 8) > dst_atomic.u.f.msize ? dst_atomic.u.f.msize + : int_buf_size * 8); + } - /* Calculate the true destination exponent by adjusting according to - * the destination exponent bias. Implied and non-implied normalization - * should be the same. - */ - if (H5T_NORM_NONE == dst.u.f.norm || H5T_NORM_IMPLIED == dst.u.f.norm) { - expo = first + dst.u.f.ebias; - } - else { - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "normalization method not implemented yet"); +padding: + /* Set padding areas in destination. */ + if (dst_atomic.offset > 0) { + assert(H5T_PAD_ZERO == dst_atomic.lsb_pad || H5T_PAD_ONE == dst_atomic.lsb_pad); + H5T__bit_set(d, (size_t)0, dst_atomic.offset, (bool)(H5T_PAD_ONE == dst_atomic.lsb_pad)); + } + { + size_t type_size; + + if (dst_p->shared->type == H5T_FLOAT) + type_size = dst_p->shared->size; + else + type_size = dst_p->shared->parent->shared->size; + + if (dst_atomic.offset + dst_atomic.prec != 8 * type_size) { + assert(H5T_PAD_ZERO == dst_atomic.msb_pad || H5T_PAD_ONE == dst_atomic.msb_pad); + H5T__bit_set(d, dst_atomic.offset + dst_atomic.prec, + 8 * type_size - (dst_atomic.offset + dst_atomic.prec), + (bool)(H5T_PAD_ONE == dst_atomic.msb_pad)); + } + } + + /* + * Put the destination in the correct byte order. See note at + * beginning of loop. Only the "real" part of a complex number + * element is swapped. By the C standard, the "imaginary" part + * should just be zeroed when converting a real value to a + * complex value. + */ + if (H5T_ORDER_BE == dst_atomic.order && reverse) { + for (size_t i = 0; i < dst_p->shared->size / 2; i++) + H5_SWAP_BYTES(d, i, dst_p->shared->size - (i + 1)); + } + else if (H5T_ORDER_VAX == dst_atomic.order && reverse) { + if (H5T_FLOAT == dst_p->shared->type) { + uint8_t tmp1, tmp2; + size_t tsize = dst_p->shared->size; + assert(0 == tsize % 2); + + for (size_t i = 0; i < tsize; i += 4) { + tmp1 = d[i]; + tmp2 = d[i + 1]; + + d[i] = d[(tsize - 2) - i]; + d[i + 1] = d[(tsize - 1) - i]; + + d[(tsize - 2) - i] = tmp1; + d[(tsize - 1) - i] = tmp2; } + } + else + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + } + + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d == dbuf) /* For complex number values, assume that dbuf was initialized to 0s */ + H5MM_memcpy(dp, d, dst_p->shared->size); + else if (dst_p->shared->type == H5T_COMPLEX) + /* Ensure imaginary part of complex number is zeroed */ + memset(dp + (dst_p->shared->size / 2), 0, dst_p->shared->size / 2); + + /* Advance source & destination pointers by delta amounts */ + sp += src_delta; + dp += dst_delta; + + memset(int_buf, 0, int_buf_size); + } /* end conversion loop */ - /* Handle mantissa part here */ - if (H5T_NORM_IMPLIED == dst.u.f.norm) { - /* Imply first bit */ - H5T__bit_set(int_buf, first, (size_t)1, 0); - } - else if (H5T_NORM_NONE == dst.u.f.norm) { - first++; - } +done: + H5MM_free(src_rev); + H5MM_free(int_buf); - /* Roundup for mantissa */ - if (first > dst.u.f.msize) { - /* If the bit sequence is bigger than the mantissa part, there'll be some - * precision loss. Let user's handler deal with the case if it's present - */ - if (conv_ctx->u.conv.cb_struct.func) { - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); /*reverse order first*/ - 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, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); - } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_i_f_loop() */ - if (except_ret == H5T_CONV_HANDLED) { - reverse = false; - goto padding; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); +/*------------------------------------------------------------------------- + * Function: H5T__conv_i_f + * + * Purpose: Convert one integer type to a floating-point type. This is + * the catch-all function for integer-float conversions and + * is probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_i_f(const H5T_t *src_p, const H5T_t *dst_p, 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) +{ + herr_t ret_value = SUCCEED; /* Return value */ - /* If user's exception handler does deal with it, we do it by dropping off the - * extra bits at the end and do rounding. If we have .50...0(decimal) after radix - * point, we do roundup when the least significant digit before radix is odd, we do - * rounddown if it's even. - */ + FUNC_ENTER_PACKAGE - /* Check 1st dropoff bit, see if it's set. */ - if (H5T__bit_get_d(int_buf, ((first - dst.u.f.msize) - 1), (size_t)1)) { - /* Check all bits after 1st dropoff bit, see if any of them is set. */ - if (((first - dst.u.f.msize) - 1) > 0 && - H5T__bit_get_d(int_buf, (size_t)0, ((first - dst.u.f.msize) - 1))) - do_round = 1; - else { /* The .50...0 case */ - /* Check if the least significant bit is odd. */ - if (H5T__bit_get_d(int_buf, (first - dst.u.f.msize), (size_t)1)) - do_round = 1; - } - } + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ - /* Right shift to drop off extra bits */ - H5T__bit_shift(int_buf, (ssize_t)(dst.u.f.msize - first), (size_t)0, buf_size * 8); + if (NULL == src_p || NULL == dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); + if (8 * sizeof(hsize_t) - 1 < dst_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; - if (do_round) { - H5T__bit_inc(int_buf, (size_t)0, buf_size * 8); - do_round = 0; + break; + } - /* If integer is like 0x0ff...fff and we need to round up the - * last f, we get 0x100...000. Treat this special case here. - */ - if (H5T__bit_get_d(int_buf, dst.u.f.msize, (size_t)1)) { - if (H5T_NORM_IMPLIED == dst.u.f.norm) { - /* The bit at this 1's position was impled already, so this - * number should be 0x200...000. We need to increment the - * exponent in this case. - */ - expo++; - } - else if (H5T_NORM_NONE == dst.u.f.norm) { - /* Right shift 1 bit to let the carried 1 fit in the mantissa, - * and increment exponent by 1. - */ - H5T__bit_shift(int_buf, (ssize_t)-1, (size_t)0, buf_size * 8); - expo++; - } - } - } - } - else { - /* The bit sequence can fit mantissa part. Left shift to fit in from high-order of - * bit position. */ - H5T__bit_shift(int_buf, (ssize_t)(dst.u.f.msize - first), (size_t)0, dst.u.f.msize); - } + case H5T_CONV_FREE: + break; - /* Check if the exponent is too big */ - expo_max = (hsize_t)(pow(2.0, (double)dst.u.f.esize) - 1); + case H5T_CONV_CONV: + if (NULL == src_p || NULL == dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - if (expo > expo_max) { /*overflows*/ - if (conv_ctx->u.conv.cb_struct - .func) { /*user's exception handler. Reverse back source order*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); /*reverse order first*/ - 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, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + if (H5T__conv_i_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); - if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - reverse = false; - goto padding; - } - } + break; - 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; - memset(int_buf, 0, buf_size); - } - } + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } - if (except_ret == H5T_CONV_UNHANDLED) { - /* Set exponent in destination */ - H5T__bit_set_d(d, dst.u.f.epos, dst.u.f.esize, expo); +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_i_f() */ - /* Copy mantissa into destination */ - H5T__bit_copy(d, dst.u.f.mpos, int_buf, (size_t)0, - (buf_size * 8) > dst.u.f.msize ? dst.u.f.msize : buf_size * 8); - } +/*------------------------------------------------------------------------- + * Function: H5T__conv_i_complex + * + * Purpose: Convert integer values to complex number values. This is + * the catch-all function for integer -> complex number + * conversions and is probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_i_complex(const H5T_t *src_p, const H5T_t *dst_p, 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) +{ + herr_t ret_value = SUCCEED; -padding: - /* - * Set padding areas in destination. - */ - if (dst.offset > 0) { - assert(H5T_PAD_ZERO == dst.lsb_pad || H5T_PAD_ONE == dst.lsb_pad); - H5T__bit_set(d, (size_t)0, dst.offset, (bool)(H5T_PAD_ONE == dst.lsb_pad)); - } - if (dst.offset + dst.prec != 8 * dst_p->shared->size) { - assert(H5T_PAD_ZERO == dst.msb_pad || H5T_PAD_ONE == dst.msb_pad); - H5T__bit_set(d, dst.offset + dst.prec, 8 * dst_p->shared->size - (dst.offset + dst.prec), - (bool)(H5T_PAD_ONE == dst.msb_pad)); - } + FUNC_ENTER_PACKAGE - /* - * Put the destination in the correct byte order. See note at - * beginning of loop. - */ - if (H5T_ORDER_BE == dst.order && reverse) { - half_size = dst_p->shared->size / 2; - for (i = 0; i < half_size; i++) { - uint8_t tmp = d[dst_p->shared->size - (i + 1)]; - d[dst_p->shared->size - (i + 1)] = d[i]; - d[i] = tmp; - } - } - else if (H5T_ORDER_VAX == dst.order && reverse) { - tsize = dst_p->shared->size; - assert(0 == tsize % 2); + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ - for (i = 0; i < tsize; i += 4) { - tmp1 = d[i]; - tmp2 = d[i + 1]; + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (!H5T_IS_ATOMIC(dst_p->shared->parent->shared)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid complex number datatype"); + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for source datatype"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for destination datatype"); + if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large"); + if (8 * sizeof(hsize_t) - 1 < dst_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; - d[i] = d[(tsize - 2) - i]; - d[i + 1] = d[(tsize - 1) - i]; + break; + } - d[(tsize - 2) - i] = tmp1; - d[(tsize - 1) - i] = tmp2; - } - } + case H5T_CONV_FREE: + break; - /* - * If we had used a temporary buffer for the destination then we - * should copy the value to the true destination buffer. - */ - if (d == dbuf) - H5MM_memcpy(dp, d, dst_p->shared->size); - if (buf_stride) { - sp += direction * (ssize_t)buf_stride; - dp += direction * (ssize_t)buf_stride; - } - else { - sp += direction * (ssize_t)src_p->shared->size; - dp += direction * (ssize_t)dst_p->shared->size; - } + case H5T_CONV_CONV: + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - memset(int_buf, 0, buf_size); - } + if (H5T__conv_i_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); - } /* end switch */ + } done: - if (int_buf) - H5MM_xfree(int_buf); - if (src_rev) - H5MM_free(src_rev); - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__conv_i_f() */ +} /* end H5T__conv_i_complex() */ /*------------------------------------------------------------------------- * Function: H5T__conv_schar_uchar @@ -1121,6 +1227,62 @@ H5T__conv_schar_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, co H5T_CONV_xF(SCHAR, LDOUBLE, signed char, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_schar_fcomplex + * + * Purpose: Convert native signed char to native float _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_schar_fcomplex(const H5T_t *st, const 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_xZ(SCHAR, FLOAT_COMPLEX, signed char, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_schar_dcomplex + * + * Purpose: Convert native signed char to native double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_schar_dcomplex(const H5T_t *st, const 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_xZ(SCHAR, DOUBLE_COMPLEX, signed char, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_schar_lcomplex + * + * Purpose: Convert native signed char to native long double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_schar_lcomplex(const H5T_t *st, const 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_xZ(SCHAR, LDOUBLE_COMPLEX, signed char, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_uchar_schar * @@ -1347,6 +1509,62 @@ H5T__conv_uchar_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, co H5T_CONV_xF(UCHAR, LDOUBLE, unsigned char, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_uchar_fcomplex + * + * Purpose: Convert native unsigned char to native float _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_uchar_fcomplex(const H5T_t *st, const 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_xZ(UCHAR, FLOAT_COMPLEX, unsigned char, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uchar_dcomplex + * + * Purpose: Convert native unsigned char to native double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_uchar_dcomplex(const H5T_t *st, const 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_xZ(UCHAR, DOUBLE_COMPLEX, unsigned char, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uchar_lcomplex + * + * Purpose: Convert native unsigned char to native long double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_uchar_lcomplex(const H5T_t *st, const 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_xZ(UCHAR, LDOUBLE_COMPLEX, unsigned char, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_short_schar * @@ -1573,6 +1791,62 @@ H5T__conv_short_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, co H5T_CONV_xF(SHORT, LDOUBLE, short, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_short_fcomplex + * + * Purpose: Convert native short to native float _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_short_fcomplex(const H5T_t *st, const 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_xZ(SHORT, FLOAT_COMPLEX, short, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_short_dcomplex + * + * Purpose: Convert native short to native double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_short_dcomplex(const H5T_t *st, const 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_xZ(SHORT, DOUBLE_COMPLEX, short, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_short_lcomplex + * + * Purpose: Convert native short to native long double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_short_lcomplex(const H5T_t *st, const 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_xZ(SHORT, LDOUBLE_COMPLEX, short, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_ushort_schar * @@ -1799,8 +2073,64 @@ H5T__conv_ushort_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, c size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { - H5T_CONV_xF(USHORT, LDOUBLE, unsigned short, long double, -, -); + H5T_CONV_xF(USHORT, LDOUBLE, unsigned short, long double, -, -); +} + +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_ushort_fcomplex + * + * Purpose: Convert native unsigned short to native float _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ushort_fcomplex(const H5T_t *st, const 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_xZ(USHORT, FLOAT_COMPLEX, unsigned short, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ushort_dcomplex + * + * Purpose: Convert native unsigned short to native double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ushort_dcomplex(const H5T_t *st, const 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_xZ(USHORT, DOUBLE_COMPLEX, unsigned short, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ushort_lcomplex + * + * Purpose: Convert native unsigned short to native long double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ushort_lcomplex(const H5T_t *st, const 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_xZ(USHORT, LDOUBLE_COMPLEX, unsigned short, long double _Complex, -, -); } +#endif /*------------------------------------------------------------------------- * Function: H5T__conv_int_schar @@ -2031,6 +2361,62 @@ H5T__conv_int_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, cons H5T_CONV_xF(INT, LDOUBLE, int, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_int_fcomplex + * + * Purpose: Convert native integer to native float _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_int_fcomplex(const H5T_t *st, const 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_xZ(INT, FLOAT_COMPLEX, int, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_int_dcomplex + * + * Purpose: Convert native integer to native double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_int_dcomplex(const H5T_t *st, const 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_xZ(INT, DOUBLE_COMPLEX, int, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_int_lcomplex + * + * Purpose: Convert native integer to native long double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_int_lcomplex(const H5T_t *st, const 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_xZ(INT, LDOUBLE_COMPLEX, int, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_uint_schar * @@ -2260,6 +2646,62 @@ H5T__conv_uint_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, con H5T_CONV_xF(UINT, LDOUBLE, unsigned int, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_uint_fcomplex + * + * Purpose: Convert native unsigned integer to native float _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_uint_fcomplex(const H5T_t *st, const 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_xZ(UINT, FLOAT_COMPLEX, unsigned int, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uint_dcomplex + * + * Purpose: Convert native unsigned integer to native double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_uint_dcomplex(const H5T_t *st, const 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_xZ(UINT, DOUBLE_COMPLEX, unsigned int, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uint_lcomplex + * + * Purpose: Convert native unsigned integer to native long double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_uint_lcomplex(const H5T_t *st, const 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_xZ(UINT, LDOUBLE_COMPLEX, unsigned int, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_long_schar * @@ -2489,6 +2931,62 @@ H5T__conv_long_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, con H5T_CONV_xF(LONG, LDOUBLE, long, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_long_fcomplex + * + * Purpose: Convert native long to native float _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_long_fcomplex(const H5T_t *st, const 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_xZ(LONG, FLOAT_COMPLEX, long, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_long_dcomplex + * + * Purpose: Convert native long to native double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_long_dcomplex(const H5T_t *st, const 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_xZ(LONG, DOUBLE_COMPLEX, long, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_long_lcomplex + * + * Purpose: Convert native long to native long double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_long_lcomplex(const H5T_t *st, const 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_xZ(LONG, LDOUBLE_COMPLEX, long, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_ulong_schar * @@ -2718,6 +3216,62 @@ H5T__conv_ulong_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, co H5T_CONV_xF(ULONG, LDOUBLE, unsigned long, long double, -, -); } +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_ulong_fcomplex + * + * Purpose: Convert native unsigned long to native float _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ulong_fcomplex(const H5T_t *st, const 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_xZ(ULONG, FLOAT_COMPLEX, unsigned long, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ulong_dcomplex + * + * Purpose: Convert native unsigned long to native double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ulong_dcomplex(const H5T_t *st, const 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_xZ(ULONG, DOUBLE_COMPLEX, unsigned long, double _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ulong_lcomplex + * + * Purpose: Convert native unsigned long to native long double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ulong_lcomplex(const H5T_t *st, const 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_xZ(ULONG, LDOUBLE_COMPLEX, unsigned long, long double _Complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_llong_schar * @@ -2949,6 +3503,64 @@ H5T__conv_llong_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, co } #endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */ +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_llong_fcomplex + * + * Purpose: Convert native long long to native float _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_llong_fcomplex(const H5T_t *st, const 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_xZ(LLONG, FLOAT_COMPLEX, long long, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_llong_dcomplex + * + * Purpose: Convert native long long to native double _Complex using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_llong_dcomplex(const H5T_t *st, const 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_xZ(LLONG, DOUBLE_COMPLEX, long long, double _Complex, -, -); +} + +#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE +/*------------------------------------------------------------------------- + * Function: H5T__conv_llong_lcomplex + * + * Purpose: Convert native long long to native long double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_llong_lcomplex(const H5T_t *st, const 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_xZ(LLONG, LDOUBLE_COMPLEX, long long, long double _Complex, -, -); +} +#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */ +#endif /* H5_HAVE_COMPLEX_NUMBERS */ + /*------------------------------------------------------------------------- * Function: H5T__conv_ullong_schar * @@ -3179,3 +3791,61 @@ H5T__conv_ullong_ldouble(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, c H5T_CONV_xF(ULLONG, LDOUBLE, unsigned long long, long double, -, -); } #endif /*H5T_CONV_INTERNAL_ULLONG_LDOUBLE*/ + +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_ullong_fcomplex + * + * Purpose: Convert native unsigned long long to native float _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ullong_fcomplex(const H5T_t *st, const 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_xZ(ULLONG, FLOAT_COMPLEX, unsigned long long, float _Complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ullong_dcomplex + * + * Purpose: Convert native unsigned long long to native double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ullong_dcomplex(const H5T_t *st, const 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_xZ(ULLONG, DOUBLE_COMPLEX, unsigned long long, double _Complex, -, -); +} + +#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE +/*------------------------------------------------------------------------- + * Function: H5T__conv_ullong_lcomplex + * + * Purpose: Convert native unsigned long long to native long double _Complex + * using hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ullong_lcomplex(const H5T_t *st, const 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_xZ(ULLONG, LDOUBLE_COMPLEX, unsigned long long, long double _Complex, -, -); +} +#endif /* H5T_CONV_INTERNAL_ULLONG_LDOUBLE */ +#endif /* H5_HAVE_COMPLEX_NUMBERS */ diff --git a/src/H5Tconv_integer.h b/src/H5Tconv_integer.h index c8eff45a285..8592b6e6549 100644 --- a/src/H5Tconv_integer.h +++ b/src/H5Tconv_integer.h @@ -16,10 +16,20 @@ /* Private headers needed by this file */ #include "H5Tpkg.h" +/*************************/ +/* Module private macros */ +/*************************/ + +#define TEMP_INT_CONV_BUFFER_SIZE 64 + /***********************/ /* Function Prototypes */ /***********************/ +/* Helper functions shared between conversion modules */ +H5_DLL herr_t H5T__conv_i_f_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, void *buf); + /****************************************/ /* Soft (emulated) conversion functions */ /****************************************/ @@ -33,6 +43,9 @@ H5_DLL herr_t H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cda H5_DLL herr_t H5T__conv_i_f(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *_buf, void *bkg); +H5_DLL herr_t H5T__conv_i_complex(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); /*********************************************/ /* Hard (compiler cast) conversion functions */ @@ -80,6 +93,17 @@ H5_DLL herr_t H5T__conv_schar_double(const H5T_t *src, const H5T_t *dst, H5T_cda H5_DLL herr_t H5T__conv_schar_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_schar_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_schar_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_schar_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'unsigned char' */ H5_DLL herr_t H5T__conv_uchar_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -123,6 +147,17 @@ H5_DLL herr_t H5T__conv_uchar_double(const H5T_t *src, const H5T_t *dst, H5T_cda H5_DLL herr_t H5T__conv_uchar_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_uchar_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_uchar_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_uchar_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'signed short' */ H5_DLL herr_t H5T__conv_short_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -166,6 +201,17 @@ H5_DLL herr_t H5T__conv_short_double(const H5T_t *src, const H5T_t *dst, H5T_cda H5_DLL herr_t H5T__conv_short_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_short_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_short_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_short_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'unsigned short' */ H5_DLL herr_t H5T__conv_ushort_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -209,6 +255,17 @@ H5_DLL herr_t H5T__conv_ushort_double(const H5T_t *src, const H5T_t *dst, H5T_cd H5_DLL herr_t H5T__conv_ushort_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_ushort_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ushort_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ushort_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'signed int' */ H5_DLL herr_t H5T__conv_int_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -252,6 +309,17 @@ H5_DLL herr_t H5T__conv_int_double(const H5T_t *src, const H5T_t *dst, H5T_cdata H5_DLL herr_t H5T__conv_int_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_int_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_int_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_int_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'unsigned int' */ H5_DLL herr_t H5T__conv_uint_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -295,6 +363,17 @@ H5_DLL herr_t H5T__conv_uint_double(const H5T_t *src, const H5T_t *dst, H5T_cdat H5_DLL herr_t H5T__conv_uint_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_uint_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_uint_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_uint_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'signed long' */ H5_DLL herr_t H5T__conv_long_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -338,6 +417,17 @@ H5_DLL herr_t H5T__conv_long_double(const H5T_t *src, const H5T_t *dst, H5T_cdat H5_DLL herr_t H5T__conv_long_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_long_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_long_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_long_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'unsigned long' */ H5_DLL herr_t H5T__conv_ulong_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -381,6 +471,17 @@ H5_DLL herr_t H5T__conv_ulong_double(const H5T_t *src, const H5T_t *dst, H5T_cda H5_DLL herr_t H5T__conv_ulong_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_ulong_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ulong_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ulong_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'signed long long' */ H5_DLL herr_t H5T__conv_llong_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -424,6 +525,17 @@ H5_DLL herr_t H5T__conv_llong_double(const H5T_t *src, const H5T_t *dst, H5T_cda H5_DLL herr_t H5T__conv_llong_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_llong_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_llong_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_llong_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif /* Conversion functions for 'unsigned long long' */ H5_DLL herr_t H5T__conv_ullong_schar(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, @@ -467,5 +579,16 @@ H5_DLL herr_t H5T__conv_ullong_double(const H5T_t *src, const H5T_t *dst, H5T_cd H5_DLL herr_t H5T__conv_ullong_ldouble(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride, void *buf, void *bkg); +#ifdef H5_HAVE_COMPLEX_NUMBERS +H5_DLL herr_t H5T__conv_ullong_fcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ullong_dcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +H5_DLL herr_t H5T__conv_ullong_lcomplex(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t bkg_stride, void *buf, void *bkg); +#endif #endif /* H5Tconv_integer_H */ diff --git a/src/H5Tconv_macros.h b/src/H5Tconv_macros.h index c2876670f5e..f1a119102c6 100644 --- a/src/H5Tconv_macros.h +++ b/src/H5Tconv_macros.h @@ -25,6 +25,10 @@ #include "H5Eprivate.h" /* Error Handling */ #include "H5Tprivate.h" /* Datatypes */ +#ifdef H5_HAVE_COMPLEX_NUMBERS +#include +#endif + #ifdef H5T_DEBUG /* Conversion debugging data for the hardware conversion functions */ @@ -99,8 +103,8 @@ typedef struct H5T_conv_hw_t { * destination is at least as wide as the source. This case * cannot generate overflows. * - * Ff: Floating-point values to floating-point values the source is at - * least as large as the destination. Overflows can occur when + * Ff: Floating-point values to floating-point values where the source is + * at least as large as the destination. Overflows can occur when * the destination is narrower than the source. * * xF: Integers to float-point(float or double) values where the destination @@ -118,6 +122,55 @@ typedef struct H5T_conv_hw_t { * wide as the destination. Overflows can occur when the destination is * narrower than the source. * + * zZ: Complex number values to complex number values where the + * destination is at least as wide as the source. This case + * cannot generate overflows. + * + * Zz: Complex number values to complex number values where the + * source is at least as large as the destination. Overflows can + * occur when the destination is narrower than the source. + * + * zF: Complex number values to floating-point values where the + * destination is at least as wide as the real part of the source + * complex number value. This case cannot generate overflows. + * + * Zf: Complex number values to floating-point values where the real + * part of the source complex number value is at least as large + * as the destination. Overflows can occur when the destination + * is narrower then the source. + * + * fZ: Floating-point values to complex number values where the + * destination is at least as wide as the source. This case + * cannot generate overflows. + * + * Fz: Floating-point values to complex number values where the source is + * at least as large as the destination. Overflows can occur when + * the destination is narrower than the source. + * + * zf: Complex number values to floating-point values where the real + * part of the source complex number value is the same size as + * the destination. This case cannot generate overflows. + * + * fz: Floating-point values to complex number values where the source + * is the same size as the real part of the destination. This case + * cannot generate overflows. + * + * xZ: Integers to complex number values where the destination is at + * least as wide as the source. This case cannot generate overflows. + * + * Zx: Complex number values to integers where the real part of the + * source complex number value is at least as wide as the destination. + * Overflow can occur when the source magnitude is too large for + * the destination. + * + * zX: Complex number values to integers where the destination is at + * least as wide as the real part of the source complex number + * value. This case cannot generate overflows. + * + * Xz: Integers to complex number 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: * @@ -804,6 +857,433 @@ typedef struct H5T_conv_hw_t { H5T_CONV(H5T_CONV_Xf, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y) \ } while (0) +#ifdef H5_HAVE_COMPLEX_NUMBERS +/* + * NOTE: while it would be very nice to be able to use type-generic macros for + * the complex number functions used below to reduce macro duplication between + * the float, double and long double _Complex cases, support for the tgmath.h + * header appears to be problematic and not particularly portable pre-C11. This + * should be revisited if the minimum required C standard version is moved to + * C11 or later. + */ +#define H5T_CONV_FLOAT_COMPLEX_REALVAL(S) float sr_val = crealf(*(S)); +#define H5T_CONV_DOUBLE_COMPLEX_REALVAL(S) double sr_val = creal(*(S)); +#define H5T_CONV_LDOUBLE_COMPLEX_REALVAL(S) long double sr_val = creall(*(S)); +#define H5T_CONV_FLOAT_COMPLEX_IMAGVAL(S) float si_val = cimagf(*(S)); +#define H5T_CONV_DOUBLE_COMPLEX_IMAGVAL(S) double si_val = cimag(*(S)); +#define H5T_CONV_LDOUBLE_COMPLEX_IMAGVAL(S) long double si_val = cimagl(*(S)); + +/* Identical logic to H5T_CONV_fF */ +#define H5T_CONV_zZ(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_Zz_CORE_IMP(STYPE, DTYPE, DBTYPE, S, D, ST, DT, SBT, DBT, D_MIN, D_MAX) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + H5T_CONV_##STYPE##_IMAGVAL(S); /* Extract "imaginary" part of complex number */ \ + bool sr_over = (sr_val) > (SBT)(D_MAX); \ + bool sr_under = (sr_val) < (SBT)(D_MIN); \ + bool si_over = (si_val) > (SBT)(D_MAX); \ + bool si_under = (si_val) < (SBT)(D_MIN); \ + if (!sr_over && !sr_under && !si_over && !si_under) \ + *(D) = (DT)(*(S)); \ + else { \ + H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED; \ + \ + /* Since there's just one chance to raise a conversion exception here and either \ + * or both of the real and imaginary parts of a complex number could raise an \ + * exception, arbitrarily raise an exception in the order of: "overflow for either \ + * part" -> "underflow for either part". There are other orderings that may make \ + * more sense, such as "overflow for real part" -> "underflow for real part" -> \ + * "underflow..." -> "underflow...". For now, this will assume that the user's \ + * conversion exception function will inspect and handle both parts of the complex \ + * number. \ + */ \ + if (sr_over || si_over) { \ + 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); \ + } \ + else if (sr_under || si_under) { \ + 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 user conversion exception function handled the exception, do nothing. \ + * Otherwise, if explicitly left unhandled, create a complex number value \ + * to return based on the exception type. \ + */ \ + if (except_ret == H5T_CONV_UNHANDLED) { \ + DBT tmp_val[2]; /* [ real, imaginary ] */ \ + \ + if (sr_over) \ + tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g); \ + else if (sr_under) \ + tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g); \ + else \ + tmp_val[0] = (DBT)(sr_val); \ + if (si_over) \ + tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g); \ + else if (si_under) \ + tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g); \ + else \ + tmp_val[1] = (DBT)(si_val); \ + \ + *(D) = (*(DT *)tmp_val); \ + } \ + else if (except_ret == H5T_CONV_ABORT) \ + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); \ + } \ + } +#define H5T_CONV_Zz_DOUBLE_COMPLEX_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, double, float, D_MIN, D_MAX) +#define H5T_CONV_Zz_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_DOUBLE_COMPLEX_##DTYPE##_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) +#define H5T_CONV_Zz_LDOUBLE_COMPLEX_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, long double, float, D_MIN, D_MAX) +#define H5T_CONV_Zz_LDOUBLE_COMPLEX_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_CORE_IMP(STYPE, DTYPE, DOUBLE, S, D, ST, DT, long double, double, D_MIN, D_MAX) +#define H5T_CONV_Zz_LDOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_LDOUBLE_COMPLEX_##DTYPE##_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) +#define H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, DBTYPE, S, D, ST, DT, SBT, DBT, D_MIN, D_MAX) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + H5T_CONV_##STYPE##_IMAGVAL(S); /* Extract "imaginary" part of complex number */ \ + bool sr_over = (sr_val) > (SBT)(D_MAX); \ + bool sr_under = (sr_val) < (SBT)(D_MIN); \ + bool si_over = (si_val) > (SBT)(D_MAX); \ + bool si_under = (si_val) < (SBT)(D_MIN); \ + if (!sr_over && !sr_under && !si_over && !si_under) \ + *(D) = (DT)(*(S)); \ + else { \ + DBT tmp_val[2]; /* [ real, imaginary ] */ \ + \ + if (sr_over) \ + tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g); \ + else if (sr_under) \ + tmp_val[0] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g); \ + else \ + tmp_val[0] = (DBT)(sr_val); \ + if (si_over) \ + tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _POS_INF_g); \ + else if (si_under) \ + tmp_val[1] = H5_GLUE3(H5T_NATIVE_, DBTYPE, _NEG_INF_g); \ + else \ + tmp_val[1] = (DBT)(si_val); \ + \ + *(D) = (*(DT *)tmp_val); \ + } \ + } +#define H5T_CONV_Zz_DOUBLE_COMPLEX_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, double, float, D_MIN, D_MAX) +#define H5T_CONV_Zz_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_DOUBLE_COMPLEX_##DTYPE##_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) +#define H5T_CONV_Zz_LDOUBLE_COMPLEX_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, FLOAT, S, D, ST, DT, long double, float, D_MIN, D_MAX) +#define H5T_CONV_Zz_LDOUBLE_COMPLEX_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_NOEX_CORE_IMP(STYPE, DTYPE, DOUBLE, S, D, ST, DT, long double, double, D_MIN, D_MAX) +#define H5T_CONV_Zz_LDOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zz_LDOUBLE_COMPLEX_##DTYPE##_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) + +/* + * Similar logic to H5T_CONV_Ff. The "real" and "imaginary" parts of the complex + * number value are retrieved using one of the creal() and cimag() variants + * (according to the source complex number type) and then are used for comparisons + * when checking for overflow and underflow. + * + * To efficiently convert between complex number types, the macros need to be aware + * of the base floating-point type for both the source and destination complex number + * types. Since there are currently only three cases where H5T_CONV_Zz applies + * (DOUBLE_COMPLEX -> FLOAT_COMPLEX, LDOUBLE_COMPLEX -> FLOAT_COMPLEX and + * LDOUBLE_COMPLEX -> DOUBLE_COMPLEX), use some specialized macros above for this + * for now. H5T_CONV_Zz directs the H5T_CONV macro to H5T_CONV_Zz__(NOEX_)CORE + * (depending on whether conversion exceptions are handled), which then redirects to + * H5T_CONV_Zz___(NOEX_)CORE, ending at H5T_CONV_Zz_(NOEX_)CORE_IMP + * after replacing values related to the source and destination datatypes that are + * passed. While a bit difficult to reason through, alternative approaches proved to + * be much more awkward. + */ +#define H5T_CONV_Zz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) >= sizeof(DT)); \ + H5T_CONV(H5T_CONV_Zz_##STYPE, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N) \ + } while (0) + +/* Identical logic to H5T_CONV_fF */ +#define H5T_CONV_zF(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_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); \ + if ((sr_val) > (SBT)(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 ((sr_val) < (SBT)(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 \ + *(D) = (DT)((sr_val)); \ + } +#define H5T_CONV_Zf_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX) +#define H5T_CONV_Zf_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX) +#define H5T_CONV_Zf_LDOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zf_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX) +#define H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + if ((sr_val) > (SBT)(D_MAX)) \ + *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _POS_INF_g); \ + else if ((sr_val) < (SBT)(D_MIN)) \ + *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g); \ + else \ + *(D) = (DT)((sr_val)); \ + } +#define H5T_CONV_Zf_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX) +#define H5T_CONV_Zf_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX) +#define H5T_CONV_Zf_LDOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zf_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX) + +/* Similar logic to H5T_CONV_Ff. The "real" part of the complex number is + * retrieved using one of the creal() variants (according to the source + * complex number type) and then is used for comparisons when checking for + * overflow and underflow. Uses specialized macros above to also pass the + * base floating-point C type of the complex number type for use in casts + * during those comparisons. + */ +#define H5T_CONV_Zf(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) >= sizeof(DT)); \ + H5T_CONV(H5T_CONV_Zf_##STYPE, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N) \ + } while (0) + +/* Identical logic to H5T_CONV_fF */ +#define H5T_CONV_fZ(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_Fz_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + if (*(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 \ + *(D) = (DT)(*(S)); \ + } +#define H5T_CONV_Fz_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 if (*(S) < (ST)(D_MIN)) \ + *(D) = H5_GLUE3(H5T_NATIVE_, DTYPE, _NEG_INF_g); \ + else \ + *(D) = (DT)(*(S)); \ + } + +/* Similar logic to H5T_CONV_Ff. In the case of overflow or underflow, the + * floating-point value is converted to a complex number value where the + * "real" part of the value is set to positive or negative infinity and + * the "imaginary" part of the value is set to 0. + */ +#define H5T_CONV_Fz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) >= sizeof(DT)); \ + H5T_CONV(H5T_CONV_Fz, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N) \ + } while (0) + +/* Convert a complex number value to the matching base floating-point type. Simple + * direct cast where the imaginary part of the complex number value is discarded. + */ +#define H5T_CONV_zf(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) == (2 * sizeof(DT))); \ + H5T_CONV(H5T_CONV_xX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N) \ + } while (0) + +/* Convert a floating-point value to the matching complex number type. Simple direct + * cast where the imaginary part should be a zero (positive or unsigned). + */ +#define H5T_CONV_fz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert((2 * sizeof(ST)) == sizeof(DT)); \ + H5T_CONV(H5T_CONV_xX, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N) \ + } while (0) + +#define H5T_CONV_xZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + 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_xZ_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + *(D) = (DT)(*(S)); \ + } + +/* Identical logic to H5T_CONV_xF */ +#define H5T_CONV_xZ(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + H5T_CONV(H5T_CONV_xZ, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y) \ + } while (0) + +#define H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + if ((sr_val) > (SBT)(D_MAX) || (sprec < dprec && (sr_val) == (SBT)(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) = (DT)(D_MAX); \ + 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 ((sr_val) < (SBT)(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) = (DT)(D_MIN); \ + 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 ((sr_val) != (SBT)((DT)((sr_val)))) { \ + H5T_conv_ret_t except_ret = (conv_ctx->u.conv.cb_struct.func)( \ + H5T_CONV_EXCEPT_TRUNCATE, 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)((sr_val)); \ + 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)((sr_val)); \ + } +#define H5T_CONV_Zx_FLOAT_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX) +#define H5T_CONV_Zx_DOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX) +#define H5T_CONV_Zx_LDOUBLE_COMPLEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zx_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX) +#define H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, SBT, D_MIN, D_MAX) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + if ((sr_val) > (SBT)(D_MAX)) \ + *(D) = (DT)(D_MAX); \ + else if ((sr_val) < (SBT)(D_MIN)) \ + *(D) = (DT)(D_MIN); \ + else \ + *(D) = (DT)((sr_val)); \ + } +#define H5T_CONV_Zx_FLOAT_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, float, D_MIN, D_MAX) +#define H5T_CONV_Zx_DOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, double, D_MIN, D_MAX) +#define H5T_CONV_Zx_LDOUBLE_COMPLEX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_Zx_NOEX_CORE_IMP(STYPE, DTYPE, S, D, ST, DT, long double, D_MIN, D_MAX) + +/* Similar logic to H5T_CONV_Fx. The "real" part of the complex number is + * retrieved using one of the creal() variants (according to the source + * complex number type) and then is used for comparisons when checking for + * overflow and underflow. Uses specialized macros above to also pass the + * base floating-point C type of the complex number type for use in casts + * during those comparisons. + */ +#define H5T_CONV_Zx(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + H5T_CONV(H5T_CONV_Zx_##STYPE, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, Y) \ + } while (0) + +/* Identical logic to H5T_CONV_fX */ +#define H5T_CONV_zX(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) + +/* H5T_CONV_Xz is currently unused (as there is no standard _Complex type for + * smaller floats than "float", though some compilers will allow this). When + * implemented, the logic should be nearly identical to H5T_CONV_Xf, with the + * comparisons being made against the "real" part of the complex number, as + * extracted with the creal() variants (similar to H5T_CONV_Zx, for guidance). + */ +/* #define H5T_CONV_Xz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) */ +#endif + /* 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. @@ -831,17 +1311,21 @@ typedef struct H5T_conv_hw_t { #define H5T_CONV_SET_PREC_Y \ /* Get source & destination precisions into a variable */ \ tclass = st->shared->type; \ - assert(tclass == H5T_INTEGER || tclass == H5T_FLOAT); \ + assert(tclass == H5T_INTEGER || tclass == H5T_FLOAT || tclass == H5T_COMPLEX); \ if (tclass == H5T_INTEGER) \ sprec = st->shared->u.atomic.prec; \ - else \ + else if (tclass == H5T_FLOAT) \ sprec = 1 + st->shared->u.atomic.u.f.msize; \ + else \ + sprec = 1 + st->shared->parent->shared->u.atomic.u.f.msize; \ tclass = dt->shared->type; \ - assert(tclass == H5T_INTEGER || tclass == H5T_FLOAT); \ + assert(tclass == H5T_INTEGER || tclass == H5T_FLOAT || tclass == H5T_COMPLEX); \ if (tclass == H5T_INTEGER) \ dprec = dt->shared->u.atomic.prec; \ + else if (tclass == H5T_FLOAT) \ + dprec = 1 + dt->shared->u.atomic.u.f.msize; \ else \ - dprec = 1 + dt->shared->u.atomic.u.f.msize; + dprec = 1 + dt->shared->parent->shared->u.atomic.u.f.msize; #define H5T_CONV_SET_PREC_N /*don't init precision variables */ diff --git a/src/H5Tconv_vlen.c b/src/H5Tconv_vlen.c index ab6f5fc2d59..6c73563644e 100644 --- a/src/H5Tconv_vlen.c +++ b/src/H5Tconv_vlen.c @@ -56,7 +56,7 @@ H5FL_BLK_DEFINE_STATIC(vlen_seq); * Function: H5T__conv_vlen_nested_free * * Purpose: Recursively locates and frees any nested VLEN components of - * complex data types (including COMPOUND). + * composite data types (including COMPOUND). * * Return: Non-negative on success/Negative on failure. * @@ -100,6 +100,7 @@ H5T__conv_vlen_nested_free(uint8_t *buf, H5T_t *dt) case H5T_OPAQUE: case H5T_REFERENCE: case H5T_ENUM: + case H5T_COMPLEX: /* These types cannot contain vl data */ break; diff --git a/src/H5Tdbg.c b/src/H5Tdbg.c index b1de7708b8f..b0316f9bd0f 100644 --- a/src/H5Tdbg.c +++ b/src/H5Tdbg.c @@ -182,6 +182,31 @@ H5T_debug(const H5T_t *dt, FILE *stream) s1 = "struct"; break; + case H5T_REFERENCE: + switch (dt->shared->u.atomic.u.r.rtype) { + case H5R_OBJECT1: + s1 = "object reference (old)"; + break; + case H5R_OBJECT2: + s1 = "object reference (new)"; + break; + case H5R_DATASET_REGION1: + s1 = "region reference (old)"; + break; + case H5R_DATASET_REGION2: + s1 = "region reference (new)"; + break; + case H5R_ATTR: + s1 = "attribute reference"; + break; + case H5R_BADTYPE: + case H5R_MAXTYPE: + default: + s1 = "invalid reference"; + break; + } + break; + case H5T_ENUM: s1 = "enum"; break; @@ -193,8 +218,14 @@ H5T_debug(const H5T_t *dt, FILE *stream) s1 = "vlen"; break; - case H5T_REFERENCE: case H5T_ARRAY: + s1 = "array"; + break; + + case H5T_COMPLEX: + s1 = "complex number"; + break; + case H5T_NCLASSES: default: s1 = ""; @@ -342,6 +373,7 @@ H5T_debug(const H5T_t *dt, FILE *stream) case H5T_ENUM: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: /* No additional info */ @@ -407,6 +439,23 @@ H5T_debug(const H5T_t *dt, FILE *stream) else if (H5T_OPAQUE == dt->shared->type) { fprintf(stream, ", tag=\"%s\"", dt->shared->u.opaque.tag); } + else if (H5T_COMPLEX == dt->shared->type) { + fprintf(stream, ", %s", dt->shared->u.cplx.homogeneous ? "homogeneous" : "heterogeneous"); + switch (dt->shared->u.cplx.form) { + case H5T_COMPLEX_RECTANGULAR: + fprintf(stream, ", rectangular form"); + break; + case H5T_COMPLEX_POLAR: + fprintf(stream, ", polar form"); + break; + case H5T_COMPLEX_EXPONENTIAL: + fprintf(stream, ", exponential form"); + break; + default: + fprintf(stream, ", invalid form"); + break; + } + } else { /* Unknown */ fprintf(stream, "unknown class %d\n", (int)(dt->shared->type)); diff --git a/src/H5Tfields.c b/src/H5Tfields.c index 86c9e1eb51b..336d016476d 100644 --- a/src/H5Tfields.c +++ b/src/H5Tfields.c @@ -172,6 +172,7 @@ H5T__get_member_name(H5T_t const *dt, unsigned membno) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "operation not supported for type class"); @@ -231,6 +232,7 @@ H5Tget_member_index(hid_t type_id, const char *name) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for this type"); diff --git a/src/H5Tfixed.c b/src/H5Tfixed.c index 178a0271fb4..b4495ddc465 100644 --- a/src/H5Tfixed.c +++ b/src/H5Tfixed.c @@ -23,13 +23,12 @@ #include "H5Tpkg.h" /*data-type functions */ /*------------------------------------------------------------------------- - * Function: H5Tget_sign + * Function: H5Tget_sign * - * Purpose: Retrieves the sign type for an integer type. + * Purpose: Retrieves the sign type for an integer type. * - * Return: Success: The sign type. - * - * Failure: H5T_SGN_ERROR (Negative) + * Return: Success: The sign type. + * Failure: H5T_SGN_ERROR (Negative) * *------------------------------------------------------------------------- */ @@ -52,14 +51,13 @@ H5Tget_sign(hid_t type_id) } /*------------------------------------------------------------------------- - * Function: H5T_get_sign + * Function: H5T_get_sign * - * Purpose: Private function for H5Tget_sign. Retrieves the sign type + * Purpose: Private function for H5Tget_sign. Retrieves the sign type * for an integer type. * - * Return: Success: The sign type. - * - * Failure: H5T_SGN_ERROR (Negative) + * Return: Success: The sign type. + * Failure: H5T_SGN_ERROR (Negative) * *------------------------------------------------------------------------- */ @@ -88,11 +86,11 @@ H5T_get_sign(H5T_t const *dt) } /*------------------------------------------------------------------------- - * Function: H5Tset_sign + * Function: H5Tset_sign * - * Purpose: Sets the sign property for an integer. + * Purpose: Sets the sign property for an integer. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ diff --git a/src/H5Tmodule.h b/src/H5Tmodule.h index 35e748bac3f..33837247fdc 100644 --- a/src/H5Tmodule.h +++ b/src/H5Tmodule.h @@ -1114,7 +1114,7 @@ * * * The datatype class: #H5T_INTEGER, #H5T_FLOAT, #H5T_STRING, #H5T_BITFIELD, #H5T_OPAQUE, #H5T_COMPOUND, - * #H5T_REFERENCE, #H5T_ENUM, #H5T_VLEN, #H5T_ARRAY + * #H5T_REFERENCE, #H5T_ENUM, #H5T_VLEN, #H5T_ARRAY, #H5T_COMPLEX * * * @@ -2404,7 +2404,8 @@ filled according to the value of this property. The padding can be: *
  • #H5T_REFERENCE
  • *
  • #H5T_ENUM
  • *
  • #H5T_VLEN
  • - *
  • #H5T_ARRAY
  • + *
  • #H5T_ARRAY
  • + *
  • #H5T_COMPLEX
  • * *
  • If class is #H5T_COMPOUND, then go to step 2 and repeat all steps under step 3. If * class is not #H5T_COMPOUND, then a member is of an atomic class and can be read @@ -3744,7 +3745,8 @@ filled according to the value of this property. The padding can be: * \ref DDLBNF114 that defines HDF5 datatypes appears below. * The definition of HDF5 datatypes from the HDF5 DDL * \code - * ::= | | | + * ::= | | | | + * * * ::= | |