diff --git a/HDF5Examples/C/H5T/200/h5ex_t_complex.c b/HDF5Examples/C/H5T/200/h5ex_t_complex.c new file mode 100644 index 00000000000..4e59f0a6efc --- /dev/null +++ b/HDF5Examples/C/H5T/200/h5ex_t_complex.c @@ -0,0 +1,137 @@ +/************************************************************ + + This example shows how to read and write complex number + datatypes to a dataset. The program first writes float + complex values to a dataset with a dataspace of DIM0xDIM1, + then closes the file. Next, it reopens the file, reads + back the data, and outputs it to the screen. This example + assumes the C99 complex number types are supported. For an + example that uses MSVC's complex number types, see the + h5ex_t_complex_msvc.c example file. + + ************************************************************/ + +#include "hdf5.h" +#include +#include +#include + +#define FILE "h5ex_t_complex.h5" +#define DATASET "DS1" +#define DIM0 4 +#define DIM1 7 + +int +main(void) +{ + float _Complex wdata[DIM0][DIM1]; /* Write buffer */ + float _Complex **rdata; /* Read buffer */ + hid_t file, space, dset; /* Handles */ + herr_t status; + hsize_t dims[2] = {DIM0, DIM1}; + int ndims; + hsize_t i, j; + + /* + * Initialize data. + */ + for (i = 0; i < DIM0; i++) + for (j = 0; j < DIM1; j++) { + float real = (float)i / (j + 0.5) + j; + float imaginary = (float)i / (j + 0.5) + j + 1; + wdata[i][j] = real + imaginary * I; + } + + /* + * Create a new file using the default properties. + */ + file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* + * Create dataspace. Setting maximum size to NULL sets the maximum + * size to be the current size. + */ + space = H5Screate_simple(2, dims, NULL); + + /* + * Create the dataset and write the complex number data to it. In + * this example we will save the data as complex numbers of 2 64-bit + * little endian IEEE floating point numbers, regardless of the native + * type. The HDF5 library automatically converts between different + * complex number types. + */ + dset = H5Dcreate(file, DATASET, H5T_COMPLEX_IEEE_F64LE, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + status = H5Dwrite(dset, H5T_NATIVE_FLOAT_COMPLEX, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata[0]); + + /* + * Close and release resources. + */ + status = H5Dclose(dset); + status = H5Sclose(space); + status = H5Fclose(file); + + /* + * Now we begin the read section of this example. Here we assume + * the dataset has the same name and rank, but can have any size. + * Therefore we must allocate a new array to read in data using + * malloc(). + */ + + /* + * Open file and dataset. + */ + file = H5Fopen(FILE, H5F_ACC_RDONLY, H5P_DEFAULT); + dset = H5Dopen(file, DATASET, H5P_DEFAULT); + + /* + * Get dataspace and allocate memory for read buffer. This is a + * two dimensional dataset so the dynamic allocation must be done + * in steps. + */ + space = H5Dget_space(dset); + ndims = H5Sget_simple_extent_dims(space, dims, NULL); + + /* + * Allocate array of pointers to rows. + */ + rdata = malloc(dims[0] * sizeof(float _Complex *)); + + /* + * Allocate space for complex number data. + */ + rdata[0] = malloc(dims[0] * dims[1] * sizeof(float _Complex)); + + /* + * Set the rest of the pointers to rows to the correct addresses. + */ + for (i = 1; i < dims[0]; i++) + rdata[i] = rdata[0] + i * dims[1]; + + /* + * Read the data. + */ + status = H5Dread(dset, H5T_NATIVE_FLOAT_COMPLEX, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata[0]); + + /* + * Output the data to the screen. + */ + printf("%s:\n", DATASET); + for (i = 0; i < dims[0]; i++) { + printf(" ["); + for (j = 0; j < dims[1]; j++) { + printf(" %6.4f%+6.4fi", crealf(rdata[i][j]), cimagf(rdata[i][j])); + } + printf("]\n"); + } + + /* + * Close and release resources. + */ + free(rdata[0]); + free(rdata); + status = H5Dclose(dset); + status = H5Sclose(space); + status = H5Fclose(file); + + return 0; +} diff --git a/HDF5Examples/C/H5T/200/h5ex_t_complex_custom.c b/HDF5Examples/C/H5T/200/h5ex_t_complex_custom.c new file mode 100644 index 00000000000..6c36a2578d8 --- /dev/null +++ b/HDF5Examples/C/H5T/200/h5ex_t_complex_custom.c @@ -0,0 +1,145 @@ +/************************************************************ + + This example shows how to read and write complex number + datatypes to a dataset. The program first writes float + complex values to a dataset with a dataspace of DIM0xDIM1, + then closes the file. Next, it reopens the file, reads + back the data, and outputs it to the screen. This example + assumes the C99 complex number types are supported. For an + example that uses MSVC's complex number types, see the + h5ex_t_complex_msvc.c example file. + + ************************************************************/ + +#include "hdf5.h" +#include +#include +#include + +#define FILE "h5ex_t_complex_custom.h5" +#define DATASET "DS1" +#define DIM0 4 +#define DIM1 7 + +int +main(void) +{ + float _Complex wdata[DIM0][DIM1]; /* Write buffer */ + float _Complex **rdata; /* Read buffer */ + hid_t file, space, dset, dtype; /* Handles */ + herr_t status; + hsize_t dims[2] = {DIM0, DIM1}; + int ndims; + hsize_t i, j; + + /* + * Initialize data. + */ + for (i = 0; i < DIM0; i++) + for (j = 0; j < DIM1; j++) { + float real = (float)i / (j + 0.5) + j; + float imaginary = (float)i / (j + 0.5) + j + 1; + wdata[i][j] = real + imaginary * I; + } + + /* + * Create a new file using the default properties. + */ + file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* + * Create dataspace. Setting maximum size to NULL sets the maximum + * size to be the current size. + */ + space = H5Screate_simple(2, dims, NULL); + + /* + * Create the dataset and write the complex number data to it. In + * this example we will save the data as complex numbers of 2 64-bit + * little endian IEEE floating point numbers, regardless of the native + * type. The HDF5 library automatically converts between different + * complex number types. + */ + dset = H5Dcreate(file, DATASET, H5T_COMPLEX_IEEE_F64LE, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + + /* + * Create a datatype for writing to the dataset. This datatype is a + * complex number equivalent to the H5T_NATIVE_FLOAT_COMPLEX type. + */ + dtype = H5Tcomplex_create(H5T_NATIVE_FLOAT); + + status = H5Dwrite(dset, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata[0]); + + /* + * Close and release resources. + */ + status = H5Dclose(dset); + status = H5Sclose(space); + status = H5Fclose(file); + + /* + * Now we begin the read section of this example. Here we assume + * the dataset has the same name and rank, but can have any size. + * Therefore we must allocate a new array to read in data using + * malloc(). + */ + + /* + * Open file and dataset. + */ + file = H5Fopen(FILE, H5F_ACC_RDONLY, H5P_DEFAULT); + dset = H5Dopen(file, DATASET, H5P_DEFAULT); + + /* + * Get dataspace and allocate memory for read buffer. This is a + * two dimensional dataset so the dynamic allocation must be done + * in steps. + */ + space = H5Dget_space(dset); + ndims = H5Sget_simple_extent_dims(space, dims, NULL); + + /* + * Allocate array of pointers to rows. + */ + rdata = malloc(dims[0] * sizeof(float _Complex *)); + + /* + * Allocate space for complex number data. + */ + rdata[0] = malloc(dims[0] * dims[1] * sizeof(float _Complex)); + + /* + * Set the rest of the pointers to rows to the correct addresses. + */ + for (i = 1; i < dims[0]; i++) + rdata[i] = rdata[0] + i * dims[1]; + + /* + * Read the data. + */ + status = H5Dread(dset, dtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata[0]); + + /* + * Output the data to the screen. + */ + printf("%s:\n", DATASET); + for (i = 0; i < dims[0]; i++) { + printf(" ["); + for (j = 0; j < dims[1]; j++) { + printf(" %6.4f%+6.4fi", crealf(rdata[i][j]), cimagf(rdata[i][j])); + } + printf("]\n"); + } + + /* + * Close and release resources. + */ + free(rdata[0]); + free(rdata); + status = H5Dclose(dset); + status = H5Sclose(space); + status = H5Tclose(dtype); + status = H5Fclose(file); + + return 0; +} diff --git a/HDF5Examples/C/H5T/200/h5ex_t_complex_msvc.c b/HDF5Examples/C/H5T/200/h5ex_t_complex_msvc.c new file mode 100644 index 00000000000..2059380a76b --- /dev/null +++ b/HDF5Examples/C/H5T/200/h5ex_t_complex_msvc.c @@ -0,0 +1,138 @@ +/************************************************************ + + This example shows how to read and write complex number + datatypes to a dataset. The program first writes float + complex values to a dataset with a dataspace of DIM0xDIM1, + then closes the file. Next, it reopens the file, reads + back the data, and outputs it to the screen. This example + assumes MSVC's complex number types are supported rather + than the C99 complex number types. For an example that uses + the C99 complex number types, see the h5ex_t_complex.c + example file. + + ************************************************************/ + +#include "hdf5.h" +#include +#include +#include + +#define FILE "h5ex_t_complex_msvc.h5" +#define DATASET "DS1" +#define DIM0 4 +#define DIM1 7 + +int +main(void) +{ + _Fcomplex wdata[DIM0][DIM1]; /* Write buffer */ + _Fcomplex **rdata; /* Read buffer */ + hid_t file, space, dset; /* Handles */ + herr_t status; + hsize_t dims[2] = {DIM0, DIM1}; + int ndims; + hsize_t i, j; + + /* + * Initialize data. + */ + for (i = 0; i < DIM0; i++) + for (j = 0; j < DIM1; j++) { + float real = (float)i / (j + 0.5) + j; + float imaginary = (float)i / (j + 0.5) + j + 1; + wdata[i][j] = _FCbuild(real, imaginary); + } + + /* + * Create a new file using the default properties. + */ + file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); + + /* + * Create dataspace. Setting maximum size to NULL sets the maximum + * size to be the current size. + */ + space = H5Screate_simple(2, dims, NULL); + + /* + * Create the dataset and write the complex number data to it. In + * this example we will save the data as complex numbers of 2 64-bit + * little endian IEEE floating point numbers, regardless of the native + * type. The HDF5 library automatically converts between different + * complex number types. + */ + dset = H5Dcreate(file, DATASET, H5T_COMPLEX_IEEE_F64LE, space, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + status = H5Dwrite(dset, H5T_NATIVE_FLOAT_COMPLEX, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata[0]); + + /* + * Close and release resources. + */ + status = H5Dclose(dset); + status = H5Sclose(space); + status = H5Fclose(file); + + /* + * Now we begin the read section of this example. Here we assume + * the dataset has the same name and rank, but can have any size. + * Therefore we must allocate a new array to read in data using + * malloc(). + */ + + /* + * Open file and dataset. + */ + file = H5Fopen(FILE, H5F_ACC_RDONLY, H5P_DEFAULT); + dset = H5Dopen(file, DATASET, H5P_DEFAULT); + + /* + * Get dataspace and allocate memory for read buffer. This is a + * two dimensional dataset so the dynamic allocation must be done + * in steps. + */ + space = H5Dget_space(dset); + ndims = H5Sget_simple_extent_dims(space, dims, NULL); + + /* + * Allocate array of pointers to rows. + */ + rdata = malloc(dims[0] * sizeof(_Fcomplex *)); + + /* + * Allocate space for complex number data. + */ + rdata[0] = malloc(dims[0] * dims[1] * sizeof(_Fcomplex)); + + /* + * Set the rest of the pointers to rows to the correct addresses. + */ + for (i = 1; i < dims[0]; i++) + rdata[i] = rdata[0] + i * dims[1]; + + /* + * Read the data. + */ + status = H5Dread(dset, H5T_NATIVE_FLOAT_COMPLEX, H5S_ALL, H5S_ALL, H5P_DEFAULT, rdata[0]); + + /* + * Output the data to the screen. + */ + printf("%s:\n", DATASET); + for (i = 0; i < dims[0]; i++) { + printf(" ["); + for (j = 0; j < dims[1]; j++) { + printf(" %6.4f%+6.4fi", crealf(rdata[i][j]), cimagf(rdata[i][j])); + } + printf("]\n"); + } + + /* + * Close and release resources. + */ + free(rdata[0]); + free(rdata); + status = H5Dclose(dset); + status = H5Sclose(space); + status = H5Fclose(file); + + return 0; +} diff --git a/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java b/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java index efeba28be37..6d9966725bc 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 750e8bb6a7e..dec33972599 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(const void *params) 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 ed53feae60b..c992756829e 100644 --- a/config/cmake/ConfigureChecks.cmake +++ b/config/cmake/ConfigureChecks.cmake @@ -21,6 +21,7 @@ include (CheckTypeSize) include (CheckVariableExists) include (TestBigEndian) include (CheckStructHasMember) +include (CMakePushCheckState) set (HDF_PREFIX "H5") @@ -828,6 +829,71 @@ macro (H5ConversionTests TEST def msg) endif () endmacro () +#----------------------------------------------------------------------------- +# Check for complex number support +#----------------------------------------------------------------------------- +message (STATUS "Checking if complex number support is available") +CHECK_INCLUDE_FILE (complex.h ${HDF_PREFIX}_HAVE_COMPLEX_H) +if (${HDF_PREFIX}_HAVE_COMPLEX_H) + set (H5_HAVE_C99_COMPLEX_NUMBERS 1) + + 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 (MSVC AND NOT ${HDF_PREFIX}_SIZEOF_FLOAT_COMPLEX AND NOT ${HDF_PREFIX}_SIZEOF_DOUBLE_COMPLEX + AND NOT ${HDF_PREFIX}_SIZEOF_LONG_DOUBLE_COMPLEX) + # If using MSVC, the _Complex types (if available) are _Fcomplex, _Dcomplex and _Lcomplex. + # The standard types are checked for first in case MSVC uses them in the future or in case + # the compiler used is simulating MSVC and uses the standard types. + cmake_push_check_state() + list (APPEND CMAKE_EXTRA_INCLUDE_FILES complex.h) + HDF_CHECK_TYPE_SIZE ("_Fcomplex" ${HDF_PREFIX}_SIZEOF__FCOMPLEX) + HDF_CHECK_TYPE_SIZE ("_Dcomplex" ${HDF_PREFIX}_SIZEOF__DCOMPLEX) + HDF_CHECK_TYPE_SIZE ("_Lcomplex" ${HDF_PREFIX}_SIZEOF__LCOMPLEX) + cmake_pop_check_state() + if (${HDF_PREFIX}_SIZEOF__FCOMPLEX AND ${HDF_PREFIX}_SIZEOF__DCOMPLEX AND + ${HDF_PREFIX}_SIZEOF__FCOMPLEX) + set (${HDF_PREFIX}_SIZEOF_FLOAT_COMPLEX ${${HDF_PREFIX}_SIZEOF__FCOMPLEX} + CACHE INTERNAL "SizeOf for float _Complex" FORCE) + set (${HDF_PREFIX}_SIZEOF_DOUBLE_COMPLEX ${${HDF_PREFIX}_SIZEOF__DCOMPLEX} + CACHE INTERNAL "SizeOf for double _Complex" FORCE) + set (${HDF_PREFIX}_SIZEOF_LONG_DOUBLE_COMPLEX ${${HDF_PREFIX}_SIZEOF__LCOMPLEX} + CACHE INTERNAL "SizeOf for long double _Complex" FORCE) + + unset (H5_HAVE_C99_COMPLEX_NUMBERS) + endif () + endif () + + 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) + # Compile simple test program with complex numbers + HDF_FUNCTION_TEST (HAVE_COMPLEX_NUMBERS) + + if (H5_HAVE_COMPLEX_NUMBERS) + if (H5_HAVE_C99_COMPLEX_NUMBERS) + message (STATUS "Using C99 complex number types") + else () + message (STATUS "Using MSVC complex number types") + endif () + else () + message (STATUS "Complex number support has been disabled since a simple test program couldn't be compiled and linked") + endif () + 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 () +else () + message (STATUS "Complex number support has been disabled since the complex.h header was not found") +endif () + #----------------------------------------------------------------------------- # Check various conversion capabilities #----------------------------------------------------------------------------- diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index 36ab096f546..9d495ceac1e 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -104,9 +104,15 @@ /* Define if the __attribute__(()) extension is present */ #cmakedefine H5_HAVE_ATTRIBUTE @H5_HAVE_ATTRIBUTE@ +/* Define if C99 complex number types are present */ +#cmakedefine H5_HAVE_C99_COMPLEX_NUMBERS @H5_HAVE_C99_COMPLEX_NUMBERS@ + /* Define to 1 if you have the `clock_gettime' function. */ #cmakedefine H5_HAVE_CLOCK_GETTIME @H5_HAVE_CLOCK_GETTIME@ +/* 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 +451,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 +513,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 +535,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 f55555c6138..4026a5ae006 100644 --- a/config/cmake/HDFTests.c +++ b/config/cmake/HDFTests.c @@ -128,3 +128,65 @@ 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 + +#if defined(_MSC_VER) && !defined(__llvm__) && !defined(__INTEL_LLVM_COMPILER) + +typedef _Fcomplex H5_float_complex; +typedef _Dcomplex H5_double_complex; +typedef _Lcomplex H5_ldouble_complex; +#define H5_make_fcomplex _FCbuild +#define H5_make_dcomplex _Cbuild +#define H5_make_lcomplex _LCbuild + +#else + +typedef float _Complex H5_float_complex; +typedef double _Complex H5_double_complex; +typedef long double _Complex H5_ldouble_complex; +static float _Complex +H5_make_fcomplex(float real, float imaginary) +{ + return real + imaginary * (float _Complex)_Complex_I; +} +static double _Complex +H5_make_dcomplex(double real, double imaginary) +{ + return real + imaginary * (double _Complex)_Complex_I; +} +static long double _Complex +H5_make_lcomplex(long double real, long double imaginary) +{ + return real + imaginary * (long double _Complex)_Complex_I; +} +#endif + +int +main(void) +{ + H5_float_complex z1 = H5_make_fcomplex(1.0f, 1.0f); + H5_double_complex z2 = H5_make_dcomplex(2.0, 4.0); + H5_ldouble_complex z3 = H5_make_lcomplex(3.0L, 5.0L); + float r1 = crealf(z1); + float i1 = cimagf(z1); + double r2 = creal(z2); + double i2 = cimag(z2); + long double r3 = creall(z3); + long double i3 = cimagl(z3); + return 0; +} +#endif diff --git a/configure.ac b/configure.ac index 0ddb77000c3..845424cc2a1 100644 --- a/configure.ac +++ b/configure.ac @@ -574,6 +574,58 @@ AC_CHECK_SIZEOF([float]) AC_CHECK_SIZEOF([double]) AC_CHECK_SIZEOF([long double]) +## ---------------------------------------------------------------------- +## Check if complex number support is available +## +HAVE_COMPLEX_NUMBERS="no" +AC_CHECK_SIZEOF([float complex], [], [#include ]) +AC_CHECK_SIZEOF([double complex], [], [#include ]) +AC_CHECK_SIZEOF([long double complex], [], [#include ]) + +if test "$ac_cv_sizeof_float_complex" != 0 && + test "$ac_cv_sizeof_double_complex" != 0 && + test "$ac_cv_sizeof_long_double_complex" != 0; then + # Check if __STDC_NO_COMPLEX__ macro is defined, in which case complex number + # support is not available + AC_MSG_CHECKING([if __STDC_NO_COMPLEX__ is defined]) + TEST_SRC="`(echo \"#define HAVE_STDC_NO_COMPLEX 1\"; cat $srcdir/config/cmake/HDFTests.c)`" + AC_CACHE_VAL([hdf5_cv_have_stdc_no_complex], + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([$TEST_SRC])], + [hdf5_cv_have_stdc_no_complex=yes], + [hdf5_cv_have_stdc_no_complex=no], + [hdf5_cv_have_stdc_no_complex=maybe])]) + AC_MSG_RESULT(${hdf5_cv_have_stdc_no_complex}) + + if test "X$hdf5_cv_have_stdc_no_complex" == "Xno"; then + # Compile simple test program with complex numbers + AC_MSG_CHECKING([if complex number test program can be compiled and linked]) + TEST_SRC="`(echo \"#define HAVE_COMPLEX_NUMBERS 1\"; cat $srcdir/config/cmake/HDFTests.c)`" + AC_CACHE_VAL([hdf5_cv_have_complex_numbers], + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([$TEST_SRC])], + [hdf5_cv_have_complex_numbers=yes], + [hdf5_cv_have_complex_numbers=no], + [hdf5_cv_have_complex_numbers=maybe])]) + AC_MSG_RESULT(${hdf5_cv_have_complex_numbers}) + + if test "X$hdf5_cv_have_complex_numbers" == "Xyes"; then + HAVE_COMPLEX_NUMBERS="yes" + + # Define HAVE_COMPLEX_NUMBERS macro for H5pubconf.h. + AC_DEFINE([HAVE_COMPLEX_NUMBERS], [1], [Determine if complex number support is available]) + AC_DEFINE([HAVE_C99_COMPLEX_NUMBERS], [1], [Determine if C99 complex number types are present]) + fi + fi +fi + +# Define HAVE_COMPLEX_NUMBERS value to substitute into other files for conditional testing +AC_SUBST([HAVE_COMPLEX_NUMBERS]) +AC_SUBST([HAVE_C99_COMPLEX_NUMBERS]) + +AC_MSG_CHECKING([if complex number support is available]) +AC_MSG_RESULT([$HAVE_COMPLEX_NUMBERS]) + #----------------------------------------------------------------------------- # Option for enabling/disabling support for non-standard features, datatypes, # etc. These features should still be checked for at configure time, but these diff --git a/doxygen/aliases b/doxygen/aliases index 3c79b179df0..ba073c6f3a8 100644 --- a/doxygen/aliases +++ b/doxygen/aliases @@ -377,7 +377,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/DDLBNF200.dox b/doxygen/dox/DDLBNF200.dox new file mode 100644 index 00000000000..8ce4c89df9f --- /dev/null +++ b/doxygen/dox/DDLBNF200.dox @@ -0,0 +1,667 @@ +/** \page DDLBNF200 DDL in BNF for HDF5 2.0.0 and above + +\todo Revise this & break it up! + +\section intro200 Introduction + +This document contains the data description language (DDL) for an HDF5 file. The +description is in Backus-Naur Form (BNF). + +\section expo200 Explanation of Symbols + +This section contains a brief explanation of the symbols used in the DDL. + +\code{.unparsed} +::= defined as + a token with the name tname +
| one of or + opt zero or one occurrence of + * zero or more occurrence of + + one or more occurrence of + [0-9] an element in the range between 0 and 9 + '[' the token within the quotes (used for special characters) + TBD To Be Decided +\endcode + +\section ddl200 The DDL + +\code{.unparsed} + ::= HDF5 { opt } + + ::= + + ::= SUPER_BLOCK { + SUPERBLOCK_VERSION + FREELIST_VERSION + SYMBOLTABLE_VERSION + OBJECTHEADER_VERSION + OFFSET_SIZE + LENGTH_SIZE + BTREE_RANK + BTREE_LEAF + ISTORE_K + + USER_BLOCK { + USERBLOCK_SIZE + } + } + + ::= FILE_SPACE_STRATEGY + FREE_SPACE_PERSIST + FREE_SPACE_SECTION_THRESHOLD + FILE_SPACE_PAGE_SIZE + + ::= H5F_FSPACE_STRATEGY_FSM_AGGR | H5F_FSPACE_STRATEGY_PAGE | + H5F_FSPACE_STRATEGY_AGGR | H5F_FSPACE_STRATEGY_NONE | + Unknown strategy + + ::= GROUP "/" { + * + opt + opt + * + * + } + + ::= | | | | + + + ::= DATATYPE { + + } + + ::= the assigned name for anonymous named type is + in the form of #oid, where oid is the object id + of the type + + ::= | |
* \snippet{doc} tables/predefinedDatatypes.dox predefined_std_datatypes_table diff --git a/doxygen/dox/Specifications.dox b/doxygen/dox/Specifications.dox index f2ba467d7bb..77bb0a8f407 100644 --- a/doxygen/dox/Specifications.dox +++ b/doxygen/dox/Specifications.dox @@ -5,6 +5,7 @@ \li \ref DDLBNF110 \li \ref DDLBNF112 \li \ref DDLBNF114 +\li \ref DDLBNF200 \section File Format diff --git a/doxygen/examples/H5.format.html b/doxygen/examples/H5.format.html index 0876c56c007..2272a2b5eff 100644 --- a/doxygen/examples/H5.format.html +++ b/doxygen/examples/H5.format.html @@ -476,6 +476,16 @@ and do not represent any values or padding in the file.

+
+

I.B. Changes for HDF5 2.0

+

The following sections have been + changed or added for the 2.0 release:

+
    +
  • Under “The Datatype Message”, + in the Description for “Fields:Datatype Message”, + version 5 was added, as well as the new Complex class (11).
  • +
+

I.B. Changes for HDF5 1.12

The following sections have been @@ -9685,6 +9695,11 @@

IV.A.2.d. The Datatype Message

Used to encode the revised reference datatype. + + 5 + Used when a complex number datatype needs to be encoded. + +

The class of the datatype determines the format for the class @@ -9752,6 +9767,11 @@

IV.A.2.d. The Datatype Message

10 Array + + + 11 + Complex +

@@ -11525,6 +11545,119 @@

IV.A.2.d. The Datatype Message

+
+
+ +

Class specific information for the Complex class (Class 11):

+ +
+ + + + + + + + + + + + + + + + + + + + + + +
+ Bits: Complex Bit Field Description +
BitsMeaning

0

Homogeneous. If zero, each part of the complex number + datatype is a different floating point datatype (heterogeneous). + Otherwise, each part of the complex number datatype is the same + floating point datatype (homogeneous). Currently, only homogeneous + complex number datatypes are supported.

1,2

Complex number form. This two-bit value contains the type of + complex number datatype described. The values defined are: + + + + + + + + + + + + + + + + + + + + + + + + + + +
ValueDescription
0Rectangular +
1Polar +
2Exponential +
3Reserved +

+ +

Currently, only rectangular complex number datatypes are supported.

+

3-23

Reserved (zero).

+
+ +
+
+ + + + + + + + + + + + + +
+ Layout: Complex Property Description +
ByteByteByteByte

Parent Type Message

+
+ +
+
+ + + + + + + + + + + +
+ Fields: Complex Property Description +
Field NameDescription

Parent Type Message

+

Each complex number type is based on a parent floating point type. + This field contains the datatype message describing that parent type. +

+
+

IV.A.2.e. The Data Storage - diff --git a/doxygen/examples/tables/predefinedDatatypes.dox b/doxygen/examples/tables/predefinedDatatypes.dox index 6cf044af5d4..f73382ab865 100644 --- a/doxygen/examples/tables/predefinedDatatypes.dox +++ b/doxygen/examples/tables/predefinedDatatypes.dox @@ -35,6 +35,41 @@ //! [predefined_ieee_datatypes_table] * * +//! [predefined_complex_datatypes_table] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Predefined Complex Number Datatypes
DatatypeDescription
#H5T_COMPLEX_IEEE_F16BEComplex number of 2 16-bit big-endian IEEE floating point numbers
#H5T_COMPLEX_IEEE_F16LEComplex number of 2 16-bit little-endian IEEE floating point numbers
#H5T_COMPLEX_IEEE_F32BEComplex number of 2 32-bit big-endian IEEE floating point numbers
#H5T_COMPLEX_IEEE_F32LEComplex number of 2 32-bit little-endian IEEE floating point numbers
#H5T_COMPLEX_IEEE_F64BEComplex number of 2 64-bit big-endian IEEE floating point numbers
#H5T_COMPLEX_IEEE_F64LEComplex number of 2 64-bit little-endian IEEE floating point numbers
+//! [predefined_complex_datatypes_table] + * + * //! [predefined_std_datatypes_table] @@ -489,6 +524,18 @@ + + + + + + + + + + + + diff --git a/fortran/src/H5Tf.c b/fortran/src/H5Tf.c index d4b8363688e..f6992f91712 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 ff1b84af34f..1416493e4d7 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 37706118a3e..53410f63e77 100644 --- a/fortran/src/H5_f.c +++ b/fortran/src/H5_f.c @@ -848,6 +848,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 79c3cbcd3d9..fd871829f4f 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 @@ -705,6 +705,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 9c973126290..7e486cffdfe 100644 --- a/fortran/src/H5f90global.F90 +++ b/fortran/src/H5f90global.F90 @@ -863,6 +863,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 @@ -901,6 +902,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 b064947b919..6457d8844d3 100644 --- a/hl/src/H5LT.c +++ b/hl/src/H5LT.c @@ -2753,6 +2753,49 @@ H5LT_dtype_to_text(hid_t dtype, char *dt_str, H5LT_lang_t lang, size_t *slen, bo break; } + case H5T_COMPLEX: { + hid_t super; + size_t super_len; + char *stmp = NULL; + + /* Print lead-in */ + snprintf(dt_str, *slen, "H5T_COMPLEX {\n"); + indent += COL; + if (!(dt_str = indentation(indent + COL, dt_str, no_user_buf, slen))) + goto out; + + if ((super = H5Tget_super(dtype)) < 0) + goto out; + if (H5LTdtype_to_text(super, NULL, lang, &super_len) < 0) + goto out; + stmp = (char *)calloc(super_len, sizeof(char)); + if (H5LTdtype_to_text(super, stmp, lang, &super_len) < 0) { + free(stmp); + goto out; + } + if (!(dt_str = realloc_and_append(no_user_buf, slen, dt_str, stmp))) { + free(stmp); + goto out; + } + + if (stmp) + free(stmp); + stmp = NULL; + snprintf(tmp_str, TMP_LEN, "\n"); + if (!(dt_str = realloc_and_append(no_user_buf, slen, dt_str, tmp_str))) + goto out; + H5Tclose(super); + + /* Print closing */ + indent -= COL; + if (!(dt_str = indentation(indent + COL, dt_str, no_user_buf, slen))) + goto out; + snprintf(tmp_str, TMP_LEN, "}"); + if (!(dt_str = realloc_and_append(no_user_buf, slen, dt_str, tmp_str))) + goto out; + + break; + } case H5T_TIME: snprintf(dt_str, *slen, "H5T_TIME: not yet implemented"); break; diff --git a/hl/src/H5LTanalyze.c b/hl/src/H5LTanalyze.c index 1b7355b130f..5ee4a2c3d47 100644 --- a/hl/src/H5LTanalyze.c +++ b/hl/src/H5LTanalyze.c @@ -645,8 +645,8 @@ static void yynoreturn yy_fatal_error ( const char* msg ); (yy_hold_char) = *yy_cp; \ *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 67 -#define YY_END_OF_BUFFER 68 +#define YY_NUM_RULES 77 +#define YY_END_OF_BUFFER 78 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -654,39 +654,45 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[283] = +static const flex_int16_t yy_accept[335] = { 0, - 66, 66, 68, 67, 66, 67, 58, 64, 65, 67, - 67, 67, 67, 62, 63, 60, 61, 66, 0, 58, - 0, 0, 0, 0, 0, 59, 0, 0, 0, 0, - 0, 41, 0, 0, 0, 0, 0, 42, 0, 0, + 76, 76, 78, 77, 76, 77, 68, 74, 75, 77, + 77, 77, 77, 72, 73, 70, 71, 76, 0, 68, + 0, 0, 0, 0, 0, 69, 0, 0, 0, 0, + 0, 50, 0, 0, 0, 0, 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 40, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 57, 39, 0, 0, 0, 48, 52, 0, 0, - 0, 0, 0, 0, 0, 0, 54, 56, 53, 0, + 0, 67, 48, 0, 0, 0, 57, 61, 0, 0, + 0, 0, 0, 0, 0, 0, 63, 66, 62, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 0, 38, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 65, + 0, 0, 0, 0, 0, 0, 0, 0, 47, 0, + 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 2, 0, 0, 0, + 0, 0, 0, 9, 10, 0, 0, 59, 0, 0, + 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 1, 2, 0, 0, 0, 0, 0, 0, 9, - 10, 0, 0, 50, 0, 47, 0, 0, 0, 0, + 0, 3, 4, 5, 6, 7, 8, 11, 12, 13, + 14, 15, 16, 0, 0, 0, 0, 55, 58, 28, + 29, 30, 31, 32, 33, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 17, 0, 0, 0, 0, 24, 0, + 0, 0, 23, 0, 0, 0, 53, 0, 0, 0, + 0, 35, 0, 26, 18, 20, 19, 0, 25, 0, + 52, 54, 0, 36, 0, 0, 0, 27, 21, 0, + 0, 34, 0, 37, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3, 4, 5, 6, - 7, 8, 11, 12, 13, 14, 15, 16, 0, 0, - 0, 46, 49, 28, 29, 30, 31, 32, 33, 0, - 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, - 0, 24, 0, 0, 0, 23, 0, 0, 0, 44, - 0, 0, 0, 35, 0, 26, 18, 20, 19, 0, - 25, 0, 43, 45, 36, 0, 0, 27, 21, 34, - 37, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 38, 39, 40, 41, 42, + 43, 0, 0, 0, 0, 0, 0, 0, 44, 0, + 45, 0, 46, 0 } ; static const YY_CHAR yy_ec[256] = @@ -699,12 +705,12 @@ static const YY_CHAR yy_ec[256] = 7, 8, 9, 10, 4, 11, 4, 12, 13, 1, 1, 1, 1, 1, 14, 15, 16, 17, 18, 19, 20, 21, 22, 1, 1, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 1, 1, 34, 35, - 36, 1, 37, 1, 38, 1, 1, 1, 1, 1, + 28, 29, 30, 31, 32, 33, 1, 34, 35, 36, + 37, 1, 38, 1, 39, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 39, 1, 40, 1, 1, 1, 1, 1, + 1, 1, 40, 1, 41, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -721,166 +727,193 @@ static const YY_CHAR yy_ec[256] = 1, 1, 1, 1, 1 } ; -static const YY_CHAR yy_meta[41] = +static const YY_CHAR yy_meta[42] = { 0, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1 } ; -static const flex_int16_t yy_base[285] = +static const flex_int16_t yy_base[337] = { 0, - 0, 0, 307, 308, 304, 0, 0, 308, 308, 11, - 296, 277, 272, 308, 308, 308, 308, 300, 298, 0, - 282, 265, 267, 269, 267, 308, 264, 267, 255, 254, - 16, 308, 273, 33, 14, 276, 267, 308, 259, 24, - 262, 260, 267, 270, 256, 251, 34, 259, 266, 262, - 243, 248, 252, 257, 244, 241, 243, 253, 239, 255, - 36, 239, 249, 231, 245, 308, 246, 249, 235, 230, - 255, 235, 227, 239, 234, 227, 216, 34, 231, 227, - 233, 308, 308, 216, 223, 210, 308, 308, 218, 208, - 212, 212, 38, 218, 39, 228, 308, 308, 308, 209, - - 47, 226, 220, 220, 219, 66, 73, 216, 203, 207, - 218, 207, 201, 199, 204, 80, 190, 308, 217, 220, - 217, 52, 214, 217, 214, 59, 308, 198, 206, 196, - 201, 201, 197, 177, 204, 207, 204, 75, 66, 73, - 78, 193, 192, 80, 85, 87, 191, 190, 184, 190, - 187, 308, 182, 192, 172, 89, 91, 94, 180, 174, - 176, 173, 96, 95, 102, 179, 178, 177, 176, 175, - 174, 308, 308, 173, 172, 171, 170, 169, 168, 308, - 308, 96, 167, 308, 162, 308, 178, 164, 163, 162, - 161, 160, 159, 162, 143, 148, 142, 146, 145, 145, - - 148, 142, 146, 141, 103, 144, 308, 308, 308, 308, - 308, 308, 308, 308, 308, 308, 308, 308, 150, 145, - 135, 308, 308, 308, 308, 308, 308, 308, 308, 132, - 145, 145, 308, 126, 132, 136, 141, 125, 139, 121, - 125, 125, 123, 131, 118, 132, 308, 122, 113, 128, - 122, 308, 112, 109, 110, 308, 113, 117, 107, 308, - 110, 114, 112, 123, 98, 308, 308, 308, 308, 100, - 308, 84, 308, 308, 308, 89, 68, 308, 308, 308, - 308, 308, 132, 65 + 0, 0, 360, 361, 357, 0, 0, 361, 361, 12, + 349, 330, 325, 361, 361, 361, 361, 353, 351, 0, + 335, 317, 320, 322, 320, 361, 317, 320, 307, 306, + 17, 361, 326, 34, 15, 329, 320, 361, 312, 31, + 315, 313, 320, 323, 309, 304, 35, 312, 319, 315, + 295, 301, 305, 310, 297, 294, 296, 306, 292, 308, + 34, 292, 302, 283, 298, 361, 299, 302, 288, 283, + 308, 288, 280, 292, 287, 280, 268, 32, 284, 280, + 286, 361, 361, 268, 39, 263, 361, 361, 272, 261, + 266, 266, 44, 272, 43, 282, 361, 361, 361, 277, + + 262, 55, 279, 273, 273, 272, 67, 74, 269, 256, + 260, 271, 251, 259, 253, 251, 256, 81, 241, 361, + 269, 272, 269, 60, 266, 269, 266, 67, 361, 250, + 258, 248, 231, 252, 252, 248, 227, 255, 258, 255, + 76, 74, 79, 81, 244, 243, 86, 88, 90, 242, + 241, 235, 241, 238, 233, 361, 232, 242, 222, 92, + 95, 97, 230, 224, 226, 223, 99, 98, 101, 229, + 228, 227, 226, 225, 224, 361, 361, 223, 222, 221, + 220, 219, 218, 361, 361, 99, 217, 361, 216, 211, + 361, 227, 213, 212, 211, 210, 209, 208, 211, 192, + + 197, 191, 195, 194, 194, 197, 191, 195, 190, 106, + 193, 361, 361, 361, 361, 361, 361, 361, 361, 361, + 361, 361, 361, 199, 194, 184, 192, 361, 361, 361, + 361, 361, 361, 361, 361, 180, 193, 193, 361, 174, + 180, 184, 189, 173, 187, 169, 173, 173, 171, 179, + 166, 180, 175, 361, 169, 160, 175, 169, 361, 159, + 156, 157, 361, 160, 164, 154, 361, 158, 164, 141, + 161, 95, 155, 361, 361, 361, 361, 157, 361, 145, + 361, 361, 156, 135, 163, 156, 153, 361, 361, 128, + 154, 361, 143, 129, 157, 160, 157, 138, 139, 146, + + 113, 122, 124, 137, 133, 133, 140, 139, 138, 137, + 136, 135, 125, 128, 125, 361, 361, 361, 361, 361, + 361, 123, 126, 116, 124, 107, 117, 93, 361, 103, + 361, 46, 361, 361, 147, 52 } ; -static const flex_int16_t yy_def[285] = +static const flex_int16_t yy_def[337] = { 0, - 282, 1, 282, 282, 282, 283, 284, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 283, 284, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 0, 282, 282 + 334, 1, 334, 334, 334, 335, 336, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 335, 336, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 0, 334, 334 } ; -static const flex_int16_t yy_nxt[349] = +static const flex_int16_t yy_nxt[403] = { 0, 4, 5, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 9, 4, 4, 10, 4, 4, 4, 4, 11, 4, 4, 4, 4, 12, 4, 4, 4, 13, - 4, 4, 4, 4, 4, 14, 15, 4, 16, 17, - 21, 22, 36, 48, 49, 37, 39, 62, 40, 53, - 41, 42, 77, 54, 43, 94, 63, 44, 45, 106, - 113, 55, 46, 109, 78, 47, 142, 20, 110, 107, - 119, 95, 120, 147, 143, 121, 122, 123, 114, 124, - 166, 148, 125, 126, 135, 281, 136, 168, 167, 137, - 159, 160, 170, 161, 174, 169, 162, 163, 280, 176, - - 171, 178, 175, 188, 164, 190, 165, 177, 192, 179, - 201, 189, 198, 191, 279, 202, 193, 203, 199, 278, - 277, 200, 219, 204, 205, 241, 220, 276, 242, 275, - 274, 206, 19, 273, 19, 272, 271, 270, 269, 268, - 267, 266, 265, 264, 263, 262, 261, 260, 259, 258, - 257, 256, 255, 254, 253, 252, 251, 250, 249, 248, - 247, 246, 245, 244, 243, 240, 239, 238, 237, 236, - 235, 234, 233, 232, 231, 230, 229, 228, 227, 226, - 225, 224, 223, 222, 221, 218, 217, 216, 215, 214, - 213, 212, 211, 210, 209, 208, 207, 197, 196, 195, - - 194, 187, 186, 185, 184, 183, 182, 181, 180, 173, - 172, 158, 157, 156, 155, 154, 153, 152, 151, 150, - 149, 146, 145, 144, 141, 140, 139, 138, 134, 133, - 132, 131, 130, 129, 128, 127, 118, 117, 116, 115, - 112, 111, 108, 105, 104, 103, 102, 101, 100, 99, - 98, 97, 96, 93, 92, 91, 90, 89, 88, 87, - 86, 85, 84, 83, 82, 81, 80, 79, 76, 75, - 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, - 64, 61, 60, 59, 58, 57, 56, 52, 51, 50, - 38, 35, 34, 33, 32, 31, 30, 29, 28, 27, - - 26, 18, 25, 24, 23, 18, 282, 3, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282 + 4, 4, 4, 4, 4, 4, 14, 15, 4, 16, + 17, 21, 22, 36, 48, 49, 37, 39, 62, 40, + 77, 41, 42, 94, 20, 43, 53, 63, 44, 45, + 54, 100, 78, 46, 101, 107, 47, 110, 115, 55, + 95, 121, 111, 122, 145, 108, 123, 124, 125, 333, + 126, 150, 146, 127, 128, 138, 116, 139, 170, 151, + 140, 163, 164, 172, 165, 174, 171, 166, 167, 285, + + 178, 173, 180, 175, 182, 168, 193, 169, 179, 195, + 181, 197, 183, 206, 194, 203, 208, 196, 207, 198, + 332, 204, 209, 210, 205, 224, 331, 307, 247, 225, + 211, 248, 295, 286, 296, 308, 309, 297, 311, 330, + 329, 328, 327, 326, 310, 325, 312, 19, 324, 19, + 323, 322, 321, 320, 319, 318, 317, 316, 315, 314, + 313, 306, 305, 304, 303, 302, 301, 300, 299, 298, + 294, 293, 292, 291, 290, 289, 288, 287, 284, 283, + 282, 281, 280, 279, 278, 277, 276, 275, 274, 273, + 272, 271, 270, 269, 268, 267, 266, 265, 264, 263, + + 262, 261, 260, 259, 258, 257, 256, 255, 254, 253, + 252, 251, 250, 249, 246, 245, 244, 243, 242, 241, + 240, 239, 238, 237, 236, 235, 234, 233, 232, 231, + 230, 229, 228, 227, 226, 223, 222, 221, 220, 219, + 218, 217, 216, 215, 214, 213, 212, 202, 201, 200, + 199, 192, 191, 190, 189, 188, 187, 186, 185, 184, + 177, 176, 162, 161, 160, 159, 158, 157, 156, 155, + 154, 153, 152, 149, 148, 147, 144, 143, 142, 141, + 137, 136, 135, 134, 133, 132, 131, 130, 129, 120, + 119, 118, 117, 114, 113, 112, 109, 106, 105, 104, + + 103, 102, 99, 98, 97, 96, 93, 92, 91, 90, + 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, + 79, 76, 75, 74, 73, 72, 71, 70, 69, 68, + 67, 66, 65, 64, 61, 60, 59, 58, 57, 56, + 52, 51, 50, 38, 35, 34, 33, 32, 31, 30, + 29, 28, 27, 26, 18, 25, 24, 23, 18, 334, + 3, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + + 334, 334 } ; -static const flex_int16_t yy_chk[349] = +static const flex_int16_t yy_chk[403] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 10, 10, 31, 35, 35, 31, 34, 47, 34, 40, - 34, 34, 61, 40, 34, 78, 47, 34, 34, 93, - 101, 40, 34, 95, 61, 34, 122, 284, 95, 93, - 106, 78, 106, 126, 122, 106, 106, 107, 101, 107, - 139, 126, 107, 107, 116, 277, 116, 140, 139, 116, - 138, 138, 141, 138, 144, 140, 138, 138, 276, 145, - - 141, 146, 144, 156, 138, 157, 138, 145, 158, 146, - 164, 156, 163, 157, 272, 164, 158, 165, 163, 270, - 265, 163, 182, 165, 165, 205, 182, 264, 205, 263, - 262, 165, 283, 261, 283, 259, 258, 257, 255, 254, - 253, 251, 250, 249, 248, 246, 245, 244, 243, 242, - 241, 240, 239, 238, 237, 236, 235, 234, 232, 231, - 230, 221, 220, 219, 206, 204, 203, 202, 201, 200, - 199, 198, 197, 196, 195, 194, 193, 192, 191, 190, - 189, 188, 187, 185, 183, 179, 178, 177, 176, 175, - 174, 171, 170, 169, 168, 167, 166, 162, 161, 160, - - 159, 155, 154, 153, 151, 150, 149, 148, 147, 143, - 142, 137, 136, 135, 134, 133, 132, 131, 130, 129, - 128, 125, 124, 123, 121, 120, 119, 117, 115, 114, - 113, 112, 111, 110, 109, 108, 105, 104, 103, 102, - 100, 96, 94, 92, 91, 90, 89, 86, 85, 84, - 81, 80, 79, 77, 76, 75, 74, 73, 72, 71, - 70, 69, 68, 67, 65, 64, 63, 62, 60, 59, - 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, - 48, 46, 45, 44, 43, 42, 41, 39, 37, 36, - 33, 30, 29, 28, 27, 25, 24, 23, 22, 21, - - 19, 18, 13, 12, 11, 5, 3, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, - 282, 282, 282, 282, 282, 282, 282, 282 + 1, 10, 10, 31, 35, 35, 31, 34, 47, 34, + 61, 34, 34, 78, 336, 34, 40, 47, 34, 34, + 40, 85, 61, 34, 85, 93, 34, 95, 102, 40, + 78, 107, 95, 107, 124, 93, 107, 107, 108, 332, + 108, 128, 124, 108, 108, 118, 102, 118, 142, 128, + 118, 141, 141, 143, 141, 144, 142, 141, 141, 272, + + 147, 143, 148, 144, 149, 141, 160, 141, 147, 161, + 148, 162, 149, 168, 160, 167, 169, 161, 168, 162, + 330, 167, 169, 169, 167, 186, 328, 301, 210, 186, + 169, 210, 290, 272, 290, 301, 302, 290, 303, 327, + 326, 325, 324, 323, 302, 322, 303, 335, 315, 335, + 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, + 304, 300, 299, 298, 297, 296, 295, 294, 293, 291, + 287, 286, 285, 284, 283, 280, 278, 273, 271, 270, + 269, 268, 266, 265, 264, 262, 261, 260, 258, 257, + 256, 255, 253, 252, 251, 250, 249, 248, 247, 246, + + 245, 244, 243, 242, 241, 240, 238, 237, 236, 227, + 226, 225, 224, 211, 209, 208, 207, 206, 205, 204, + 203, 202, 201, 200, 199, 198, 197, 196, 195, 194, + 193, 192, 190, 189, 187, 183, 182, 181, 180, 179, + 178, 175, 174, 173, 172, 171, 170, 166, 165, 164, + 163, 159, 158, 157, 155, 154, 153, 152, 151, 150, + 146, 145, 140, 139, 138, 137, 136, 135, 134, 133, + 132, 131, 130, 127, 126, 125, 123, 122, 121, 119, + 117, 116, 115, 114, 113, 112, 111, 110, 109, 106, + 105, 104, 103, 101, 100, 96, 94, 92, 91, 90, + + 89, 86, 84, 81, 80, 79, 77, 76, 75, 74, + 73, 72, 71, 70, 69, 68, 67, 65, 64, 63, + 62, 60, 59, 58, 57, 56, 55, 54, 53, 52, + 51, 50, 49, 48, 46, 45, 44, 43, 42, 41, + 39, 37, 36, 33, 30, 29, 28, 27, 25, 24, + 23, 22, 21, 19, 18, 13, 12, 11, 5, 3, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 334, + + 334, 334 } ; static yy_state_type yy_last_accepting_state; @@ -939,8 +972,8 @@ static int my_yyinput(char *, int); extern char *myinput; extern size_t input_len; -#line 913 "hl/src//H5LTanalyze.c" -#line 914 "hl/src//H5LTanalyze.c" +#line 946 "hl/src//H5LTanalyze.c" +#line 947 "hl/src//H5LTanalyze.c" #define INITIAL 0 @@ -1152,7 +1185,7 @@ YY_DECL #line 53 "hl/src//H5LTanalyze.l" -#line 1126 "hl/src//H5LTanalyze.c" +#line 1159 "hl/src//H5LTanalyze.c" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1179,13 +1212,13 @@ YY_DECL while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 283 ) + if ( yy_current_state >= 335 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_base[yy_current_state] != 308 ); + while ( yy_base[yy_current_state] != 361 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1397,162 +1430,212 @@ YY_RULE_SETUP case 38: YY_RULE_SETUP #line 96 "hl/src//H5LTanalyze.l" -{return token(H5T_STRING_TOKEN);} +{return hid(H5T_COMPLEX_IEEE_F16BE_TOKEN);} YY_BREAK case 39: YY_RULE_SETUP #line 97 "hl/src//H5LTanalyze.l" -{return token(STRSIZE_TOKEN);} +{return hid(H5T_COMPLEX_IEEE_F16LE_TOKEN);} YY_BREAK case 40: YY_RULE_SETUP #line 98 "hl/src//H5LTanalyze.l" -{return token(STRPAD_TOKEN);} +{return hid(H5T_COMPLEX_IEEE_F32BE_TOKEN);} YY_BREAK case 41: YY_RULE_SETUP #line 99 "hl/src//H5LTanalyze.l" -{return token(CSET_TOKEN);} +{return hid(H5T_COMPLEX_IEEE_F32LE_TOKEN);} YY_BREAK case 42: YY_RULE_SETUP #line 100 "hl/src//H5LTanalyze.l" -{return token(CTYPE_TOKEN);} +{return hid(H5T_COMPLEX_IEEE_F64BE_TOKEN);} YY_BREAK case 43: YY_RULE_SETUP #line 101 "hl/src//H5LTanalyze.l" -{return token(H5T_STR_NULLTERM_TOKEN);} +{return hid(H5T_COMPLEX_IEEE_F64LE_TOKEN);} YY_BREAK case 44: YY_RULE_SETUP #line 102 "hl/src//H5LTanalyze.l" -{return token(H5T_STR_NULLPAD_TOKEN);} +{return hid(H5T_NATIVE_FLOAT_COMPLEX_TOKEN);} YY_BREAK case 45: YY_RULE_SETUP #line 103 "hl/src//H5LTanalyze.l" -{return token(H5T_STR_SPACEPAD_TOKEN);} +{return hid(H5T_NATIVE_DOUBLE_COMPLEX_TOKEN);} YY_BREAK case 46: YY_RULE_SETUP #line 104 "hl/src//H5LTanalyze.l" -{return token(H5T_CSET_ASCII_TOKEN);} +{return hid(H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN);} YY_BREAK case 47: YY_RULE_SETUP -#line 105 "hl/src//H5LTanalyze.l" -{return token(H5T_CSET_UTF8_TOKEN);} +#line 106 "hl/src//H5LTanalyze.l" +{return token(H5T_STRING_TOKEN);} YY_BREAK case 48: YY_RULE_SETUP -#line 106 "hl/src//H5LTanalyze.l" -{return token(H5T_C_S1_TOKEN);} +#line 107 "hl/src//H5LTanalyze.l" +{return token(STRSIZE_TOKEN);} YY_BREAK case 49: YY_RULE_SETUP -#line 107 "hl/src//H5LTanalyze.l" -{return token(H5T_FORTRAN_S1_TOKEN);} +#line 108 "hl/src//H5LTanalyze.l" +{return token(STRPAD_TOKEN);} YY_BREAK case 50: YY_RULE_SETUP -#line 108 "hl/src//H5LTanalyze.l" -{return token(H5T_VARIABLE_TOKEN);} +#line 109 "hl/src//H5LTanalyze.l" +{return token(CSET_TOKEN);} YY_BREAK case 51: YY_RULE_SETUP #line 110 "hl/src//H5LTanalyze.l" -{return token(H5T_COMPOUND_TOKEN);} +{return token(CTYPE_TOKEN);} YY_BREAK case 52: YY_RULE_SETUP #line 111 "hl/src//H5LTanalyze.l" -{return token(H5T_ENUM_TOKEN);} +{return token(H5T_STR_NULLTERM_TOKEN);} YY_BREAK case 53: YY_RULE_SETUP #line 112 "hl/src//H5LTanalyze.l" -{return token(H5T_ARRAY_TOKEN);} +{return token(H5T_STR_NULLPAD_TOKEN);} YY_BREAK case 54: YY_RULE_SETUP #line 113 "hl/src//H5LTanalyze.l" -{return token(H5T_VLEN_TOKEN);} +{return token(H5T_STR_SPACEPAD_TOKEN);} YY_BREAK case 55: YY_RULE_SETUP -#line 115 "hl/src//H5LTanalyze.l" -{return token(H5T_OPAQUE_TOKEN);} +#line 114 "hl/src//H5LTanalyze.l" +{return token(H5T_CSET_ASCII_TOKEN);} YY_BREAK case 56: YY_RULE_SETUP -#line 116 "hl/src//H5LTanalyze.l" -{return token(OPQ_SIZE_TOKEN);} +#line 115 "hl/src//H5LTanalyze.l" +{return token(H5T_CSET_UTF8_TOKEN);} YY_BREAK case 57: YY_RULE_SETUP +#line 116 "hl/src//H5LTanalyze.l" +{return token(H5T_C_S1_TOKEN);} + YY_BREAK +case 58: +YY_RULE_SETUP #line 117 "hl/src//H5LTanalyze.l" +{return token(H5T_FORTRAN_S1_TOKEN);} + YY_BREAK +case 59: +YY_RULE_SETUP +#line 118 "hl/src//H5LTanalyze.l" +{return token(H5T_VARIABLE_TOKEN);} + YY_BREAK +case 60: +YY_RULE_SETUP +#line 120 "hl/src//H5LTanalyze.l" +{return token(H5T_COMPOUND_TOKEN);} + YY_BREAK +case 61: +YY_RULE_SETUP +#line 121 "hl/src//H5LTanalyze.l" +{return token(H5T_ENUM_TOKEN);} + YY_BREAK +case 62: +YY_RULE_SETUP +#line 122 "hl/src//H5LTanalyze.l" +{return token(H5T_ARRAY_TOKEN);} + YY_BREAK +case 63: +YY_RULE_SETUP +#line 123 "hl/src//H5LTanalyze.l" +{return token(H5T_VLEN_TOKEN);} + YY_BREAK +case 64: +YY_RULE_SETUP +#line 124 "hl/src//H5LTanalyze.l" +{return token(H5T_COMPLEX_TOKEN);} + YY_BREAK +case 65: +YY_RULE_SETUP +#line 126 "hl/src//H5LTanalyze.l" +{return token(H5T_OPAQUE_TOKEN);} + YY_BREAK +case 66: +YY_RULE_SETUP +#line 127 "hl/src//H5LTanalyze.l" +{return token(OPQ_SIZE_TOKEN);} + YY_BREAK +case 67: +YY_RULE_SETUP +#line 128 "hl/src//H5LTanalyze.l" {return token(OPQ_TAG_TOKEN);} YY_BREAK -case 58: +case 68: YY_RULE_SETUP -#line 119 "hl/src//H5LTanalyze.l" +#line 130 "hl/src//H5LTanalyze.l" { H5LTyylval.ival = atoi(yytext); return NUMBER; } YY_BREAK -case 59: -/* rule 59 can match eol */ +case 69: +/* rule 69 can match eol */ YY_RULE_SETUP -#line 124 "hl/src//H5LTanalyze.l" +#line 135 "hl/src//H5LTanalyze.l" { H5LTyylval.sval = trim_quotes(yytext); return STRING; } YY_BREAK -case 60: +case 70: YY_RULE_SETUP -#line 129 "hl/src//H5LTanalyze.l" +#line 140 "hl/src//H5LTanalyze.l" {return token('{');} YY_BREAK -case 61: +case 71: YY_RULE_SETUP -#line 130 "hl/src//H5LTanalyze.l" +#line 141 "hl/src//H5LTanalyze.l" {return token('}');} YY_BREAK -case 62: +case 72: YY_RULE_SETUP -#line 131 "hl/src//H5LTanalyze.l" +#line 142 "hl/src//H5LTanalyze.l" {return token('[');} YY_BREAK -case 63: +case 73: YY_RULE_SETUP -#line 132 "hl/src//H5LTanalyze.l" +#line 143 "hl/src//H5LTanalyze.l" {return token(']');} YY_BREAK -case 64: +case 74: YY_RULE_SETUP -#line 133 "hl/src//H5LTanalyze.l" +#line 144 "hl/src//H5LTanalyze.l" {return token(':');} YY_BREAK -case 65: +case 75: YY_RULE_SETUP -#line 134 "hl/src//H5LTanalyze.l" +#line 145 "hl/src//H5LTanalyze.l" {return token(';');} YY_BREAK -case 66: -/* rule 66 can match eol */ +case 76: +/* rule 76 can match eol */ YY_RULE_SETUP -#line 135 "hl/src//H5LTanalyze.l" +#line 146 "hl/src//H5LTanalyze.l" ; YY_BREAK -case 67: +case 77: YY_RULE_SETUP -#line 137 "hl/src//H5LTanalyze.l" +#line 148 "hl/src//H5LTanalyze.l" ECHO; YY_BREAK -#line 1526 "hl/src//H5LTanalyze.c" +#line 1609 "hl/src//H5LTanalyze.c" case YY_STATE_EOF(INITIAL): yyterminate(); @@ -1849,7 +1932,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 283 ) + if ( yy_current_state >= 335 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -1877,11 +1960,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 283 ) + if ( yy_current_state >= 335 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 282); + yy_is_jam = (yy_current_state == 334); return yy_is_jam ? 0 : yy_current_state; } @@ -2557,7 +2640,7 @@ void yyfree (void * ptr ) #define YYTABLES_NAME "yytables" -#line 137 "hl/src//H5LTanalyze.l" +#line 148 "hl/src//H5LTanalyze.l" /* Allocate a copy of `quoted` with the double quote character at diff --git a/hl/src/H5LTanalyze.l b/hl/src/H5LTanalyze.l index f78a4159567..84b0a61f03a 100644 --- a/hl/src/H5LTanalyze.l +++ b/hl/src/H5LTanalyze.l @@ -93,6 +93,16 @@ 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_COMPLEX_IEEE_F16BE {return hid(H5T_COMPLEX_IEEE_F16BE_TOKEN);} +H5T_COMPLEX_IEEE_F16LE {return hid(H5T_COMPLEX_IEEE_F16LE_TOKEN);} +H5T_COMPLEX_IEEE_F32BE {return hid(H5T_COMPLEX_IEEE_F32BE_TOKEN);} +H5T_COMPLEX_IEEE_F32LE {return hid(H5T_COMPLEX_IEEE_F32LE_TOKEN);} +H5T_COMPLEX_IEEE_F64BE {return hid(H5T_COMPLEX_IEEE_F64BE_TOKEN);} +H5T_COMPLEX_IEEE_F64LE {return hid(H5T_COMPLEX_IEEE_F64LE_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 +121,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.c b/hl/src/H5LTparse.c index 46c3ae79b72..df2b4d04d25 100644 --- a/hl/src/H5LTparse.c +++ b/hl/src/H5LTparse.c @@ -221,77 +221,88 @@ enum yysymbol_kind_t YYSYMBOL_H5T_NATIVE_FLOAT_TOKEN = 37, /* H5T_NATIVE_FLOAT_TOKEN */ YYSYMBOL_H5T_NATIVE_DOUBLE_TOKEN = 38, /* H5T_NATIVE_DOUBLE_TOKEN */ YYSYMBOL_H5T_NATIVE_LDOUBLE_TOKEN = 39, /* H5T_NATIVE_LDOUBLE_TOKEN */ - YYSYMBOL_H5T_STRING_TOKEN = 40, /* H5T_STRING_TOKEN */ - YYSYMBOL_STRSIZE_TOKEN = 41, /* STRSIZE_TOKEN */ - YYSYMBOL_STRPAD_TOKEN = 42, /* STRPAD_TOKEN */ - YYSYMBOL_CSET_TOKEN = 43, /* CSET_TOKEN */ - YYSYMBOL_CTYPE_TOKEN = 44, /* CTYPE_TOKEN */ - YYSYMBOL_H5T_VARIABLE_TOKEN = 45, /* H5T_VARIABLE_TOKEN */ - YYSYMBOL_H5T_STR_NULLTERM_TOKEN = 46, /* H5T_STR_NULLTERM_TOKEN */ - YYSYMBOL_H5T_STR_NULLPAD_TOKEN = 47, /* H5T_STR_NULLPAD_TOKEN */ - YYSYMBOL_H5T_STR_SPACEPAD_TOKEN = 48, /* H5T_STR_SPACEPAD_TOKEN */ - YYSYMBOL_H5T_CSET_ASCII_TOKEN = 49, /* H5T_CSET_ASCII_TOKEN */ - YYSYMBOL_H5T_CSET_UTF8_TOKEN = 50, /* H5T_CSET_UTF8_TOKEN */ - YYSYMBOL_H5T_C_S1_TOKEN = 51, /* H5T_C_S1_TOKEN */ - YYSYMBOL_H5T_FORTRAN_S1_TOKEN = 52, /* H5T_FORTRAN_S1_TOKEN */ - YYSYMBOL_H5T_OPAQUE_TOKEN = 53, /* H5T_OPAQUE_TOKEN */ - YYSYMBOL_OPQ_SIZE_TOKEN = 54, /* OPQ_SIZE_TOKEN */ - YYSYMBOL_OPQ_TAG_TOKEN = 55, /* OPQ_TAG_TOKEN */ - YYSYMBOL_H5T_COMPOUND_TOKEN = 56, /* H5T_COMPOUND_TOKEN */ - YYSYMBOL_H5T_ENUM_TOKEN = 57, /* H5T_ENUM_TOKEN */ - YYSYMBOL_H5T_ARRAY_TOKEN = 58, /* H5T_ARRAY_TOKEN */ - YYSYMBOL_H5T_VLEN_TOKEN = 59, /* H5T_VLEN_TOKEN */ - YYSYMBOL_STRING = 60, /* STRING */ - YYSYMBOL_NUMBER = 61, /* NUMBER */ - YYSYMBOL_62_ = 62, /* '{' */ - YYSYMBOL_63_ = 63, /* '}' */ - YYSYMBOL_64_ = 64, /* '[' */ - YYSYMBOL_65_ = 65, /* ']' */ - YYSYMBOL_66_ = 66, /* ':' */ - YYSYMBOL_67_ = 67, /* ';' */ - YYSYMBOL_YYACCEPT = 68, /* $accept */ - YYSYMBOL_start = 69, /* start */ - YYSYMBOL_ddl_type = 70, /* ddl_type */ - YYSYMBOL_atomic_type = 71, /* atomic_type */ - YYSYMBOL_integer_type = 72, /* integer_type */ - YYSYMBOL_fp_type = 73, /* fp_type */ - YYSYMBOL_compound_type = 74, /* compound_type */ - YYSYMBOL_75_1 = 75, /* $@1 */ - YYSYMBOL_memb_list = 76, /* memb_list */ - YYSYMBOL_memb_def = 77, /* memb_def */ - YYSYMBOL_78_2 = 78, /* $@2 */ - YYSYMBOL_field_name = 79, /* field_name */ - YYSYMBOL_field_offset = 80, /* field_offset */ - YYSYMBOL_offset = 81, /* offset */ - YYSYMBOL_array_type = 82, /* array_type */ - YYSYMBOL_83_3 = 83, /* $@3 */ - YYSYMBOL_dim_list = 84, /* dim_list */ - YYSYMBOL_dim = 85, /* dim */ - YYSYMBOL_86_4 = 86, /* $@4 */ - YYSYMBOL_87_5 = 87, /* $@5 */ - YYSYMBOL_dimsize = 88, /* dimsize */ - YYSYMBOL_vlen_type = 89, /* vlen_type */ - YYSYMBOL_opaque_type = 90, /* opaque_type */ - YYSYMBOL_91_6 = 91, /* @6 */ - YYSYMBOL_92_7 = 92, /* $@7 */ - YYSYMBOL_opaque_size = 93, /* opaque_size */ - YYSYMBOL_opaque_tag = 94, /* opaque_tag */ - YYSYMBOL_string_type = 95, /* string_type */ - YYSYMBOL_96_8 = 96, /* $@8 */ - YYSYMBOL_97_9 = 97, /* $@9 */ - YYSYMBOL_98_10 = 98, /* $@10 */ - YYSYMBOL_99_11 = 99, /* @11 */ - YYSYMBOL_strsize = 100, /* strsize */ - YYSYMBOL_strpad = 101, /* strpad */ - YYSYMBOL_cset = 102, /* cset */ - YYSYMBOL_ctype = 103, /* ctype */ - YYSYMBOL_enum_type = 104, /* enum_type */ - YYSYMBOL_105_12 = 105, /* $@12 */ - YYSYMBOL_enum_list = 106, /* enum_list */ - YYSYMBOL_enum_def = 107, /* enum_def */ - YYSYMBOL_108_13 = 108, /* $@13 */ - YYSYMBOL_enum_symbol = 109, /* enum_symbol */ - YYSYMBOL_enum_val = 110 /* enum_val */ + YYSYMBOL_H5T_COMPLEX_IEEE_F16BE_TOKEN = 40, /* H5T_COMPLEX_IEEE_F16BE_TOKEN */ + YYSYMBOL_H5T_COMPLEX_IEEE_F16LE_TOKEN = 41, /* H5T_COMPLEX_IEEE_F16LE_TOKEN */ + YYSYMBOL_H5T_COMPLEX_IEEE_F32BE_TOKEN = 42, /* H5T_COMPLEX_IEEE_F32BE_TOKEN */ + YYSYMBOL_H5T_COMPLEX_IEEE_F32LE_TOKEN = 43, /* H5T_COMPLEX_IEEE_F32LE_TOKEN */ + YYSYMBOL_H5T_COMPLEX_IEEE_F64BE_TOKEN = 44, /* H5T_COMPLEX_IEEE_F64BE_TOKEN */ + YYSYMBOL_H5T_COMPLEX_IEEE_F64LE_TOKEN = 45, /* H5T_COMPLEX_IEEE_F64LE_TOKEN */ + YYSYMBOL_H5T_NATIVE_FLOAT_COMPLEX_TOKEN = 46, /* H5T_NATIVE_FLOAT_COMPLEX_TOKEN */ + YYSYMBOL_H5T_NATIVE_DOUBLE_COMPLEX_TOKEN = 47, /* H5T_NATIVE_DOUBLE_COMPLEX_TOKEN */ + YYSYMBOL_H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN = 48, /* H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN */ + YYSYMBOL_H5T_STRING_TOKEN = 49, /* H5T_STRING_TOKEN */ + YYSYMBOL_STRSIZE_TOKEN = 50, /* STRSIZE_TOKEN */ + YYSYMBOL_STRPAD_TOKEN = 51, /* STRPAD_TOKEN */ + YYSYMBOL_CSET_TOKEN = 52, /* CSET_TOKEN */ + YYSYMBOL_CTYPE_TOKEN = 53, /* CTYPE_TOKEN */ + YYSYMBOL_H5T_VARIABLE_TOKEN = 54, /* H5T_VARIABLE_TOKEN */ + YYSYMBOL_H5T_STR_NULLTERM_TOKEN = 55, /* H5T_STR_NULLTERM_TOKEN */ + YYSYMBOL_H5T_STR_NULLPAD_TOKEN = 56, /* H5T_STR_NULLPAD_TOKEN */ + YYSYMBOL_H5T_STR_SPACEPAD_TOKEN = 57, /* H5T_STR_SPACEPAD_TOKEN */ + YYSYMBOL_H5T_CSET_ASCII_TOKEN = 58, /* H5T_CSET_ASCII_TOKEN */ + YYSYMBOL_H5T_CSET_UTF8_TOKEN = 59, /* H5T_CSET_UTF8_TOKEN */ + YYSYMBOL_H5T_C_S1_TOKEN = 60, /* H5T_C_S1_TOKEN */ + YYSYMBOL_H5T_FORTRAN_S1_TOKEN = 61, /* H5T_FORTRAN_S1_TOKEN */ + YYSYMBOL_H5T_OPAQUE_TOKEN = 62, /* H5T_OPAQUE_TOKEN */ + YYSYMBOL_OPQ_SIZE_TOKEN = 63, /* OPQ_SIZE_TOKEN */ + YYSYMBOL_OPQ_TAG_TOKEN = 64, /* OPQ_TAG_TOKEN */ + YYSYMBOL_H5T_COMPOUND_TOKEN = 65, /* H5T_COMPOUND_TOKEN */ + YYSYMBOL_H5T_ENUM_TOKEN = 66, /* H5T_ENUM_TOKEN */ + YYSYMBOL_H5T_ARRAY_TOKEN = 67, /* H5T_ARRAY_TOKEN */ + YYSYMBOL_H5T_VLEN_TOKEN = 68, /* H5T_VLEN_TOKEN */ + YYSYMBOL_H5T_COMPLEX_TOKEN = 69, /* H5T_COMPLEX_TOKEN */ + YYSYMBOL_STRING = 70, /* STRING */ + YYSYMBOL_NUMBER = 71, /* NUMBER */ + YYSYMBOL_72_ = 72, /* '{' */ + YYSYMBOL_73_ = 73, /* '}' */ + YYSYMBOL_74_ = 74, /* '[' */ + YYSYMBOL_75_ = 75, /* ']' */ + YYSYMBOL_76_ = 76, /* ':' */ + YYSYMBOL_77_ = 77, /* ';' */ + YYSYMBOL_YYACCEPT = 78, /* $accept */ + YYSYMBOL_start = 79, /* start */ + YYSYMBOL_ddl_type = 80, /* ddl_type */ + YYSYMBOL_atomic_type = 81, /* atomic_type */ + YYSYMBOL_integer_type = 82, /* integer_type */ + YYSYMBOL_fp_type = 83, /* fp_type */ + YYSYMBOL_compound_type = 84, /* compound_type */ + YYSYMBOL_85_1 = 85, /* $@1 */ + YYSYMBOL_memb_list = 86, /* memb_list */ + YYSYMBOL_memb_def = 87, /* memb_def */ + YYSYMBOL_88_2 = 88, /* $@2 */ + YYSYMBOL_field_name = 89, /* field_name */ + YYSYMBOL_field_offset = 90, /* field_offset */ + YYSYMBOL_offset = 91, /* offset */ + YYSYMBOL_array_type = 92, /* array_type */ + YYSYMBOL_93_3 = 93, /* $@3 */ + YYSYMBOL_dim_list = 94, /* dim_list */ + YYSYMBOL_dim = 95, /* dim */ + YYSYMBOL_96_4 = 96, /* $@4 */ + YYSYMBOL_97_5 = 97, /* $@5 */ + YYSYMBOL_dimsize = 98, /* dimsize */ + YYSYMBOL_vlen_type = 99, /* vlen_type */ + YYSYMBOL_complex_type = 100, /* complex_type */ + YYSYMBOL_opaque_type = 101, /* opaque_type */ + YYSYMBOL_102_6 = 102, /* @6 */ + YYSYMBOL_103_7 = 103, /* $@7 */ + YYSYMBOL_opaque_size = 104, /* opaque_size */ + YYSYMBOL_opaque_tag = 105, /* opaque_tag */ + YYSYMBOL_string_type = 106, /* string_type */ + YYSYMBOL_107_8 = 107, /* $@8 */ + YYSYMBOL_108_9 = 108, /* $@9 */ + YYSYMBOL_109_10 = 109, /* $@10 */ + YYSYMBOL_110_11 = 110, /* @11 */ + YYSYMBOL_strsize = 111, /* strsize */ + YYSYMBOL_strpad = 112, /* strpad */ + YYSYMBOL_cset = 113, /* cset */ + YYSYMBOL_ctype = 114, /* ctype */ + YYSYMBOL_enum_type = 115, /* enum_type */ + YYSYMBOL_116_12 = 116, /* $@12 */ + YYSYMBOL_enum_list = 117, /* enum_list */ + YYSYMBOL_enum_def = 118, /* enum_def */ + YYSYMBOL_119_13 = 119, /* $@13 */ + YYSYMBOL_enum_symbol = 120, /* enum_symbol */ + YYSYMBOL_enum_val = 121 /* enum_val */ }; typedef enum yysymbol_kind_t yysymbol_kind_t; @@ -617,21 +628,21 @@ union yyalloc #endif /* !YYCOPY_NEEDED */ /* YYFINAL -- State number of the termination state. */ -#define YYFINAL 61 +#define YYFINAL 73 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 206 +#define YYLAST 239 /* YYNTOKENS -- Number of terminals. */ -#define YYNTOKENS 68 +#define YYNTOKENS 78 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 43 +#define YYNNTS 44 /* YYNRULES -- Number of rules. */ -#define YYNRULES 95 +#define YYNRULES 106 /* YYNSTATES -- Number of states. */ -#define YYNSTATES 137 +#define YYNSTATES 151 /* YYMAXUTOK -- Last valid token kind. */ -#define YYMAXUTOK 316 +#define YYMAXUTOK 326 /* YYTRANSLATE(TOKEN-NUM) -- Symbol number corresponding to TOKEN-NUM @@ -650,14 +661,14 @@ static const yytype_int8 yytranslate[] = 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 66, 67, + 2, 2, 2, 2, 2, 2, 2, 2, 76, 77, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 64, 2, 65, 2, 2, 2, 2, 2, 2, + 2, 74, 2, 75, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 62, 2, 63, 2, 2, 2, 2, + 2, 2, 2, 72, 2, 73, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, @@ -676,23 +687,25 @@ static const yytype_int8 yytranslate[] = 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, - 55, 56, 57, 58, 59, 60, 61 + 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, + 65, 66, 67, 68, 69, 70, 71 }; #if YYDEBUG /* YYRLINE[YYN] -- Source line where rule number YYN was defined. */ static const yytype_int16 yyrline[] = { - 0, 102, 102, 103, 105, 106, 107, 108, 110, 111, - 112, 113, 114, 117, 118, 119, 120, 121, 122, 123, - 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, - 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, - 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, - 159, 158, 167, 168, 170, 170, 207, 215, 216, 219, - 221, 221, 230, 231, 233, 234, 233, 241, 244, 251, - 256, 248, 263, 265, 270, 277, 286, 293, 267, 317, - 318, 320, 321, 322, 324, 325, 327, 328, 332, 331, - 336, 337, 339, 339, 389, 391 + 0, 108, 108, 109, 111, 112, 113, 114, 115, 117, + 118, 119, 120, 121, 124, 125, 126, 127, 128, 129, + 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, + 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, 153, 154, 155, 156, 157, 158, 159, 160, 161, + 162, 166, 165, 174, 175, 177, 177, 214, 222, 223, + 226, 228, 228, 237, 238, 240, 241, 240, 248, 251, + 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 271, 276, 268, 283, 285, 290, 297, 306, 313, 287, + 337, 338, 340, 341, 342, 344, 345, 347, 348, 352, + 351, 356, 357, 359, 359, 409, 411 }; #endif @@ -724,18 +737,23 @@ static const char *const yytname[] = "H5T_IEEE_F64BE_TOKEN", "H5T_IEEE_F64LE_TOKEN", "H5T_NATIVE_FLOAT16_TOKEN", "H5T_NATIVE_FLOAT_TOKEN", "H5T_NATIVE_DOUBLE_TOKEN", "H5T_NATIVE_LDOUBLE_TOKEN", - "H5T_STRING_TOKEN", "STRSIZE_TOKEN", "STRPAD_TOKEN", "CSET_TOKEN", - "CTYPE_TOKEN", "H5T_VARIABLE_TOKEN", "H5T_STR_NULLTERM_TOKEN", - "H5T_STR_NULLPAD_TOKEN", "H5T_STR_SPACEPAD_TOKEN", - "H5T_CSET_ASCII_TOKEN", "H5T_CSET_UTF8_TOKEN", "H5T_C_S1_TOKEN", - "H5T_FORTRAN_S1_TOKEN", "H5T_OPAQUE_TOKEN", "OPQ_SIZE_TOKEN", - "OPQ_TAG_TOKEN", "H5T_COMPOUND_TOKEN", "H5T_ENUM_TOKEN", - "H5T_ARRAY_TOKEN", "H5T_VLEN_TOKEN", "STRING", "NUMBER", "'{'", "'}'", - "'['", "']'", "':'", "';'", "$accept", "start", "ddl_type", - "atomic_type", "integer_type", "fp_type", "compound_type", "$@1", - "memb_list", "memb_def", "$@2", "field_name", "field_offset", "offset", - "array_type", "$@3", "dim_list", "dim", "$@4", "$@5", "dimsize", - "vlen_type", "opaque_type", "@6", "$@7", "opaque_size", "opaque_tag", + "H5T_COMPLEX_IEEE_F16BE_TOKEN", "H5T_COMPLEX_IEEE_F16LE_TOKEN", + "H5T_COMPLEX_IEEE_F32BE_TOKEN", "H5T_COMPLEX_IEEE_F32LE_TOKEN", + "H5T_COMPLEX_IEEE_F64BE_TOKEN", "H5T_COMPLEX_IEEE_F64LE_TOKEN", + "H5T_NATIVE_FLOAT_COMPLEX_TOKEN", "H5T_NATIVE_DOUBLE_COMPLEX_TOKEN", + "H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN", "H5T_STRING_TOKEN", "STRSIZE_TOKEN", + "STRPAD_TOKEN", "CSET_TOKEN", "CTYPE_TOKEN", "H5T_VARIABLE_TOKEN", + "H5T_STR_NULLTERM_TOKEN", "H5T_STR_NULLPAD_TOKEN", + "H5T_STR_SPACEPAD_TOKEN", "H5T_CSET_ASCII_TOKEN", "H5T_CSET_UTF8_TOKEN", + "H5T_C_S1_TOKEN", "H5T_FORTRAN_S1_TOKEN", "H5T_OPAQUE_TOKEN", + "OPQ_SIZE_TOKEN", "OPQ_TAG_TOKEN", "H5T_COMPOUND_TOKEN", + "H5T_ENUM_TOKEN", "H5T_ARRAY_TOKEN", "H5T_VLEN_TOKEN", + "H5T_COMPLEX_TOKEN", "STRING", "NUMBER", "'{'", "'}'", "'['", "']'", + "':'", "';'", "$accept", "start", "ddl_type", "atomic_type", + "integer_type", "fp_type", "compound_type", "$@1", "memb_list", + "memb_def", "$@2", "field_name", "field_offset", "offset", "array_type", + "$@3", "dim_list", "dim", "$@4", "$@5", "dimsize", "vlen_type", + "complex_type", "opaque_type", "@6", "$@7", "opaque_size", "opaque_tag", "string_type", "$@8", "$@9", "$@10", "@11", "strsize", "strpad", "cset", "ctype", "enum_type", "$@12", "enum_list", "enum_def", "$@13", "enum_symbol", "enum_val", YY_NULLPTR @@ -748,7 +766,7 @@ yysymbol_name (yysymbol_kind_t yysymbol) } #endif -#define YYPACT_NINF (-25) +#define YYPACT_NINF (-24) #define yypact_value_is_default(Yyn) \ ((Yyn) == YYPACT_NINF) @@ -762,20 +780,22 @@ yysymbol_name (yysymbol_kind_t yysymbol) STATE-NUM. */ static const yytype_int16 yypact[] = { - 120, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, -25, -25, -25, -25, -25, -24, -22, - -25, -13, -25, -11, 52, -25, -25, -25, -25, -25, - -25, -25, -25, -25, -25, 18, 48, 41, 177, 42, - 120, -25, -4, 44, -25, 39, -25, 45, -25, -25, - 40, -25, 43, 59, -25, -3, -25, -25, -25, -25, - -25, -25, -25, -25, 46, -25, 69, 58, 54, -21, - 60, -25, 0, 101, -25, 53, -25, -25, -25, -25, - -25, -25, -25, -25, -25, 95, -25, 96, 103, 98, - 105, 55, -25, -25, -25, -25, -25, -25, 100, -25, - 125, 106, -25, -6, -25, -25, -25, 104, -25, 126, - 49, -25, -25, 107, -25, 109, -25 + 140, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -21, -15, -24, + -14, -24, -4, -2, 119, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, 70, 58, 51, 207, + 52, 140, 140, -24, 68, 54, -24, 49, -24, 55, + 56, -24, -24, 50, -24, 53, 69, -24, -3, -24, + -24, -24, -24, -24, -24, -24, -24, -24, 59, -24, + 82, 76, 71, -23, 120, -24, -1, 122, -24, 114, + -24, -24, -24, -24, -24, -24, -24, -24, -24, 116, + -24, 117, 124, 121, 125, 126, -24, -24, -24, -24, + -24, -24, 123, -24, 145, 130, -24, -10, -24, -24, + -24, 127, -24, 146, 0, -24, -24, 160, -24, 165, + -24 }; /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM. @@ -783,40 +803,42 @@ static const yytype_int16 yypact[] = means the default is an error. */ static const yytype_int8 yydefact[] = { - 2, 13, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, - 42, 43, 44, 45, 46, 47, 48, 49, 0, 0, - 50, 0, 60, 0, 0, 3, 4, 8, 9, 5, - 6, 7, 12, 10, 11, 0, 0, 0, 0, 0, - 0, 1, 0, 0, 52, 0, 62, 0, 79, 80, - 0, 72, 0, 0, 88, 0, 68, 74, 69, 51, - 54, 53, 90, 64, 0, 63, 0, 0, 0, 0, - 0, 61, 0, 0, 56, 57, 94, 89, 91, 92, - 67, 65, 81, 82, 83, 0, 73, 0, 0, 0, - 0, 0, 75, 70, 59, 58, 55, 95, 0, 66, - 0, 0, 93, 0, 71, 84, 85, 0, 76, 0, - 0, 86, 87, 0, 77, 0, 78 + 2, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, 74, 73, + 76, 75, 78, 77, 70, 71, 72, 0, 0, 51, + 0, 61, 0, 0, 0, 3, 4, 9, 10, 5, + 6, 7, 8, 13, 11, 12, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 53, 0, 63, 0, + 0, 90, 91, 0, 83, 0, 0, 99, 0, 69, + 79, 85, 80, 52, 55, 54, 101, 65, 0, 64, + 0, 0, 0, 0, 0, 62, 0, 0, 57, 58, + 105, 100, 102, 103, 68, 66, 92, 93, 94, 0, + 84, 0, 0, 0, 0, 0, 86, 81, 60, 59, + 56, 106, 0, 67, 0, 0, 104, 0, 82, 95, + 96, 0, 87, 0, 0, 97, 98, 0, 88, 0, + 89 }; /* YYPGOTO[NTERM-NUM]. */ -static const yytype_int8 yypgoto[] = +static const yytype_int16 yypgoto[] = { - -25, -25, -15, -25, 117, -25, -25, -25, -25, -25, - -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25, -25, -25, -25, -25, -25, -25, -25, - -25, -25, -25 + -24, -24, -19, -24, 170, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24, -24, -24, -24, -24, -24, -24, + -24, -24, -24, -24 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_uint8 yydefgoto[] = { - 0, 44, 45, 46, 47, 48, 49, 57, 73, 81, - 88, 95, 109, 115, 50, 59, 75, 85, 90, 111, - 101, 51, 52, 87, 121, 72, 107, 53, 86, 120, - 129, 135, 70, 105, 127, 133, 54, 82, 89, 98, - 110, 99, 118 + 0, 54, 55, 56, 57, 58, 59, 68, 86, 95, + 102, 109, 123, 129, 60, 70, 88, 99, 104, 125, + 115, 61, 62, 63, 101, 135, 85, 121, 64, 100, + 134, 143, 149, 83, 119, 141, 147, 65, 96, 103, + 112, 124, 113, 132 }; /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If @@ -827,24 +849,27 @@ static const yytype_uint8 yytable[] = 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32, 33, 34, 35, 36, 37, 38, 55, 96, - 56, 68, 97, 125, 126, 67, 102, 103, 104, 58, - 39, 60, 61, 40, 41, 42, 43, 69, 80, 62, - 84, 83, 1, 2, 3, 4, 5, 6, 7, 8, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 110, 139, 140, + 111, 66, 79, 80, 116, 117, 118, 67, 69, 48, + 145, 146, 49, 50, 51, 52, 53, 94, 71, 98, + 72, 97, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, - 131, 132, 63, 64, 66, 71, 74, 77, 76, 91, - 78, 92, 39, 93, 94, 40, 41, 42, 43, 108, - 119, 100, 79, 1, 2, 3, 4, 5, 6, 7, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 73, + 74, 75, 81, 76, 78, 84, 87, 91, 89, 90, + 92, 48, 105, 106, 49, 50, 51, 52, 53, 82, + 107, 108, 93, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 106, 112, 113, 114, 116, 117, 122, 123, 124, - 130, 128, 136, 39, 134, 65, 40, 41, 42, 43, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 122, 114, 120, 126, 127, 128, 131, 137, 130, 144, + 136, 133, 48, 138, 142, 49, 50, 51, 52, 53, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, - 21, 22, 23, 24, 25, 26, 27 + 21, 22, 23, 24, 25, 26, 27, 148, 150, 77 }; static const yytype_int8 yycheck[] = @@ -852,24 +877,27 @@ static const yytype_int8 yycheck[] = 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, - 33, 34, 35, 36, 37, 38, 39, 40, 62, 60, - 62, 45, 63, 49, 50, 60, 46, 47, 48, 62, - 53, 62, 0, 56, 57, 58, 59, 61, 73, 41, - 75, 64, 3, 4, 5, 6, 7, 8, 9, 10, + 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 70, 58, 59, + 73, 72, 71, 72, 55, 56, 57, 72, 72, 62, + 60, 61, 65, 66, 67, 68, 69, 86, 72, 88, + 72, 74, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, - 51, 52, 54, 62, 62, 61, 67, 67, 63, 63, - 67, 42, 53, 55, 60, 56, 57, 58, 59, 66, - 65, 61, 63, 3, 4, 5, 6, 7, 8, 9, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 0, + 50, 63, 54, 72, 72, 71, 77, 77, 73, 73, + 77, 62, 73, 51, 65, 66, 67, 68, 69, 71, + 64, 70, 73, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, - 40, 60, 67, 67, 61, 67, 61, 67, 43, 63, - 44, 67, 63, 53, 67, 58, 56, 57, 58, 59, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, + 76, 71, 70, 77, 77, 71, 71, 52, 77, 53, + 77, 75, 62, 73, 77, 65, 66, 67, 68, 69, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, - 23, 24, 25, 26, 27, 28, 29 + 23, 24, 25, 26, 27, 28, 29, 77, 73, 69 }; /* YYSTOS[STATE-NUM] -- The symbol kind of the accessing symbol of @@ -879,32 +907,35 @@ static const yytype_int8 yystos[] = 0, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, 40, 53, - 56, 57, 58, 59, 69, 70, 71, 72, 73, 74, - 82, 89, 90, 95, 104, 62, 62, 75, 62, 83, - 62, 0, 41, 54, 62, 72, 62, 70, 45, 61, - 100, 61, 93, 76, 67, 84, 63, 67, 67, 63, - 70, 77, 105, 64, 70, 85, 96, 91, 78, 106, - 86, 63, 42, 55, 60, 79, 60, 63, 107, 109, - 61, 88, 46, 47, 48, 101, 60, 94, 66, 80, - 108, 87, 67, 67, 61, 81, 67, 61, 110, 65, - 97, 92, 67, 43, 63, 49, 50, 102, 67, 98, - 44, 51, 52, 103, 67, 99, 63 + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 62, 65, + 66, 67, 68, 69, 79, 80, 81, 82, 83, 84, + 92, 99, 100, 101, 106, 115, 72, 72, 85, 72, + 93, 72, 72, 0, 50, 63, 72, 82, 72, 80, + 80, 54, 71, 111, 71, 104, 86, 77, 94, 73, + 73, 77, 77, 73, 80, 87, 116, 74, 80, 95, + 107, 102, 88, 117, 96, 73, 51, 64, 70, 89, + 70, 73, 118, 120, 71, 98, 55, 56, 57, 112, + 70, 105, 76, 90, 119, 97, 77, 77, 71, 91, + 77, 71, 121, 75, 108, 103, 77, 52, 73, 58, + 59, 113, 77, 109, 53, 60, 61, 114, 77, 110, + 73 }; /* YYR1[RULE-NUM] -- Symbol kind of the left-hand side of rule RULE-NUM. */ static const yytype_int8 yyr1[] = { - 0, 68, 69, 69, 70, 70, 70, 70, 71, 71, - 71, 71, 71, 72, 72, 72, 72, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, - 75, 74, 76, 76, 78, 77, 79, 80, 80, 81, - 83, 82, 84, 84, 86, 87, 85, 88, 89, 91, - 92, 90, 93, 94, 96, 97, 98, 99, 95, 100, - 100, 101, 101, 101, 102, 102, 103, 103, 105, 104, - 106, 106, 108, 107, 109, 110 + 0, 78, 79, 79, 80, 80, 80, 80, 80, 81, + 81, 81, 81, 81, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 83, 83, 83, 83, 83, 83, 83, 83, 83, + 83, 85, 84, 86, 86, 88, 87, 89, 90, 90, + 91, 93, 92, 94, 94, 96, 97, 95, 98, 99, + 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, + 102, 103, 101, 104, 105, 107, 108, 109, 110, 106, + 111, 111, 112, 112, 112, 113, 113, 114, 114, 116, + 115, 117, 117, 119, 118, 120, 121 }; /* YYR2[RULE-NUM] -- Number of symbols on the right-hand side of rule RULE-NUM. */ @@ -915,11 +946,12 @@ static const yytype_int8 yyr2[] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 5, 0, 2, 0, 5, 1, 0, 2, 1, - 0, 6, 0, 2, 0, 0, 5, 1, 4, 0, - 0, 11, 1, 1, 0, 0, 0, 0, 19, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 7, - 0, 2, 0, 4, 1, 1 + 1, 0, 5, 0, 2, 0, 5, 1, 0, 2, + 1, 0, 6, 0, 2, 0, 0, 5, 1, 4, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 0, 0, 11, 1, 1, 0, 0, 0, 0, 19, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 7, 0, 2, 0, 4, 1, 1 }; @@ -1383,263 +1415,263 @@ yyparse (void) switch (yyn) { case 2: /* start: %empty */ -#line 102 "hl/src//H5LTparse.y" +#line 108 "hl/src//H5LTparse.y" { memset(arr_stack, 0, STACK_SIZE*sizeof(struct arr_info)); /*initialize here?*/ } -#line 1360 "hl/src//H5LTparse.c" +#line 1392 "hl/src//H5LTparse.c" break; case 3: /* start: ddl_type */ -#line 103 "hl/src//H5LTparse.y" +#line 109 "hl/src//H5LTparse.y" { return (yyval.hid);} -#line 1366 "hl/src//H5LTparse.c" +#line 1398 "hl/src//H5LTparse.c" break; - case 13: /* integer_type: H5T_STD_I8BE_TOKEN */ -#line 117 "hl/src//H5LTparse.y" + case 14: /* integer_type: H5T_STD_I8BE_TOKEN */ +#line 124 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I8BE); } -#line 1372 "hl/src//H5LTparse.c" +#line 1404 "hl/src//H5LTparse.c" break; - case 14: /* integer_type: H5T_STD_I8LE_TOKEN */ -#line 118 "hl/src//H5LTparse.y" + case 15: /* integer_type: H5T_STD_I8LE_TOKEN */ +#line 125 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I8LE); } -#line 1378 "hl/src//H5LTparse.c" +#line 1410 "hl/src//H5LTparse.c" break; - case 15: /* integer_type: H5T_STD_I16BE_TOKEN */ -#line 119 "hl/src//H5LTparse.y" + case 16: /* integer_type: H5T_STD_I16BE_TOKEN */ +#line 126 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I16BE); } -#line 1384 "hl/src//H5LTparse.c" +#line 1416 "hl/src//H5LTparse.c" break; - case 16: /* integer_type: H5T_STD_I16LE_TOKEN */ -#line 120 "hl/src//H5LTparse.y" + case 17: /* integer_type: H5T_STD_I16LE_TOKEN */ +#line 127 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I16LE); } -#line 1390 "hl/src//H5LTparse.c" +#line 1422 "hl/src//H5LTparse.c" break; - case 17: /* integer_type: H5T_STD_I32BE_TOKEN */ -#line 121 "hl/src//H5LTparse.y" + case 18: /* integer_type: H5T_STD_I32BE_TOKEN */ +#line 128 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I32BE); } -#line 1396 "hl/src//H5LTparse.c" +#line 1428 "hl/src//H5LTparse.c" break; - case 18: /* integer_type: H5T_STD_I32LE_TOKEN */ -#line 122 "hl/src//H5LTparse.y" + case 19: /* integer_type: H5T_STD_I32LE_TOKEN */ +#line 129 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I32LE); } -#line 1402 "hl/src//H5LTparse.c" +#line 1434 "hl/src//H5LTparse.c" break; - case 19: /* integer_type: H5T_STD_I64BE_TOKEN */ -#line 123 "hl/src//H5LTparse.y" + case 20: /* integer_type: H5T_STD_I64BE_TOKEN */ +#line 130 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I64BE); } -#line 1408 "hl/src//H5LTparse.c" +#line 1440 "hl/src//H5LTparse.c" break; - case 20: /* integer_type: H5T_STD_I64LE_TOKEN */ -#line 124 "hl/src//H5LTparse.y" + case 21: /* integer_type: H5T_STD_I64LE_TOKEN */ +#line 131 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_I64LE); } -#line 1414 "hl/src//H5LTparse.c" +#line 1446 "hl/src//H5LTparse.c" break; - case 21: /* integer_type: H5T_STD_U8BE_TOKEN */ -#line 125 "hl/src//H5LTparse.y" + case 22: /* integer_type: H5T_STD_U8BE_TOKEN */ +#line 132 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U8BE); } -#line 1420 "hl/src//H5LTparse.c" +#line 1452 "hl/src//H5LTparse.c" break; - case 22: /* integer_type: H5T_STD_U8LE_TOKEN */ -#line 126 "hl/src//H5LTparse.y" + case 23: /* integer_type: H5T_STD_U8LE_TOKEN */ +#line 133 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U8LE); } -#line 1426 "hl/src//H5LTparse.c" +#line 1458 "hl/src//H5LTparse.c" break; - case 23: /* integer_type: H5T_STD_U16BE_TOKEN */ -#line 127 "hl/src//H5LTparse.y" + case 24: /* integer_type: H5T_STD_U16BE_TOKEN */ +#line 134 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U16BE); } -#line 1432 "hl/src//H5LTparse.c" +#line 1464 "hl/src//H5LTparse.c" break; - case 24: /* integer_type: H5T_STD_U16LE_TOKEN */ -#line 128 "hl/src//H5LTparse.y" + case 25: /* integer_type: H5T_STD_U16LE_TOKEN */ +#line 135 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U16LE); } -#line 1438 "hl/src//H5LTparse.c" +#line 1470 "hl/src//H5LTparse.c" break; - case 25: /* integer_type: H5T_STD_U32BE_TOKEN */ -#line 129 "hl/src//H5LTparse.y" + case 26: /* integer_type: H5T_STD_U32BE_TOKEN */ +#line 136 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U32BE); } -#line 1444 "hl/src//H5LTparse.c" +#line 1476 "hl/src//H5LTparse.c" break; - case 26: /* integer_type: H5T_STD_U32LE_TOKEN */ -#line 130 "hl/src//H5LTparse.y" + case 27: /* integer_type: H5T_STD_U32LE_TOKEN */ +#line 137 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U32LE); } -#line 1450 "hl/src//H5LTparse.c" +#line 1482 "hl/src//H5LTparse.c" break; - case 27: /* integer_type: H5T_STD_U64BE_TOKEN */ -#line 131 "hl/src//H5LTparse.y" + case 28: /* integer_type: H5T_STD_U64BE_TOKEN */ +#line 138 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U64BE); } -#line 1456 "hl/src//H5LTparse.c" +#line 1488 "hl/src//H5LTparse.c" break; - case 28: /* integer_type: H5T_STD_U64LE_TOKEN */ -#line 132 "hl/src//H5LTparse.y" + case 29: /* integer_type: H5T_STD_U64LE_TOKEN */ +#line 139 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_STD_U64LE); } -#line 1462 "hl/src//H5LTparse.c" +#line 1494 "hl/src//H5LTparse.c" break; - case 29: /* integer_type: H5T_NATIVE_CHAR_TOKEN */ -#line 133 "hl/src//H5LTparse.y" + case 30: /* integer_type: H5T_NATIVE_CHAR_TOKEN */ +#line 140 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_CHAR); } -#line 1468 "hl/src//H5LTparse.c" +#line 1500 "hl/src//H5LTparse.c" break; - case 30: /* integer_type: H5T_NATIVE_SCHAR_TOKEN */ -#line 134 "hl/src//H5LTparse.y" + case 31: /* integer_type: H5T_NATIVE_SCHAR_TOKEN */ +#line 141 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_SCHAR); } -#line 1474 "hl/src//H5LTparse.c" +#line 1506 "hl/src//H5LTparse.c" break; - case 31: /* integer_type: H5T_NATIVE_UCHAR_TOKEN */ -#line 135 "hl/src//H5LTparse.y" + case 32: /* integer_type: H5T_NATIVE_UCHAR_TOKEN */ +#line 142 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_UCHAR); } -#line 1480 "hl/src//H5LTparse.c" +#line 1512 "hl/src//H5LTparse.c" break; - case 32: /* integer_type: H5T_NATIVE_SHORT_TOKEN */ -#line 136 "hl/src//H5LTparse.y" + case 33: /* integer_type: H5T_NATIVE_SHORT_TOKEN */ +#line 143 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_SHORT); } -#line 1486 "hl/src//H5LTparse.c" +#line 1518 "hl/src//H5LTparse.c" break; - case 33: /* integer_type: H5T_NATIVE_USHORT_TOKEN */ -#line 137 "hl/src//H5LTparse.y" + case 34: /* integer_type: H5T_NATIVE_USHORT_TOKEN */ +#line 144 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_USHORT); } -#line 1492 "hl/src//H5LTparse.c" +#line 1524 "hl/src//H5LTparse.c" break; - case 34: /* integer_type: H5T_NATIVE_INT_TOKEN */ -#line 138 "hl/src//H5LTparse.y" + case 35: /* integer_type: H5T_NATIVE_INT_TOKEN */ +#line 145 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_INT); } -#line 1498 "hl/src//H5LTparse.c" +#line 1530 "hl/src//H5LTparse.c" break; - case 35: /* integer_type: H5T_NATIVE_UINT_TOKEN */ -#line 139 "hl/src//H5LTparse.y" + case 36: /* integer_type: H5T_NATIVE_UINT_TOKEN */ +#line 146 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_UINT); } -#line 1504 "hl/src//H5LTparse.c" +#line 1536 "hl/src//H5LTparse.c" break; - case 36: /* integer_type: H5T_NATIVE_LONG_TOKEN */ -#line 140 "hl/src//H5LTparse.y" + case 37: /* integer_type: H5T_NATIVE_LONG_TOKEN */ +#line 147 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_LONG); } -#line 1510 "hl/src//H5LTparse.c" +#line 1542 "hl/src//H5LTparse.c" break; - case 37: /* integer_type: H5T_NATIVE_ULONG_TOKEN */ -#line 141 "hl/src//H5LTparse.y" + case 38: /* integer_type: H5T_NATIVE_ULONG_TOKEN */ +#line 148 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_ULONG); } -#line 1516 "hl/src//H5LTparse.c" +#line 1548 "hl/src//H5LTparse.c" break; - case 38: /* integer_type: H5T_NATIVE_LLONG_TOKEN */ -#line 142 "hl/src//H5LTparse.y" + case 39: /* integer_type: H5T_NATIVE_LLONG_TOKEN */ +#line 149 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_LLONG); } -#line 1522 "hl/src//H5LTparse.c" +#line 1554 "hl/src//H5LTparse.c" break; - case 39: /* integer_type: H5T_NATIVE_ULLONG_TOKEN */ -#line 143 "hl/src//H5LTparse.y" + case 40: /* integer_type: H5T_NATIVE_ULLONG_TOKEN */ +#line 150 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_ULLONG); } -#line 1528 "hl/src//H5LTparse.c" +#line 1560 "hl/src//H5LTparse.c" break; - case 40: /* fp_type: H5T_IEEE_F16BE_TOKEN */ -#line 146 "hl/src//H5LTparse.y" + case 41: /* fp_type: H5T_IEEE_F16BE_TOKEN */ +#line 153 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_IEEE_F16BE); } -#line 1534 "hl/src//H5LTparse.c" +#line 1566 "hl/src//H5LTparse.c" break; - case 41: /* fp_type: H5T_IEEE_F16LE_TOKEN */ -#line 147 "hl/src//H5LTparse.y" + case 42: /* fp_type: H5T_IEEE_F16LE_TOKEN */ +#line 154 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_IEEE_F16LE); } -#line 1540 "hl/src//H5LTparse.c" +#line 1572 "hl/src//H5LTparse.c" break; - case 42: /* fp_type: H5T_IEEE_F32BE_TOKEN */ -#line 148 "hl/src//H5LTparse.y" + case 43: /* fp_type: H5T_IEEE_F32BE_TOKEN */ +#line 155 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_IEEE_F32BE); } -#line 1546 "hl/src//H5LTparse.c" +#line 1578 "hl/src//H5LTparse.c" break; - case 43: /* fp_type: H5T_IEEE_F32LE_TOKEN */ -#line 149 "hl/src//H5LTparse.y" + case 44: /* fp_type: H5T_IEEE_F32LE_TOKEN */ +#line 156 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_IEEE_F32LE); } -#line 1552 "hl/src//H5LTparse.c" +#line 1584 "hl/src//H5LTparse.c" break; - case 44: /* fp_type: H5T_IEEE_F64BE_TOKEN */ -#line 150 "hl/src//H5LTparse.y" + case 45: /* fp_type: H5T_IEEE_F64BE_TOKEN */ +#line 157 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_IEEE_F64BE); } -#line 1558 "hl/src//H5LTparse.c" +#line 1590 "hl/src//H5LTparse.c" break; - case 45: /* fp_type: H5T_IEEE_F64LE_TOKEN */ -#line 151 "hl/src//H5LTparse.y" + case 46: /* fp_type: H5T_IEEE_F64LE_TOKEN */ +#line 158 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_IEEE_F64LE); } -#line 1564 "hl/src//H5LTparse.c" +#line 1596 "hl/src//H5LTparse.c" break; - case 46: /* fp_type: H5T_NATIVE_FLOAT16_TOKEN */ -#line 152 "hl/src//H5LTparse.y" + case 47: /* fp_type: H5T_NATIVE_FLOAT16_TOKEN */ +#line 159 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_FLOAT16); } -#line 1570 "hl/src//H5LTparse.c" +#line 1602 "hl/src//H5LTparse.c" break; - case 47: /* fp_type: H5T_NATIVE_FLOAT_TOKEN */ -#line 153 "hl/src//H5LTparse.y" + case 48: /* fp_type: H5T_NATIVE_FLOAT_TOKEN */ +#line 160 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_FLOAT); } -#line 1576 "hl/src//H5LTparse.c" +#line 1608 "hl/src//H5LTparse.c" break; - case 48: /* fp_type: H5T_NATIVE_DOUBLE_TOKEN */ -#line 154 "hl/src//H5LTparse.y" + case 49: /* fp_type: H5T_NATIVE_DOUBLE_TOKEN */ +#line 161 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_DOUBLE); } -#line 1582 "hl/src//H5LTparse.c" +#line 1614 "hl/src//H5LTparse.c" break; - case 49: /* fp_type: H5T_NATIVE_LDOUBLE_TOKEN */ -#line 155 "hl/src//H5LTparse.y" + case 50: /* fp_type: H5T_NATIVE_LDOUBLE_TOKEN */ +#line 162 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tcopy(H5T_NATIVE_LDOUBLE); } -#line 1588 "hl/src//H5LTparse.c" +#line 1620 "hl/src//H5LTparse.c" break; - case 50: /* $@1: %empty */ -#line 159 "hl/src//H5LTparse.y" + case 51: /* $@1: %empty */ +#line 166 "hl/src//H5LTparse.y" { csindex++; cmpd_stack[csindex].id = H5Tcreate(H5T_COMPOUND, 1); /*temporarily set size to 1*/ } -#line 1594 "hl/src//H5LTparse.c" +#line 1626 "hl/src//H5LTparse.c" break; - case 51: /* compound_type: H5T_COMPOUND_TOKEN $@1 '{' memb_list '}' */ -#line 161 "hl/src//H5LTparse.y" + case 52: /* compound_type: H5T_COMPOUND_TOKEN $@1 '{' memb_list '}' */ +#line 168 "hl/src//H5LTparse.y" { (yyval.hid) = cmpd_stack[csindex].id; cmpd_stack[csindex].id = 0; cmpd_stack[csindex].first_memb = 1; csindex--; } -#line 1604 "hl/src//H5LTparse.c" +#line 1636 "hl/src//H5LTparse.c" break; - case 54: /* $@2: %empty */ -#line 170 "hl/src//H5LTparse.y" + case 55: /* $@2: %empty */ +#line 177 "hl/src//H5LTparse.y" { cmpd_stack[csindex].is_field = 1; /*notify lexer a compound member is parsed*/ } -#line 1610 "hl/src//H5LTparse.c" +#line 1642 "hl/src//H5LTparse.c" break; - case 55: /* memb_def: ddl_type $@2 field_name field_offset ';' */ -#line 172 "hl/src//H5LTparse.y" + case 56: /* memb_def: ddl_type $@2 field_name field_offset ';' */ +#line 179 "hl/src//H5LTparse.y" { size_t origin_size, new_size; hid_t dtype_id = cmpd_stack[csindex].id; @@ -1674,108 +1706,168 @@ yyparse (void) new_size = H5Tget_size(dtype_id); } -#line 1649 "hl/src//H5LTparse.c" +#line 1681 "hl/src//H5LTparse.c" break; - case 56: /* field_name: STRING */ -#line 208 "hl/src//H5LTparse.y" + case 57: /* field_name: STRING */ +#line 215 "hl/src//H5LTparse.y" { (yyval.sval) = strdup(yylval.sval); free(yylval.sval); yylval.sval = NULL; } -#line 1659 "hl/src//H5LTparse.c" +#line 1691 "hl/src//H5LTparse.c" break; - case 57: /* field_offset: %empty */ -#line 215 "hl/src//H5LTparse.y" + case 58: /* field_offset: %empty */ +#line 222 "hl/src//H5LTparse.y" { (yyval.ival) = 0; } -#line 1665 "hl/src//H5LTparse.c" +#line 1697 "hl/src//H5LTparse.c" break; - case 58: /* field_offset: ':' offset */ -#line 217 "hl/src//H5LTparse.y" + case 59: /* field_offset: ':' offset */ +#line 224 "hl/src//H5LTparse.y" { (yyval.ival) = yylval.ival; } -#line 1671 "hl/src//H5LTparse.c" +#line 1703 "hl/src//H5LTparse.c" break; - case 60: /* $@3: %empty */ -#line 221 "hl/src//H5LTparse.y" + case 61: /* $@3: %empty */ +#line 228 "hl/src//H5LTparse.y" { asindex++; /*pushd onto the stack*/ } -#line 1677 "hl/src//H5LTparse.c" +#line 1709 "hl/src//H5LTparse.c" break; - case 61: /* array_type: H5T_ARRAY_TOKEN $@3 '{' dim_list ddl_type '}' */ -#line 223 "hl/src//H5LTparse.y" + case 62: /* array_type: H5T_ARRAY_TOKEN $@3 '{' dim_list ddl_type '}' */ +#line 230 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tarray_create2((yyvsp[-1].hid), arr_stack[asindex].ndims, arr_stack[asindex].dims); arr_stack[asindex].ndims = 0; asindex--; H5Tclose((yyvsp[-1].hid)); } -#line 1688 "hl/src//H5LTparse.c" +#line 1720 "hl/src//H5LTparse.c" break; - case 64: /* $@4: %empty */ -#line 233 "hl/src//H5LTparse.y" + case 65: /* $@4: %empty */ +#line 240 "hl/src//H5LTparse.y" { arr_stack[asindex].is_dim = 1; /*notice lexer of dimension size*/ } -#line 1694 "hl/src//H5LTparse.c" +#line 1726 "hl/src//H5LTparse.c" break; - case 65: /* $@5: %empty */ -#line 234 "hl/src//H5LTparse.y" + case 66: /* $@5: %empty */ +#line 241 "hl/src//H5LTparse.y" { unsigned ndims = arr_stack[asindex].ndims; arr_stack[asindex].dims[ndims] = (hsize_t)yylval.ival; arr_stack[asindex].ndims++; arr_stack[asindex].is_dim = 0; } -#line 1704 "hl/src//H5LTparse.c" +#line 1736 "hl/src//H5LTparse.c" break; - case 68: /* vlen_type: H5T_VLEN_TOKEN '{' ddl_type '}' */ -#line 245 "hl/src//H5LTparse.y" + case 69: /* vlen_type: H5T_VLEN_TOKEN '{' ddl_type '}' */ +#line 252 "hl/src//H5LTparse.y" { (yyval.hid) = H5Tvlen_create((yyvsp[-1].hid)); H5Tclose((yyvsp[-1].hid)); } -#line 1710 "hl/src//H5LTparse.c" +#line 1742 "hl/src//H5LTparse.c" + break; + + case 70: /* complex_type: H5T_NATIVE_FLOAT_COMPLEX_TOKEN */ +#line 255 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_NATIVE_FLOAT_COMPLEX); } +#line 1748 "hl/src//H5LTparse.c" + break; + + case 71: /* complex_type: H5T_NATIVE_DOUBLE_COMPLEX_TOKEN */ +#line 256 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_NATIVE_DOUBLE_COMPLEX); } +#line 1754 "hl/src//H5LTparse.c" + break; + + case 72: /* complex_type: H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN */ +#line 257 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_NATIVE_LDOUBLE_COMPLEX); } +#line 1760 "hl/src//H5LTparse.c" + break; + + case 73: /* complex_type: H5T_COMPLEX_IEEE_F16LE_TOKEN */ +#line 258 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_COMPLEX_IEEE_F16LE); } +#line 1766 "hl/src//H5LTparse.c" + break; + + case 74: /* complex_type: H5T_COMPLEX_IEEE_F16BE_TOKEN */ +#line 259 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_COMPLEX_IEEE_F16BE); } +#line 1772 "hl/src//H5LTparse.c" break; - case 69: /* @6: %empty */ -#line 251 "hl/src//H5LTparse.y" + case 75: /* complex_type: H5T_COMPLEX_IEEE_F32LE_TOKEN */ +#line 260 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_COMPLEX_IEEE_F32LE); } +#line 1778 "hl/src//H5LTparse.c" + break; + + case 76: /* complex_type: H5T_COMPLEX_IEEE_F32BE_TOKEN */ +#line 261 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_COMPLEX_IEEE_F32BE); } +#line 1784 "hl/src//H5LTparse.c" + break; + + case 77: /* complex_type: H5T_COMPLEX_IEEE_F64LE_TOKEN */ +#line 262 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_COMPLEX_IEEE_F64LE); } +#line 1790 "hl/src//H5LTparse.c" + break; + + case 78: /* complex_type: H5T_COMPLEX_IEEE_F64BE_TOKEN */ +#line 263 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_COMPLEX_IEEE_F64BE); } +#line 1796 "hl/src//H5LTparse.c" + break; + + case 79: /* complex_type: H5T_COMPLEX_TOKEN '{' ddl_type '}' */ +#line 265 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcomplex_create((yyvsp[-1].hid)); H5Tclose((yyvsp[-1].hid)); } +#line 1802 "hl/src//H5LTparse.c" + break; + + case 80: /* @6: %empty */ +#line 271 "hl/src//H5LTparse.y" { size_t size = (size_t)yylval.ival; (yyval.hid) = H5Tcreate(H5T_OPAQUE, size); } -#line 1719 "hl/src//H5LTparse.c" +#line 1811 "hl/src//H5LTparse.c" break; - case 70: /* $@7: %empty */ -#line 256 "hl/src//H5LTparse.y" + case 81: /* $@7: %empty */ +#line 276 "hl/src//H5LTparse.y" { H5Tset_tag((yyvsp[-3].hid), yylval.sval); free(yylval.sval); yylval.sval = NULL; } -#line 1729 "hl/src//H5LTparse.c" +#line 1821 "hl/src//H5LTparse.c" break; - case 71: /* opaque_type: H5T_OPAQUE_TOKEN '{' OPQ_SIZE_TOKEN opaque_size ';' @6 OPQ_TAG_TOKEN opaque_tag ';' $@7 '}' */ -#line 261 "hl/src//H5LTparse.y" + case 82: /* opaque_type: H5T_OPAQUE_TOKEN '{' OPQ_SIZE_TOKEN opaque_size ';' @6 OPQ_TAG_TOKEN opaque_tag ';' $@7 '}' */ +#line 281 "hl/src//H5LTparse.y" { (yyval.hid) = (yyvsp[-5].hid); } -#line 1735 "hl/src//H5LTparse.c" +#line 1827 "hl/src//H5LTparse.c" break; - case 74: /* $@8: %empty */ -#line 270 "hl/src//H5LTparse.y" + case 85: /* $@8: %empty */ +#line 290 "hl/src//H5LTparse.y" { if((yyvsp[-1].ival) == H5T_VARIABLE_TOKEN) is_variable = 1; else str_size = yylval.ival; } -#line 1746 "hl/src//H5LTparse.c" +#line 1838 "hl/src//H5LTparse.c" break; - case 75: /* $@9: %empty */ -#line 277 "hl/src//H5LTparse.y" + case 86: /* $@9: %empty */ +#line 297 "hl/src//H5LTparse.y" { if((yyvsp[-1].ival) == H5T_STR_NULLTERM_TOKEN) str_pad = H5T_STR_NULLTERM; @@ -1784,33 +1876,33 @@ yyparse (void) else if((yyvsp[-1].ival) == H5T_STR_SPACEPAD_TOKEN) str_pad = H5T_STR_SPACEPAD; } -#line 1759 "hl/src//H5LTparse.c" +#line 1851 "hl/src//H5LTparse.c" break; - case 76: /* $@10: %empty */ -#line 286 "hl/src//H5LTparse.y" + case 87: /* $@10: %empty */ +#line 306 "hl/src//H5LTparse.y" { if((yyvsp[-1].ival) == H5T_CSET_ASCII_TOKEN) str_cset = H5T_CSET_ASCII; else if((yyvsp[-1].ival) == H5T_CSET_UTF8_TOKEN) str_cset = H5T_CSET_UTF8; } -#line 1770 "hl/src//H5LTparse.c" +#line 1862 "hl/src//H5LTparse.c" break; - case 77: /* @11: %empty */ -#line 293 "hl/src//H5LTparse.y" + case 88: /* @11: %empty */ +#line 313 "hl/src//H5LTparse.y" { if((yyvsp[-1].hid) == H5T_C_S1_TOKEN) (yyval.hid) = H5Tcopy(H5T_C_S1); else if((yyvsp[-1].hid) == H5T_FORTRAN_S1_TOKEN) (yyval.hid) = H5Tcopy(H5T_FORTRAN_S1); } -#line 1781 "hl/src//H5LTparse.c" +#line 1873 "hl/src//H5LTparse.c" break; - case 78: /* string_type: H5T_STRING_TOKEN '{' STRSIZE_TOKEN strsize ';' $@8 STRPAD_TOKEN strpad ';' $@9 CSET_TOKEN cset ';' $@10 CTYPE_TOKEN ctype ';' @11 '}' */ -#line 300 "hl/src//H5LTparse.y" + case 89: /* string_type: H5T_STRING_TOKEN '{' STRSIZE_TOKEN strsize ';' $@8 STRPAD_TOKEN strpad ';' $@9 CSET_TOKEN cset ';' $@10 CTYPE_TOKEN ctype ';' @11 '}' */ +#line 320 "hl/src//H5LTparse.y" { hid_t str_id = (yyvsp[-1].hid); @@ -1827,82 +1919,82 @@ yyparse (void) (yyval.hid) = str_id; } -#line 1802 "hl/src//H5LTparse.c" +#line 1894 "hl/src//H5LTparse.c" break; - case 79: /* strsize: H5T_VARIABLE_TOKEN */ -#line 317 "hl/src//H5LTparse.y" + case 90: /* strsize: H5T_VARIABLE_TOKEN */ +#line 337 "hl/src//H5LTparse.y" {(yyval.ival) = H5T_VARIABLE_TOKEN;} -#line 1808 "hl/src//H5LTparse.c" +#line 1900 "hl/src//H5LTparse.c" break; - case 81: /* strpad: H5T_STR_NULLTERM_TOKEN */ -#line 320 "hl/src//H5LTparse.y" + case 92: /* strpad: H5T_STR_NULLTERM_TOKEN */ +#line 340 "hl/src//H5LTparse.y" {(yyval.ival) = H5T_STR_NULLTERM_TOKEN;} -#line 1814 "hl/src//H5LTparse.c" +#line 1906 "hl/src//H5LTparse.c" break; - case 82: /* strpad: H5T_STR_NULLPAD_TOKEN */ -#line 321 "hl/src//H5LTparse.y" + case 93: /* strpad: H5T_STR_NULLPAD_TOKEN */ +#line 341 "hl/src//H5LTparse.y" {(yyval.ival) = H5T_STR_NULLPAD_TOKEN;} -#line 1820 "hl/src//H5LTparse.c" +#line 1912 "hl/src//H5LTparse.c" break; - case 83: /* strpad: H5T_STR_SPACEPAD_TOKEN */ -#line 322 "hl/src//H5LTparse.y" + case 94: /* strpad: H5T_STR_SPACEPAD_TOKEN */ +#line 342 "hl/src//H5LTparse.y" {(yyval.ival) = H5T_STR_SPACEPAD_TOKEN;} -#line 1826 "hl/src//H5LTparse.c" +#line 1918 "hl/src//H5LTparse.c" break; - case 84: /* cset: H5T_CSET_ASCII_TOKEN */ -#line 324 "hl/src//H5LTparse.y" + case 95: /* cset: H5T_CSET_ASCII_TOKEN */ +#line 344 "hl/src//H5LTparse.y" {(yyval.ival) = H5T_CSET_ASCII_TOKEN;} -#line 1832 "hl/src//H5LTparse.c" +#line 1924 "hl/src//H5LTparse.c" break; - case 85: /* cset: H5T_CSET_UTF8_TOKEN */ -#line 325 "hl/src//H5LTparse.y" + case 96: /* cset: H5T_CSET_UTF8_TOKEN */ +#line 345 "hl/src//H5LTparse.y" {(yyval.ival) = H5T_CSET_UTF8_TOKEN;} -#line 1838 "hl/src//H5LTparse.c" +#line 1930 "hl/src//H5LTparse.c" break; - case 86: /* ctype: H5T_C_S1_TOKEN */ -#line 327 "hl/src//H5LTparse.y" + case 97: /* ctype: H5T_C_S1_TOKEN */ +#line 347 "hl/src//H5LTparse.y" {(yyval.hid) = H5T_C_S1_TOKEN;} -#line 1844 "hl/src//H5LTparse.c" +#line 1936 "hl/src//H5LTparse.c" break; - case 87: /* ctype: H5T_FORTRAN_S1_TOKEN */ -#line 328 "hl/src//H5LTparse.y" + case 98: /* ctype: H5T_FORTRAN_S1_TOKEN */ +#line 348 "hl/src//H5LTparse.y" {(yyval.hid) = H5T_FORTRAN_S1_TOKEN;} -#line 1850 "hl/src//H5LTparse.c" +#line 1942 "hl/src//H5LTparse.c" break; - case 88: /* $@12: %empty */ -#line 332 "hl/src//H5LTparse.y" + case 99: /* $@12: %empty */ +#line 352 "hl/src//H5LTparse.y" { is_enum = 1; enum_id = H5Tenum_create((yyvsp[-1].hid)); H5Tclose((yyvsp[-1].hid)); } -#line 1856 "hl/src//H5LTparse.c" +#line 1948 "hl/src//H5LTparse.c" break; - case 89: /* enum_type: H5T_ENUM_TOKEN '{' integer_type ';' $@12 enum_list '}' */ -#line 334 "hl/src//H5LTparse.y" + case 100: /* enum_type: H5T_ENUM_TOKEN '{' integer_type ';' $@12 enum_list '}' */ +#line 354 "hl/src//H5LTparse.y" { is_enum = 0; /*reset*/ (yyval.hid) = enum_id; } -#line 1862 "hl/src//H5LTparse.c" +#line 1954 "hl/src//H5LTparse.c" break; - case 92: /* $@13: %empty */ -#line 339 "hl/src//H5LTparse.y" + case 103: /* $@13: %empty */ +#line 359 "hl/src//H5LTparse.y" { is_enum_memb = 1; /*indicate member of enum*/ enum_memb_symbol = strdup(yylval.sval); free(yylval.sval); yylval.sval = NULL; } -#line 1873 "hl/src//H5LTparse.c" +#line 1965 "hl/src//H5LTparse.c" break; - case 93: /* enum_def: enum_symbol $@13 enum_val ';' */ -#line 346 "hl/src//H5LTparse.y" + case 104: /* enum_def: enum_symbol $@13 enum_val ';' */ +#line 366 "hl/src//H5LTparse.y" { char char_val=(char)yylval.ival; short short_val=(short)yylval.ival; @@ -1945,11 +2037,11 @@ yyparse (void) H5Tclose(super); H5Tclose(native); } -#line 1920 "hl/src//H5LTparse.c" +#line 2012 "hl/src//H5LTparse.c" break; -#line 1924 "hl/src//H5LTparse.c" +#line 2016 "hl/src//H5LTparse.c" default: break; } diff --git a/hl/src/H5LTparse.h b/hl/src/H5LTparse.h index be3c91f7fdb..0ac873895c3 100644 --- a/hl/src/H5LTparse.h +++ b/hl/src/H5LTparse.h @@ -91,28 +91,38 @@ extern int H5LTyydebug; H5T_NATIVE_FLOAT_TOKEN = 292, /* H5T_NATIVE_FLOAT_TOKEN */ H5T_NATIVE_DOUBLE_TOKEN = 293, /* H5T_NATIVE_DOUBLE_TOKEN */ H5T_NATIVE_LDOUBLE_TOKEN = 294, /* H5T_NATIVE_LDOUBLE_TOKEN */ - H5T_STRING_TOKEN = 295, /* H5T_STRING_TOKEN */ - STRSIZE_TOKEN = 296, /* STRSIZE_TOKEN */ - STRPAD_TOKEN = 297, /* STRPAD_TOKEN */ - CSET_TOKEN = 298, /* CSET_TOKEN */ - CTYPE_TOKEN = 299, /* CTYPE_TOKEN */ - H5T_VARIABLE_TOKEN = 300, /* H5T_VARIABLE_TOKEN */ - H5T_STR_NULLTERM_TOKEN = 301, /* H5T_STR_NULLTERM_TOKEN */ - H5T_STR_NULLPAD_TOKEN = 302, /* H5T_STR_NULLPAD_TOKEN */ - H5T_STR_SPACEPAD_TOKEN = 303, /* H5T_STR_SPACEPAD_TOKEN */ - H5T_CSET_ASCII_TOKEN = 304, /* H5T_CSET_ASCII_TOKEN */ - H5T_CSET_UTF8_TOKEN = 305, /* H5T_CSET_UTF8_TOKEN */ - H5T_C_S1_TOKEN = 306, /* H5T_C_S1_TOKEN */ - H5T_FORTRAN_S1_TOKEN = 307, /* H5T_FORTRAN_S1_TOKEN */ - H5T_OPAQUE_TOKEN = 308, /* H5T_OPAQUE_TOKEN */ - OPQ_SIZE_TOKEN = 309, /* OPQ_SIZE_TOKEN */ - OPQ_TAG_TOKEN = 310, /* OPQ_TAG_TOKEN */ - H5T_COMPOUND_TOKEN = 311, /* H5T_COMPOUND_TOKEN */ - H5T_ENUM_TOKEN = 312, /* H5T_ENUM_TOKEN */ - H5T_ARRAY_TOKEN = 313, /* H5T_ARRAY_TOKEN */ - H5T_VLEN_TOKEN = 314, /* H5T_VLEN_TOKEN */ - STRING = 315, /* STRING */ - NUMBER = 316 /* NUMBER */ + H5T_COMPLEX_IEEE_F16BE_TOKEN = 295, /* H5T_COMPLEX_IEEE_F16BE_TOKEN */ + H5T_COMPLEX_IEEE_F16LE_TOKEN = 296, /* H5T_COMPLEX_IEEE_F16LE_TOKEN */ + H5T_COMPLEX_IEEE_F32BE_TOKEN = 297, /* H5T_COMPLEX_IEEE_F32BE_TOKEN */ + H5T_COMPLEX_IEEE_F32LE_TOKEN = 298, /* H5T_COMPLEX_IEEE_F32LE_TOKEN */ + H5T_COMPLEX_IEEE_F64BE_TOKEN = 299, /* H5T_COMPLEX_IEEE_F64BE_TOKEN */ + H5T_COMPLEX_IEEE_F64LE_TOKEN = 300, /* H5T_COMPLEX_IEEE_F64LE_TOKEN */ + H5T_NATIVE_FLOAT_COMPLEX_TOKEN = 301, /* H5T_NATIVE_FLOAT_COMPLEX_TOKEN */ + H5T_NATIVE_DOUBLE_COMPLEX_TOKEN = 302, /* H5T_NATIVE_DOUBLE_COMPLEX_TOKEN */ + H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN = 303, /* H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN */ + H5T_STRING_TOKEN = 304, /* H5T_STRING_TOKEN */ + STRSIZE_TOKEN = 305, /* STRSIZE_TOKEN */ + STRPAD_TOKEN = 306, /* STRPAD_TOKEN */ + CSET_TOKEN = 307, /* CSET_TOKEN */ + CTYPE_TOKEN = 308, /* CTYPE_TOKEN */ + H5T_VARIABLE_TOKEN = 309, /* H5T_VARIABLE_TOKEN */ + H5T_STR_NULLTERM_TOKEN = 310, /* H5T_STR_NULLTERM_TOKEN */ + H5T_STR_NULLPAD_TOKEN = 311, /* H5T_STR_NULLPAD_TOKEN */ + H5T_STR_SPACEPAD_TOKEN = 312, /* H5T_STR_SPACEPAD_TOKEN */ + H5T_CSET_ASCII_TOKEN = 313, /* H5T_CSET_ASCII_TOKEN */ + H5T_CSET_UTF8_TOKEN = 314, /* H5T_CSET_UTF8_TOKEN */ + H5T_C_S1_TOKEN = 315, /* H5T_C_S1_TOKEN */ + H5T_FORTRAN_S1_TOKEN = 316, /* H5T_FORTRAN_S1_TOKEN */ + H5T_OPAQUE_TOKEN = 317, /* H5T_OPAQUE_TOKEN */ + OPQ_SIZE_TOKEN = 318, /* OPQ_SIZE_TOKEN */ + OPQ_TAG_TOKEN = 319, /* OPQ_TAG_TOKEN */ + H5T_COMPOUND_TOKEN = 320, /* H5T_COMPOUND_TOKEN */ + H5T_ENUM_TOKEN = 321, /* H5T_ENUM_TOKEN */ + H5T_ARRAY_TOKEN = 322, /* H5T_ARRAY_TOKEN */ + H5T_VLEN_TOKEN = 323, /* H5T_VLEN_TOKEN */ + H5T_COMPLEX_TOKEN = 324, /* H5T_COMPLEX_TOKEN */ + STRING = 325, /* STRING */ + NUMBER = 326 /* NUMBER */ }; typedef enum yytokentype yytoken_kind_t; #endif @@ -127,7 +137,7 @@ union YYSTYPE char *sval; /*for name string*/ hid_t hid; /*for hid_t token*/ -#line 131 "hl/src//H5LTparse.h" +#line 141 "hl/src//H5LTparse.h" }; typedef union YYSTYPE YYSTYPE; diff --git a/hl/src/H5LTparse.y b/hl/src/H5LTparse.y index 97132a1df66..2d36af73b0c 100644 --- a/hl/src/H5LTparse.y +++ b/hl/src/H5LTparse.y @@ -83,6 +83,11 @@ 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_COMPLEX_IEEE_F16BE_TOKEN H5T_COMPLEX_IEEE_F16LE_TOKEN +%token H5T_COMPLEX_IEEE_F32BE_TOKEN H5T_COMPLEX_IEEE_F32LE_TOKEN +%token H5T_COMPLEX_IEEE_F64BE_TOKEN H5T_COMPLEX_IEEE_F64LE_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 +98,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 +112,7 @@ ddl_type : atomic_type | compound_type | array_type | vlen_type + | complex_type ; atomic_type : integer_type | fp_type @@ -245,6 +252,19 @@ vlen_type : H5T_VLEN_TOKEN '{' ddl_type '}' { $$ = H5Tvlen_create($3); H5Tclose($3); } ; +complex_type : H5T_NATIVE_FLOAT_COMPLEX_TOKEN { $$ = H5Tcopy(H5T_NATIVE_FLOAT_COMPLEX); } + | H5T_NATIVE_DOUBLE_COMPLEX_TOKEN { $$ = H5Tcopy(H5T_NATIVE_DOUBLE_COMPLEX); } + | H5T_NATIVE_LDOUBLE_COMPLEX_TOKEN { $$ = H5Tcopy(H5T_NATIVE_LDOUBLE_COMPLEX); } + | H5T_COMPLEX_IEEE_F16LE_TOKEN { $$ = H5Tcopy(H5T_COMPLEX_IEEE_F16LE); } + | H5T_COMPLEX_IEEE_F16BE_TOKEN { $$ = H5Tcopy(H5T_COMPLEX_IEEE_F16BE); } + | H5T_COMPLEX_IEEE_F32LE_TOKEN { $$ = H5Tcopy(H5T_COMPLEX_IEEE_F32LE); } + | H5T_COMPLEX_IEEE_F32BE_TOKEN { $$ = H5Tcopy(H5T_COMPLEX_IEEE_F32BE); } + | H5T_COMPLEX_IEEE_F64LE_TOKEN { $$ = H5Tcopy(H5T_COMPLEX_IEEE_F64LE); } + | H5T_COMPLEX_IEEE_F64BE_TOKEN { $$ = H5Tcopy(H5T_COMPLEX_IEEE_F64BE); } + | H5T_COMPLEX_TOKEN '{' ddl_type '}' + { $$ = H5Tcomplex_create($3); H5Tclose($3); } + ; + opaque_type : H5T_OPAQUE_TOKEN '{' OPQ_SIZE_TOKEN opaque_size ';' diff --git a/hl/test/test_lite.c b/hl/test/test_lite.c index 7d40e3deed1..d17ca14870f 100644 --- a/hl/test/test_lite.c +++ b/hl/test/test_lite.c @@ -1893,6 +1893,226 @@ test_complicated_compound(void) return -1; } +/*------------------------------------------------------------------------- + * subroutine for test_text_dtype(): test complex number datatypes + *------------------------------------------------------------------------- + */ +static int +test_complex(void) +{ + hid_t dtype; + H5T_class_t type_class; + + HL_TESTING3(" text for complex number types"); + +#ifdef H5_HAVE_COMPLEX_NUMBERS + if ((dtype = H5LTtext_to_dtype("H5T_NATIVE_FLOAT_COMPLEX\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_NATIVE_FLOAT_COMPLEX)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_NATIVE_DOUBLE_COMPLEX\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_NATIVE_DOUBLE_COMPLEX)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_NATIVE_LDOUBLE_COMPLEX\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_NATIVE_LDOUBLE_COMPLEX)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_NATIVE_FLOAT }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_NATIVE_FLOAT_COMPLEX)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_NATIVE_DOUBLE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_NATIVE_DOUBLE_COMPLEX)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_NATIVE_LDOUBLE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_NATIVE_LDOUBLE_COMPLEX)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; +#endif + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX_IEEE_F16LE\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F16LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX_IEEE_F16BE\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F16BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX_IEEE_F32LE\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F32LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX_IEEE_F32BE\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F32BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX_IEEE_F64LE\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F64LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX_IEEE_F64BE\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F64BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_IEEE_F16LE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F16LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_IEEE_F16BE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F16BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_IEEE_F32LE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F32LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_IEEE_F32BE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F32BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_IEEE_F64LE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F64LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_COMPLEX { H5T_IEEE_F64BE }\n", H5LT_DDL)) < 0) + goto out; + if ((type_class = H5Tget_class(dtype)) < 0) + goto out; + if (type_class != H5T_COMPLEX) + goto out; + if (!H5Tequal(dtype, H5T_COMPLEX_IEEE_F64BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + PASSED(); + return 0; + +out: + H5_FAILED(); + return -1; +} + /*------------------------------------------------------------------------- * test H5LTtext_to_dtype function *------------------------------------------------------------------------- @@ -1933,6 +2153,9 @@ test_text_dtype(void) if (test_complicated_compound() < 0) goto out; + if (test_complex() < 0) + goto out; + return 0; out: diff --git a/hl/tools/h5watch/h5watch.c b/hl/tools/h5watch/h5watch.c index cfa6bae857d..594e8cbbcf7 100644 --- a/hl/tools/h5watch/h5watch.c +++ b/hl/tools/h5watch/h5watch.c @@ -94,17 +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_ldouble[16]; /* Format info */ - 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; @@ -176,8 +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", DBL_DIG); + 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 53350eb7a87..fe475611bc8 100644 --- a/java/src/hdf/hdf5lib/H5.java +++ b/java/src/hdf/hdf5lib/H5.java @@ -13747,6 +13747,33 @@ public synchronized static native void H5Tcommit_anon(long loc_id, long type_id, public synchronized static native void H5Tcompiler_conv(long src_id, long dst_id) throws HDF5LibraryException; + /** + * @ingroup JH5T + * + * H5Tcomplex_create creates a new complex number datatype object. + * + * @param base_id + * IN: Datatype identifier for the complex number base datatype. + * Must be a floating-point datatype. + * + * @return a valid datatype identifier + * + * @exception HDF5LibraryException + * Error from the HDF5 Library. + **/ + public static long H5Tcomplex_create(long base_id) throws HDF5LibraryException + { + long id = _H5Tcomplex_create(base_id); + if (id > 0) { + log.trace("OPEN_IDS: H5Tcomplex_create add {}", id); + OPEN_IDS.add(id); + log.trace("OPEN_IDS: {}", OPEN_IDS.size()); + } + return id; + } + + private synchronized static native long _H5Tcomplex_create(long base_id) throws HDF5LibraryException; + /** * @ingroup JH5T * @@ -14250,6 +14277,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 acc6d7d7b18..7ace14f8c2f 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(); @@ -1049,6 +1051,18 @@ public class HDF5Constants { /** */ public static final int H5T_CONV_INIT = H5T_CONV_INIT(); /** */ + public static final long H5T_COMPLEX_IEEE_F16BE = H5T_COMPLEX_IEEE_F16BE(); + /** */ + public static final long H5T_COMPLEX_IEEE_F16LE = H5T_COMPLEX_IEEE_F16LE(); + /** */ + public static final long H5T_COMPLEX_IEEE_F32BE = H5T_COMPLEX_IEEE_F32BE(); + /** */ + public static final long H5T_COMPLEX_IEEE_F32LE = H5T_COMPLEX_IEEE_F32LE(); + /** */ + public static final long H5T_COMPLEX_IEEE_F64BE = H5T_COMPLEX_IEEE_F64BE(); + /** */ + public static final long H5T_COMPLEX_IEEE_F64LE = H5T_COMPLEX_IEEE_F64LE(); + /** */ public static final int H5T_CSET_ERROR = H5T_CSET_ERROR(); /** */ public static final int H5T_CSET_ASCII = H5T_CSET_ASCII(); @@ -1177,10 +1191,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 +1241,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 +2552,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(); @@ -2540,6 +2562,18 @@ public class HDF5Constants { private static native final int H5T_CONV_INIT(); + private static native final long H5T_COMPLEX_IEEE_F16BE(); + + private static native final long H5T_COMPLEX_IEEE_F16LE(); + + private static native final long H5T_COMPLEX_IEEE_F32BE(); + + private static native final long H5T_COMPLEX_IEEE_F32LE(); + + private static native final long H5T_COMPLEX_IEEE_F64BE(); + + private static native final long H5T_COMPLEX_IEEE_F64LE(); + private static native final int H5T_CSET_ERROR(); private static native final int H5T_CSET_ASCII(); @@ -2668,10 +2702,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 +2752,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 984ed937967..c9fc5c142eb 100644 --- a/java/src/jni/h5Constants.c +++ b/java/src/jni/h5Constants.c @@ -2537,6 +2537,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; @@ -2556,6 +2561,36 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1CONV_1INIT(JNIEnv *env, jclass cls) { return H5T_CONV_INIT; } +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX_1IEEE_1F16BE(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX_IEEE_F16BE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX_1IEEE_1F16LE(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX_IEEE_F16LE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX_1IEEE_1F32BE(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX_IEEE_F32BE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX_1IEEE_1F32LE(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX_IEEE_F32LE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX_1IEEE_1F64BE(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX_IEEE_F64BE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX_1IEEE_1F64LE(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX_IEEE_F64LE; +} JNIEXPORT jint JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1CSET_1ERROR(JNIEnv *env, jclass cls) { @@ -2877,6 +2912,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; @@ -2887,6 +2927,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; @@ -2992,6 +3037,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 47388b1b884..b6447e51eea 100644 --- a/java/src/jni/h5aImp.c +++ b/java/src/jni/h5aImp.c @@ -1237,12 +1237,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); @@ -1266,13 +1267,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); @@ -1283,7 +1284,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); } @@ -1441,12 +1442,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); @@ -1470,13 +1472,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); @@ -1487,7 +1489,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 405c471b9f9..5dba7a85d93 100644 --- a/java/src/jni/h5dImp.c +++ b/java/src/jni/h5dImp.c @@ -1253,12 +1253,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); @@ -1282,13 +1283,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); @@ -1299,7 +1300,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); @@ -1478,12 +1479,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); @@ -1507,13 +1509,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); @@ -1524,7 +1526,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/h5tImp.c b/java/src/jni/h5tImp.c index 7512f8214b1..039db7b9053 100644 --- a/java/src/jni/h5tImp.c +++ b/java/src/jni/h5tImp.c @@ -1641,6 +1641,25 @@ Java_hdf_hdf5lib_H5_H5Tget_1array_1dims2(JNIEnv *env, jclass clss, jlong type_id return (jint)ndims; } /* end Java_hdf_hdf5lib_H5_H5Tget_1array_1dims2 */ +/* + * Class: hdf_hdf5lib_H5 + * Method: _H5Tcomplex_create + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_H5__1H5Tcomplex_1create(JNIEnv *env, jclass clss, jlong base_id) +{ + hid_t retVal = H5I_INVALID_HID; + + UNUSED(clss); + + if ((retVal = H5Tcomplex_create((hid_t)base_id)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + +done: + return (jlong)retVal; +} /* end Java_hdf_hdf5lib_H5__1H5Tcomplex_1create */ + /* * Class: hdf_hdf5lib_H5 * Method: H5Tconvert diff --git a/java/src/jni/h5tImp.h b/java/src/jni/h5tImp.h index 0d45cc10fa9..dc3f6f939f5 100644 --- a/java/src/jni/h5tImp.h +++ b/java/src/jni/h5tImp.h @@ -479,6 +479,13 @@ JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_H5__1H5Tarray_1create2(JNIEnv *, jclass */ JNIEXPORT jint JNICALL Java_hdf_hdf5lib_H5_H5Tget_1array_1dims2(JNIEnv *, jclass, jlong, jlongArray); +/* + * Class: hdf_hdf5lib_H5 + * Method: _H5Tcomplex_create + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_H5__1H5Tcomplex_1create(JNIEnv *, jclass, jlong); + /* * Class: hdf_hdf5lib_H5 * Method: H5Tconvert diff --git a/java/src/jni/h5util.c b/java/src/jni/h5util.c index 2ceb05258b5..cc08e33ab70 100644 --- a/java/src/jni/h5util.c +++ b/java/src/jni/h5util.c @@ -614,6 +614,43 @@ h5str_convert(JNIEnv *env, char **in_str, hid_t container, hid_t tid, void *out_ break; } + case H5T_COMPLEX: { + size_t baseTypeSize; + + if ((mtid = H5Tget_super(tid)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + + if (!(baseTypeSize = H5Tget_size(mtid))) + H5_LIBRARY_ERROR(ENVONLY); + + if (NULL == (cptr = calloc(1, typeSize))) + H5_OUT_OF_MEMORY_ERROR(ENVONLY, "h5str_convert: failed to allocate array buffer"); + + /* Convert real part */ + if (!(h5str_convert(ENVONLY, &this_str, container, mtid, out_buf, 0))) { + CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); + goto done; + } + + /* Skip any whitespace */ + while (*this_str == ' ') + this_str++; + + /* Convert imaginary part */ + if (!(h5str_convert(ENVONLY, &this_str, container, mtid, out_buf, baseTypeSize))) { + CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); + goto done; + } + + if (H5Tclose(mtid) < 0) + H5_LIBRARY_ERROR(ENVONLY); + mtid = H5I_INVALID_HID; + + retVal = typeSize; + + break; + } + case H5T_NCLASSES: case H5T_NO_CLASS: { H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_convert: invalid datatype class"); @@ -1476,6 +1513,48 @@ h5str_sprintf(JNIEnv *env, h5str_t *out_str, hid_t container, hid_t tid, void *i break; } + case H5T_COMPLEX: { + h5str_t real_part, imag_part; + size_t baseSize; + + h5str_new(&real_part, 128); + h5str_new(&imag_part, 128); + + /* Get the base datatype for the complex number type */ + if ((mtid = H5Tget_super(tid)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + + if (!(baseSize = H5Tget_size(mtid))) + H5_LIBRARY_ERROR(ENVONLY); + + if (!h5str_sprintf(ENVONLY, &real_part, container, mtid, cptr, expand_data)) + CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); + if (!h5str_sprintf(ENVONLY, &imag_part, container, mtid, cptr + baseSize, expand_data)) + CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); + + if (!h5str_append(out_str, real_part.s)) + H5_ASSERTION_ERROR(ENVONLY, "Unable to append string."); + + if (NULL == strstr(imag_part.s, "-")) + if (!h5str_append(out_str, "+")) + H5_ASSERTION_ERROR(ENVONLY, "Unable to append string."); + + if (!h5str_append(out_str, imag_part.s)) + H5_ASSERTION_ERROR(ENVONLY, "Unable to append string."); + + if (!h5str_append(out_str, "i")) + H5_ASSERTION_ERROR(ENVONLY, "Unable to append string."); + + if (H5Tclose(mtid) < 0) + H5_LIBRARY_ERROR(ENVONLY); + mtid = H5I_INVALID_HID; + + h5str_free(&real_part); + h5str_free(&imag_part); + + break; + } + case H5T_NO_CLASS: case H5T_NCLASSES: { H5_BAD_ARGUMENT_ERROR(ENVONLY, "h5str_sprintf: invalid datatype class"); @@ -2110,6 +2189,17 @@ h5str_get_little_endian_type(hid_t tid) break; } + case H5T_COMPLEX: { + if (size == 4) + p_type = H5Tcopy(H5T_COMPLEX_IEEE_F16LE); + else if (size == 8) + p_type = H5Tcopy(H5T_COMPLEX_IEEE_F32LE); + else if (size == 16) + p_type = H5Tcopy(H5T_COMPLEX_IEEE_F64LE); + + break; + } + case H5T_NO_CLASS: case H5T_NCLASSES: { goto done; @@ -2206,6 +2296,17 @@ h5str_get_big_endian_type(hid_t tid) break; } + case H5T_COMPLEX: { + if (size == 4) + p_type = H5Tcopy(H5T_COMPLEX_IEEE_F16BE); + else if (size == 8) + p_type = H5Tcopy(H5T_COMPLEX_IEEE_F32BE); + else if (size == 16) + p_type = H5Tcopy(H5T_COMPLEX_IEEE_F64BE); + + break; + } + case H5T_NO_CLASS: case H5T_NCLASSES: { goto done; @@ -2462,6 +2563,32 @@ h5str_render_bin_output(FILE *stream, hid_t container, hid_t tid, void *_mem, hs break; } + case H5T_COMPLEX: { + hid_t memb = H5I_INVALID_HID; + + if ((memb = H5Tget_super(tid)) < 0) { + ret_value = FAIL; + goto done; + } + + for (block_index = 0; block_index < block_nelmts; block_index++) { + mem = ((unsigned char *)_mem) + block_index * size; + + /* dump the complex number element */ + if (h5str_render_bin_output(stream, container, memb, mem, 2) < 0) { + ret_value = FAIL; + break; + } + } + + if (H5Tclose(memb) < 0) { + ret_value = FAIL; + goto done; + } + + break; + } + case H5T_NO_CLASS: case H5T_NCLASSES: { ret_value = FAIL; @@ -4306,6 +4433,39 @@ translate_atomic_rbuf(JNIEnv *env, jlong mem_type_id, H5T_class_t type_class, vo break; } /* H5T_STRING */ + case H5T_COMPLEX: { + H5T_class_t base_class; + size_t base_size, typeCount; + void *objBuf = NULL; + + if (!(typeSize = H5Tget_size(mem_type_id))) + H5_LIBRARY_ERROR(ENVONLY); + if ((memb = H5Tget_super(mem_type_id)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + if (!(base_size = H5Tget_size(memb))) + H5_LIBRARY_ERROR(ENVONLY); + if ((base_class = H5Tget_class(memb)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + + typeCount = typeSize / base_size; + + if (NULL == (objBuf = malloc(typeSize))) + H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate buffer"); + + memcpy((char *)objBuf, char_buf, typeSize); + + /* The list we're going to return */ + if (NULL == (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0))) + H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate list read buffer"); + + translate_rbuf(ENVONLY, jList, memb, base_class, (jsize)typeCount, objBuf); + jobj = jList; + + if (objBuf) + free(objBuf); + + break; + } case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: @@ -4530,6 +4690,41 @@ translate_atomic_wbuf(JNIEnv *env, jobject in_obj, jlong mem_type_id, H5T_class_ } break; } /* H5T_STRING */ + case H5T_COMPLEX: { + H5T_class_t base_class; + size_t base_size; + void *objBuf = NULL; + + if (!(typeSize = H5Tget_size(mem_type_id))) + H5_LIBRARY_ERROR(ENVONLY); + if ((memb = H5Tget_super(mem_type_id)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + if (!(base_size = H5Tget_size(memb))) + H5_LIBRARY_ERROR(ENVONLY); + if ((base_class = H5Tget_class(memb)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + + /* Convert each array element - invoke the toArray method */ + if (mToArray == NULL) + CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); + jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, in_obj, mToArray); + jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array); + + if (jnelmts < 0) + H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_atomic_wbuf: number of array elements < 0"); + + if (NULL == (objBuf = malloc((size_t)jnelmts * base_size))) + H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_wbuf: failed to allocate buffer"); + + translate_wbuf(ENVONLY, array, memb, base_class, (jsize)jnelmts, objBuf); + + memcpy(char_buf, (char *)objBuf, base_size * (size_t)jnelmts); + + if (objBuf) + free(objBuf); + + break; + } case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: @@ -4752,6 +4947,60 @@ translate_rbuf(JNIEnv *env, jobjectArray ret_buf, jlong mem_type_id, H5T_class_t } break; } + case H5T_COMPLEX: { + H5T_class_t base_class; + size_t base_size, typeCount; + void *objBuf = NULL; + + if (!(typeSize = H5Tget_size(mem_type_id))) + H5_LIBRARY_ERROR(ENVONLY); + if ((memb = H5Tget_super(mem_type_id)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + if (!(base_size = H5Tget_size(memb))) + H5_LIBRARY_ERROR(ENVONLY); + if ((base_class = H5Tget_class(memb)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + + typeCount = typeSize / base_size; + + if (NULL == (objBuf = malloc(typeSize))) + H5_OUT_OF_MEMORY_ERROR(ENVONLY, "translate_atomic_rbuf: failed to allocate buffer"); + + /* Convert each element to a list of 2 floating-point elements */ + for (i = 0; i < (size_t)count; i++) { + found_jList = JNI_TRUE; + jList = NULL; + + /* Get the object element */ + memcpy((char *)objBuf, char_buf + i * typeSize, typeSize); + + /* The list we're going to return: */ + if (i < (size_t)ret_buflen) { + if (NULL == + (jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)ret_buf, (jsize)i))) + found_jList = JNI_FALSE; + } + if (NULL == jList) { + if (NULL == + (jList = (jobjectArray)ENVPTR->NewObject(ENVONLY, arrCList, arrListMethod, 0))) + H5_OUT_OF_MEMORY_ERROR(ENVONLY, + "translate_rbuf: failed to allocate list read buffer"); + } + + translate_rbuf(ENVONLY, jList, memb, base_class, (jsize)typeCount, objBuf); + if (found_jList == JNI_FALSE) + ENVPTR->CallBooleanMethod(ENVONLY, ret_buf, arrAddMethod, jList); + else + ENVPTR->SetObjectArrayElement(ENVONLY, ret_buf, (jsize)i, jList); + CHECK_JNI_EXCEPTION(ENVONLY, JNI_TRUE); + ENVPTR->DeleteLocalRef(ENVONLY, jList); + } + + if (objBuf) + free(objBuf); + + break; + } case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: @@ -4914,6 +5163,39 @@ translate_wbuf(JNIEnv *env, jobjectArray in_buf, jlong mem_type_id, H5T_class_t } break; } + case H5T_COMPLEX: { + H5T_class_t base_class; + size_t base_size; + + if ((memb = H5Tget_super(mem_type_id)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + if (!(base_size = H5Tget_size(memb))) + H5_LIBRARY_ERROR(ENVONLY); + if ((base_class = H5Tget_class(memb)) < 0) + H5_LIBRARY_ERROR(ENVONLY); + + /* Convert each list to an array element */ + for (i = 0; i < (size_t)count; i++) { + if (NULL == (jList = ENVPTR->GetObjectArrayElement(ENVONLY, (jobjectArray)in_buf, (jsize)i))) + CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); + + /* invoke the toArray method */ + if (mToArray == NULL) + CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); + jobjectArray array = (jobjectArray)ENVPTR->CallObjectMethod(ENVONLY, jList, mToArray); + jsize jnelmts = ENVPTR->GetArrayLength(ENVONLY, array); + + if (jnelmts < 0) + H5_BAD_ARGUMENT_ERROR(ENVONLY, "translate_wbuf: number of array elements < 0"); + + translate_wbuf(ENVONLY, array, memb, base_class, jnelmts, + char_buf + i * base_size * (size_t)jnelmts); + + ENVPTR->DeleteLocalRef(ENVONLY, jList); + } /* end for (i = 0; i < count; i++) */ + + break; + } case H5T_TIME: case H5T_NO_CLASS: case H5T_NCLASSES: diff --git a/java/test/TestH5T.java b/java/test/TestH5T.java index b861e80613b..d57ff354119 100644 --- a/java/test/TestH5T.java +++ b/java/test/TestH5T.java @@ -240,6 +240,60 @@ public void testH5Tget_array_dims() } } + @Test + public void testH5Tcomplex_create() + { + String class_name; + long[] fields1 = {0, 0, 0, 0, 0}; + long[] fields2 = {0, 0, 0, 0, 0}; + long filetype_id = HDF5Constants.H5I_INVALID_HID; + long dt_size = -1; + int typeclass = -1; + int typeorder = HDF5Constants.H5T_ORDER_ERROR; + int prec1 = 0; + int prec2 = 0; + + try { + filetype_id = H5.H5Tcomplex_create(HDF5Constants.H5T_IEEE_F32LE); + assertTrue("testH5Tcomplex_create:H5Tcomplex_create", filetype_id >= 0); + + typeclass = H5.H5Tget_class(filetype_id); + assertTrue("H5.H5Tget_class", typeclass > 0); + class_name = H5.H5Tget_class_name(typeclass); + assertTrue("H5.H5Tget_class_name", class_name.compareTo("H5T_COMPLEX") == 0); + + dt_size = H5.H5Tget_size(filetype_id); + assertTrue("H5.H5Tget_size", dt_size == 8); + + typeorder = H5.H5Tget_order(filetype_id); + assertTrue("H5.H5Tget_order", typeorder == HDF5Constants.H5T_ORDER_LE); + + prec1 = H5.H5Tget_precision(HDF5Constants.H5T_IEEE_F32LE); + prec2 = H5.H5Tget_precision(filetype_id); + assertTrue("H5.H5Tget_precision", prec1 == prec2); + + H5.H5Tget_fields(HDF5Constants.H5T_IEEE_F32LE, fields1); + H5.H5Tget_fields(filetype_id, fields2); + assertTrue("H5.H5Tget_fields[spos]", fields1[0] == fields2[0]); + assertTrue("H5.H5Tget_fields[epos]", fields1[1] == fields2[1]); + assertTrue("H5.H5Tget_fields[esize]", fields1[2] == fields2[2]); + assertTrue("H5.H5Tget_fields[mpos]", fields1[3] == fields2[3]); + assertTrue("H5.H5Tget_fields[msize]", fields1[4] == fields2[4]); + } + catch (Throwable err) { + err.printStackTrace(); + fail("testH5Tcomplex_create " + err); + } + finally { + if (filetype_id >= 0) + try { + H5.H5Tclose(filetype_id); + } + catch (Exception ex) { + } + } + } + @Test public void testH5Tenum_functions() { diff --git a/java/test/testfiles/JUnit-TestH5T.txt b/java/test/testfiles/JUnit-TestH5T.txt index 06e7a9cbb5b..039e8286f31 100644 --- a/java/test/testfiles/JUnit-TestH5T.txt +++ b/java/test/testfiles/JUnit-TestH5T.txt @@ -11,9 +11,10 @@ JUnit version 4.13.2 .testH5Tcompound_functions .testH5Tget_size .testH5Tarray_create +.testH5Tcomplex_create .testH5Topaque_functions Time: XXXX -OK (13 tests) +OK (14 tests) diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index 5f8321daae9..86f894d3bea 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -151,6 +151,200 @@ New Features Library: -------- + - Added support for complex number datatypes + + Support for the C99 "float _Complex", "double _Complex" and "long double _Complex" + (with MSVC, "_Fcomplex", "_Dcomplex" and "_Lcomplex") types has been added for + platforms/compilers that support them. These types have been implemented with a + new datatype class, H5T_COMPLEX. Note that any datatypes of class H5T_COMPLEX + will not be readable with previous versions of HDF5. If a file is accessed with + a library version bounds "high" setting less than H5F_LIBVER_V200, an error will + occur if the application tries to create an object with a complex number datatype. + If compatibility with previous versions of HDF5 is desired, applications should + instead consider adopting one of the existing conventions at + https://nc-complex.readthedocs.io/en/latest/#conventions-used-in-applications. + + The following new macros have been added: + + - H5_HAVE_COMPLEX_NUMBERS + + This macro is defined in H5pubconf.h and will have the value 1 if native + support for complex numbers is available. It will not be defined otherwise. + + - H5_HAVE_C99_COMPLEX_NUMBERS + + This macro is defined in H5pubconf.h and will have the value 1 if native + support for C99 complex numbers is available. It will not be defined otherwise. + If this macro is not defined but H5_HAVE_COMPLEX_NUMBERS is defined, the + complex number types supported are the MSVC types. + + - H5_SIZEOF_FLOAT_COMPLEX + + This macro is defined in H5pubconf.h and will have a value corresponding + to the size of the native float complex datatype, as computed by sizeof(). + If C99 complex number support is available, this will be the size of the + "float _Complex" type. Otherwise, it will be the size of the "_Fcomplex" + type. It will have the value 0 if support for a native float complex datatype + is not available. + + - H5_SIZEOF_DOUBLE_COMPLEX + + This macro is defined in H5pubconf.h and will have a value corresponding + to the size of the native double complex datatype, as computed by sizeof(). + If C99 complex number support is available, this will be the size of the + "double _Complex" type. Otherwise, it will be the size of the "_Dcomplex" + type. It will have the value 0 if support for a native double complex datatype + is not available. + + - H5_SIZEOF_LONG_DOUBLE_COMPLEX + + This macro is defined in H5pubconf.h and will have a value corresponding + to the size of the native long double complex datatype, as computed by sizeof(). + If C99 complex number support is available, this will be the size of the + "long double _Complex" type. Otherwise, it will be the size of the "_Lcomplex" + type. It will have the value 0 if support for a native long double complex + datatype is not available. + + - H5T_NATIVE_FLOAT_COMPLEX + + This macro maps to the ID of an HDF5 datatype representing the native C + float complex datatype (either "float _Complex" or "_Fcomplex") for the + platform. If support for a native float complex datatype is not available + (H5_HAVE_COMPLEX_NUMBERS is not defined), the macro will map to + H5I_INVALID_HID and should not be used. + + - H5T_NATIVE_DOUBLE_COMPLEX + + This macro maps to the ID of an HDF5 datatype representing the native C + double complex datatype (either "double _Complex" or "_Dcomplex") for the + platform. If support for a native double complex datatype is not available + (H5_HAVE_COMPLEX_NUMBERS is not defined), the macro will map to + H5I_INVALID_HID and should not be used. + + - H5T_NATIVE_LDOUBLE_COMPLEX + + This macro maps to the ID of an HDF5 datatype representing the native C + long double complex datatype (either "long double _Complex" or "_Lcomplex") + for the platform. If support for a native long double complex datatype is + not available (H5_HAVE_COMPLEX_NUMBERS is not defined), the macro will map + to H5I_INVALID_HID and should not be used. + + - H5T_COMPLEX_IEEE_F16LE / H5T_COMPLEX_IEEE_F16BE + + These macros map to IDs of HDF5 datatypes representing a complex number of + two parts, each of which is an IEEE 754 16-bit floating-point datatype in + little- or big-endian order. These datatypes are available regardless of + whether complex number support is available or not. + + - H5T_COMPLEX_IEEE_F32LE / H5T_COMPLEX_IEEE_F32BE + + These macros map to IDs of HDF5 datatypes representing a complex number of + two parts, each of which is an IEEE 754 32-bit floating-point datatype in + little- or big-endian order. These datatypes are available regardless of + whether complex number support is available or not. + + - H5T_COMPLEX_IEEE_F64LE / H5T_COMPLEX_IEEE_F64BE + + These macros map to IDs of HDF5 datatypes representing a complex number of + two parts, each of which is an IEEE 754 64-bit floating-point datatype in + little- or big-endian order. These datatypes are available regardless of + whether complex number support is available or not. + + The following new API function has been added: + + hid_t H5Tcomplex_create(hid_t base_type_id); + + Creates a new complex number datatype from the base datatype specified + by the given HDF5 ID `base_type_id`. The base datatype must be a + floating-point datatype. + + The following new hard datatype conversion paths have been added, but + will only be used when complex number support is available: + + H5T_NATIVE_SCHAR <-> H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_UCHAR <-> H5T_NATIVE_FLOAT_COMPLEX + H5T_NATIVE_SHORT <-> H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_USHORT <-> H5T_NATIVE_FLOAT_COMPLEX + H5T_NATIVE_INT <-> H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_UINT <-> H5T_NATIVE_FLOAT_COMPLEX + H5T_NATIVE_LONG <-> H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_ULONG <-> H5T_NATIVE_FLOAT_COMPLEX + H5T_NATIVE_LLONG <-> H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_ULLONG <-> H5T_NATIVE_FLOAT_COMPLEX + H5T_NATIVE_FLOAT16 <-> H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_FLOAT <-> H5T_NATIVE_FLOAT_COMPLEX + H5T_NATIVE_DOUBLE <-> H5T_NATIVE_FLOAT_COMPLEX | H5T_NATIVE_LDOUBLE <-> H5T_NATIVE_FLOAT_COMPLEX + + H5T_NATIVE_SCHAR <-> H5T_NATIVE_DOUBLE_COMPLEX | H5T_NATIVE_UCHAR <-> H5T_NATIVE_DOUBLE_COMPLEX + H5T_NATIVE_SHORT <-> H5T_NATIVE_DOUBLE_COMPLEX | H5T_NATIVE_USHORT <-> H5T_NATIVE_DOUBLE_COMPLEX + H5T_NATIVE_INT <-> H5T_NATIVE_DOUBLE_COMPLEX | H5T_NATIVE_UINT <-> H5T_NATIVE_DOUBLE_COMPLEX + H5T_NATIVE_LONG <-> H5T_NATIVE_DOUBLE_COMPLEX | H5T_NATIVE_ULONG <-> H5T_NATIVE_DOUBLE_COMPLEX + H5T_NATIVE_LLONG <-> H5T_NATIVE_DOUBLE_COMPLEX | H5T_NATIVE_ULLONG <-> H5T_NATIVE_DOUBLE_COMPLEX + H5T_NATIVE_FLOAT16 <-> H5T_NATIVE_DOUBLE_COMPLEX | H5T_NATIVE_FLOAT <-> H5T_NATIVE_DOUBLE_COMPLEX + H5T_NATIVE_DOUBLE <-> H5T_NATIVE_DOUBLE_COMPLEX | H5T_NATIVE_LDOUBLE <-> H5T_NATIVE_DOUBLE_COMPLEX + + H5T_NATIVE_SCHAR <-> H5T_NATIVE_LDOUBLE_COMPLEX | H5T_NATIVE_UCHAR <-> H5T_NATIVE_LDOUBLE_COMPLEX + H5T_NATIVE_SHORT <-> H5T_NATIVE_LDOUBLE_COMPLEX | H5T_NATIVE_USHORT <-> H5T_NATIVE_LDOUBLE_COMPLEX + H5T_NATIVE_INT <-> H5T_NATIVE_LDOUBLE_COMPLEX | H5T_NATIVE_UINT <-> H5T_NATIVE_LDOUBLE_COMPLEX + H5T_NATIVE_LONG <-> H5T_NATIVE_LDOUBLE_COMPLEX | H5T_NATIVE_ULONG <-> H5T_NATIVE_LDOUBLE_COMPLEX + H5T_NATIVE_LLONG <-> H5T_NATIVE_LDOUBLE_COMPLEX | H5T_NATIVE_ULLONG <-> H5T_NATIVE_LDOUBLE_COMPLEX + H5T_NATIVE_FLOAT16 <-> H5T_NATIVE_LDOUBLE_COMPLEX | H5T_NATIVE_FLOAT <-> H5T_NATIVE_LDOUBLE_COMPLEX + H5T_NATIVE_DOUBLE <-> H5T_NATIVE_LDOUBLE_COMPLEX | H5T_NATIVE_LDOUBLE <-> H5T_NATIVE_LDOUBLE_COMPLEX + + H5T_NATIVE_FLOAT_COMPLEX <-> H5T_NATIVE_DOUBLE_COMPLEX + H5T_NATIVE_FLOAT_COMPLEX <-> H5T_NATIVE_LDOUBLE_COMPLEX + H5T_NATIVE_DOUBLE_COMPLEX <-> H5T_NATIVE_LDOUBLE_COMPLEX + + Alternative software implementation conversion paths have been added for all of + the above for use when native complex number support is not available. All of these + conversion paths follow the behavior outlined in the C standard for conversions of + complex number values. + + Additionally, a special datatype conversion path has been added between complex number + datatypes and array or compound datatypes where the in-memory layout of data is the + same between the datatypes and data can be directly converted. This conversion path + is subject to the following rules: + + - An array datatype must consist of exactly two elements where each element is of + the same floating-point datatype as the complex number datatype's base floating-point + datatype. + + - A compound datatype must consist of exactly two fields where each field is of the + same floating-point datatype as the complex number datatype's base floating-point + datatype. The compound datatype must not have any leading or trailing structure + padding or any padding between its two fields. The fields must also have compatible + names, must have compatible offsets within the datatype and must be in the order + of "real" part -> "imaginary" part, such that the compound datatype matches the + following representation: + + H5T_COMPOUND { + "r(e)(a)(l)"; OFFSET 0 + "i(m)(a)(g)(i)(n)(a)(r)(y)"; OFFSET SIZEOF("r(e)(a)(l)") + } + + where "r(e)(a)(l)" means the field may be named any substring of "real", such as + "r", or "re" and "i(m)(a)(g)(i)(n)(a)(r)(y)" means the field may be named any + substring of "imaginary", such as "im" or "imag". + + Support for complex numbers has been added to the h5dump, h5ls and h5diff/ph5diff + tools. The h5dump command-line option '-m' can be used to change the floating-point + printing format for the float complex and double complex datatypes, as well as + the long double complex datatype if it has the same size as a double complex + datatype. + + Support for the predefined complex number datatypes and the H5Tcomplex_create + function has been added to the Java wrappers. However, Java does not have + official types for complex numbers, so an application must be sure that + data is in an appropriate format in-memory when using these datatypes. + + Support for the Fortran wrappers has not yet been added. + + Support for the predefined complex number datatypes and the H5Tcomplex_create + function has been added to the high level library, allowing them to work + with the H5LTtext_to_dtype and H5LTdtype_to_text functions. + + Simple example programs showing how to use complex number datatypes have + been added in the following files: + + - HDF5Examples/C/H5T/200/h5ex_t_complex.c (Uses C99 complex number types) + - HDF5Examples/C/H5T/200/h5ex_t_complex_msvc.c (Uses MSVC complex number types) + - HDF5Examples/C/H5T/200/h5ex_t_complex_custom.c (Uses H5Tcomplex_create to create + a custom complex number type) + - The H5VLstart_lib_state / H5VLfinish_lib_state API routines for pass- through connector authors now require a parameter that can be used to store the library's context. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 644539bfc00..2cdaa575c43 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 @@ -979,6 +981,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/H5Fmodule.h b/src/H5Fmodule.h index ba9ab98f4dc..61d981b8394 100644 --- a/src/H5Fmodule.h +++ b/src/H5Fmodule.h @@ -240,7 +240,7 @@ * Tools * page under * Command-line Tools. - * The HDF5 DDL grammar is described in the document \ref DDLBNF114. + * The HDF5 DDL grammar is described in the document \ref DDLBNF200. * * \subsection subsec_file_summary File Function Summaries * General library (\ref H5 functions and macros), (\ref H5F functions), file related diff --git a/src/H5Gmodule.h b/src/H5Gmodule.h index 3457db90b03..901f3b5b640 100644 --- a/src/H5Gmodule.h +++ b/src/H5Gmodule.h @@ -344,7 +344,7 @@ * * h5dump is described on the “HDF5 Tools” page of the \ref RM. * - * The HDF5 DDL grammar is described in the @ref DDLBNF114. + * The HDF5 DDL grammar is described in the @ref DDLBNF200. * * \subsection subsec_group_function Group Function Summaries * Functions that can be used with groups (\ref H5G functions) and property list functions that can used diff --git a/src/H5Odtype.c b/src/H5Odtype.c index 86892288923..bd3871c23b6 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -830,6 +830,52 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t dt->shared->force_conv = true; break; + case H5T_COMPLEX: { + bool homogeneous; + + /* + * Complex number datatypes... + */ + + /* Set whether the complex number datatype is homogeneous */ + homogeneous = (bool)(flags & 0x01); + + if (!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"); + + /* Other bits of the flags beyond bits 0,1,2 should not be set */ + if ((flags >> 3) != 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, + "invalid flag bits set for complex number datatype"); + + /* 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"); + + /* Check if the parent of this complex number type has a version greater + * than the type itself. + */ + H5O_DTYPE_CHECK_VERSION(dt, version, dt->shared->parent->shared->version, ioflags, "complex", + FAIL) + + /* There should be no complex number datatypes with version < 5. */ + H5O_DTYPE_CHECK_VERSION(dt, version, H5O_DTYPE_VERSION_5, ioflags, "complex", FAIL) + + break; + } + case H5T_NO_CLASS: case H5T_NCLASSES: default: @@ -1347,6 +1393,32 @@ 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: + /* Check that the version is valid */ + assert(dt->shared->version >= H5O_DTYPE_VERSION_5); + + /* Check that the version is at least as great as the parent */ + assert(dt->shared->version >= dt->shared->parent->shared->version); + + 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 that complex number is homogeneous in first flag bit; + * Currently, only homogeneous complex number datatypes are supported. + */ + 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 +1716,10 @@ H5O__dtype_size(const H5F_t *f, const void *_mesg) ret_value += H5O__dtype_size(f, dt->shared->parent); break; + case H5T_COMPLEX: + ret_value += H5O__dtype_size(f, dt->shared->parent); + break; + case H5T_NO_CLASS: case H5T_STRING: case H5T_REFERENCE: @@ -2001,6 +2077,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 +2324,25 @@ 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; + } + + 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 807ee3d5cf3..a498b99db0b 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 24c8c581ad9..c6ca851e62c 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 ec07f74a73e..789ea606d69 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -373,23 +373,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 80c64e91fad..57141a7c728 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -255,10 +255,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 31d68a9ad21..88110be5f97 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 b2137e752c3..234e29d22c4 100644 --- a/src/H5T.c +++ b/src/H5T.c @@ -53,6 +53,7 @@ #include "H5Tconv_enum.h" #include "H5Tconv_vlen.h" #include "H5Tconv_array.h" +#include "H5Tconv_complex.h" /****************/ /* Local Macros */ @@ -432,6 +433,13 @@ hid_t H5T_IEEE_F32LE_g = H5I_INVALID_HID; hid_t H5T_IEEE_F64BE_g = H5I_INVALID_HID; hid_t H5T_IEEE_F64LE_g = H5I_INVALID_HID; +hid_t H5T_COMPLEX_IEEE_F16BE_g = H5I_INVALID_HID; +hid_t H5T_COMPLEX_IEEE_F16LE_g = H5I_INVALID_HID; +hid_t H5T_COMPLEX_IEEE_F32BE_g = H5I_INVALID_HID; +hid_t H5T_COMPLEX_IEEE_F32LE_g = H5I_INVALID_HID; +hid_t H5T_COMPLEX_IEEE_F64BE_g = H5I_INVALID_HID; +hid_t H5T_COMPLEX_IEEE_F64LE_g = H5I_INVALID_HID; + hid_t H5T_VAX_F32_g = H5I_INVALID_HID; hid_t H5T_VAX_F64_g = H5I_INVALID_HID; @@ -472,30 +480,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; @@ -541,20 +552,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; @@ -596,10 +610,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 +H5_float_complex H5T_NATIVE_FLOAT_COMPLEX_POS_INF_g; +H5_float_complex H5T_NATIVE_FLOAT_COMPLEX_NEG_INF_g; +H5_double_complex H5T_NATIVE_DOUBLE_COMPLEX_POS_INF_g; +H5_double_complex H5T_NATIVE_DOUBLE_COMPLEX_NEG_INF_g; +H5_ldouble_complex H5T_NATIVE_LDOUBLE_COMPLEX_POS_INF_g; +H5_ldouble_complex H5T_NATIVE_LDOUBLE_COMPLEX_NEG_INF_g; +#endif /* Declare the free list for H5T_t's and H5T_shared_t's */ H5FL_DEFINE(H5T_t); @@ -612,7 +636,7 @@ const unsigned H5O_dtype_ver_bounds[] = { H5O_DTYPE_VERSION_3, /* H5F_LIBVER_V110 */ H5O_DTYPE_VERSION_4, /* H5F_LIBVER_V112 */ H5O_DTYPE_VERSION_4, /* H5F_LIBVER_V114 */ - H5O_DTYPE_VERSION_4, /* H5F_LIBVER_V200 */ + H5O_DTYPE_VERSION_5, /* H5F_LIBVER_V200 */ H5O_DTYPE_VERSION_LATEST /* H5F_LIBVER_LATEST */ }; @@ -777,6 +801,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))) @@ -820,6 +885,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() */ @@ -859,6 +940,7 @@ H5T__init_package(void) H5T_t *std_u64le = NULL; /* Datatype structure for unsigned 64-bit little-endian integer */ H5T_t *std_u64be = NULL; /* Datatype structure for unsigned 64-bit big-endian integer */ H5T_t *dt = NULL; + H5T_t *tmp_float = NULL; H5T_t *fixedpt = NULL; /* Datatype structure for native int */ H5T_t *floatpt = NULL; /* Datatype structure for native float */ H5T_t *string = NULL; /* Datatype structure for C string */ @@ -867,6 +949,7 @@ H5T__init_package(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 */ @@ -876,6 +959,12 @@ H5T__init_package(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 / _Fcomplex type */ + H5T_t *native_double_complex = NULL; /* Datatype structure for native double _Complex / _Dcomplex type */ + H5T_t *native_ldouble_complex = + NULL; /* Datatype structure for native long double _Complex / _Lcomplex type */ #endif herr_t ret_value = SUCCEED; /* Return value */ @@ -893,6 +982,12 @@ H5T__init_package(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"); @@ -928,6 +1023,14 @@ H5T__init_package(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 @@ -1151,6 +1254,59 @@ H5T__init_package(void) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "invalid datatype location"); ref = dt; /* Keep type for later */ + /*------------------------------------------------------------ + * Complex Number Types + *------------------------------------------------------------ + */ + + /* Complex number of 2 IEEE 2-byte little-endian floats */ + if (NULL == (tmp_float = H5I_object(H5T_IEEE_F16LE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (dt = H5T__complex_create(tmp_float))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype"); + if ((H5T_COMPLEX_IEEE_F16LE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom"); + + /* Complex number of 2 IEEE 2-byte big-endian floats */ + if (NULL == (tmp_float = H5I_object(H5T_IEEE_F16BE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (dt = H5T__complex_create(tmp_float))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype"); + if ((H5T_COMPLEX_IEEE_F16BE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom"); + + /* Complex number of 2 IEEE 4-byte little-endian floats */ + if (NULL == (tmp_float = H5I_object(H5T_IEEE_F32LE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (dt = H5T__complex_create(tmp_float))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype"); + if ((H5T_COMPLEX_IEEE_F32LE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom"); + + /* Complex number of 2 IEEE 4-byte big-endian floats */ + if (NULL == (tmp_float = H5I_object(H5T_IEEE_F32BE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (dt = H5T__complex_create(tmp_float))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype"); + if ((H5T_COMPLEX_IEEE_F32BE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom"); + + /* Complex number of 2 IEEE 8-byte little-endian floats */ + if (NULL == (tmp_float = H5I_object(H5T_IEEE_F64LE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (dt = H5T__complex_create(tmp_float))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype"); + if ((H5T_COMPLEX_IEEE_F64LE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom"); + + /* Complex number of 2 IEEE 8-byte big-endian floats */ + if (NULL == (tmp_float = H5I_object(H5T_IEEE_F64BE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (dt = H5T__complex_create(tmp_float))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "couldn't create complex number datatype"); + if ((H5T_COMPLEX_IEEE_F64BE_g = H5I_register(H5I_DATATYPE, dt, false)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, FAIL, "unable to register datatype atom"); + /* * Register conversion functions beginning with the most general and * ending with the most specific. @@ -1165,18 +1321,27 @@ H5T__init_package(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); status |= H5T__register_int(H5T_PERS_SOFT, "enum", enum_type, enum_type, H5T__conv_enum); @@ -1189,6 +1354,12 @@ H5T__init_package(void) status |= H5T__register_int(H5T_PERS_SOFT, "ref", ref, ref, H5T__conv_ref); status |= H5T__register_int(H5T_PERS_SOFT, "objref_ref", objref, ref, H5T__conv_ref); status |= H5T__register_int(H5T_PERS_SOFT, "regref_ref", regref, ref, H5T__conv_ref); + status |= H5T__register_int(H5T_PERS_SOFT, "complex_array_compat", cplx, array, H5T__conv_complex_compat); + status |= H5T__register_int(H5T_PERS_SOFT, "array_complex_compat", array, cplx, H5T__conv_complex_compat); + status |= + H5T__register_int(H5T_PERS_SOFT, "complex_compound_compat", cplx, compound, H5T__conv_complex_compat); + status |= + H5T__register_int(H5T_PERS_SOFT, "compound_complex_compat", compound, cplx, H5T__conv_complex_compat); /* * Native conversions should be listed last since we can use hardware to @@ -1226,6 +1397,34 @@ H5T__init_package(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 */ @@ -1389,6 +1588,14 @@ H5T__init_package(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 |= @@ -1401,6 +1608,14 @@ H5T__init_package(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 |= @@ -1413,6 +1628,14 @@ H5T__init_package(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 |= @@ -1425,6 +1648,14 @@ H5T__init_package(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); @@ -1434,6 +1665,14 @@ H5T__init_package(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); @@ -1444,6 +1683,14 @@ H5T__init_package(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); @@ -1454,6 +1701,14 @@ H5T__init_package(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 |= @@ -1466,6 +1721,14 @@ H5T__init_package(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 |= @@ -1479,6 +1742,16 @@ H5T__init_package(void) #ifdef H5_HAVE__FLOAT16 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); +#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE + status |= H5T__register_int(H5T_PERS_HARD, "llong_lcomplex", native_llong, native_ldouble_complex, + H5T__conv_llong_lcomplex); +#endif #endif /* From unsigned long long to floats */ @@ -1493,6 +1766,16 @@ H5T__init_package(void) #ifdef H5_HAVE__FLOAT16 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); +#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE + status |= H5T__register_int(H5T_PERS_HARD, "ullong_lcomplex", native_ullong, native_ldouble_complex, + H5T__conv_ullong_lcomplex); +#endif #endif /* From floats to char */ @@ -1603,7 +1886,7 @@ H5T__init_package(void) H5T__register_int(H5T_PERS_HARD, "flt_ullong", native_float, native_ullong, H5T__conv_float_ullong); status |= H5T__register_int(H5T_PERS_HARD, "dbl_ullong", native_double, native_ullong, H5T__conv_double_ullong); -#if H5T_CONV_INTERNAL_LDOUBLE_ULLONG +#ifdef H5T_CONV_INTERNAL_LDOUBLE_ULLONG status |= H5T__register_int(H5T_PERS_HARD, "ldbl_ullong", native_ldouble, native_ullong, H5T__conv_ldouble_ullong); #endif /* H5T_CONV_INTERNAL_LDOUBLE_ULLONG */ @@ -1612,6 +1895,138 @@ H5T__init_package(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); +#ifdef 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 @@ -1652,6 +2067,8 @@ H5T__init_package(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,6 +2182,13 @@ H5T_top_term_package(void) H5T_IEEE_F64BE_g = H5I_INVALID_HID; H5T_IEEE_F64LE_g = H5I_INVALID_HID; + H5T_COMPLEX_IEEE_F16BE_g = H5I_INVALID_HID; + H5T_COMPLEX_IEEE_F16LE_g = H5I_INVALID_HID; + H5T_COMPLEX_IEEE_F32BE_g = H5I_INVALID_HID; + H5T_COMPLEX_IEEE_F32LE_g = H5I_INVALID_HID; + H5T_COMPLEX_IEEE_F64BE_g = H5I_INVALID_HID; + H5T_COMPLEX_IEEE_F64LE_g = H5I_INVALID_HID; + H5T_STD_I8BE_g = H5I_INVALID_HID; H5T_STD_I8LE_g = H5I_INVALID_HID; H5T_STD_I16BE_g = H5I_INVALID_HID; @@ -1802,30 +2226,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; @@ -1968,19 +2395,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) @@ -2390,7 +2817,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); @@ -2402,6 +2829,9 @@ 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: + HGOTO_DONE(H5T_detect_class(dt->shared->parent, cls, from_api)); + break; case H5T_NO_CLASS: case H5T_INTEGER: case H5T_FLOAT: @@ -2537,7 +2967,9 @@ H5Tset_size(hid_t type_id, size_t size) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "only strings may be variable length"); if (H5T_ENUM == dt->shared->type && dt->shared->u.enumer.nmembs > 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not allowed after members are defined"); - if (H5T_REFERENCE == dt->shared->type) + if (H5T_ARRAY == dt->shared->type || H5T_REFERENCE == dt->shared->type || H5T_COMPLEX == dt->shared->type) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype"); + if (H5T_VLEN == dt->shared->type && H5T_VLEN_STRING != dt->shared->u.vlen.type) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "operation not defined for this datatype"); /* Modify the datatype */ @@ -3269,11 +3701,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 @@ -3282,11 +3714,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) @@ -3492,6 +3924,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: @@ -3793,6 +4228,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; @@ -4162,6 +4598,7 @@ H5T__free(H5T_t *dt) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: break; @@ -4342,18 +4779,15 @@ H5T__set_size(H5T_t *dt, size_t size) assert(dt); assert(dt->shared); assert(size != 0); + assert(H5T_ARRAY != dt->shared->type); assert(H5T_REFERENCE != dt->shared->type); + assert(H5T_COMPLEX != dt->shared->type); + assert(H5T_VLEN != dt->shared->type || H5T_VLEN_STRING == dt->shared->u.vlen.type); 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) 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_VLEN) - dt->shared->size = dt->shared->parent->shared->size; } else { if (H5T_IS_ATOMIC(dt->shared)) { @@ -4475,6 +4909,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; @@ -4863,6 +5298,23 @@ 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 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); + + tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset); + if (tmp < 0) + HGOTO_DONE(-1); + if (tmp > 0) + HGOTO_DONE(1); + + break; + case H5T_NO_CLASS: case H5T_INTEGER: case H5T_FLOAT: @@ -4993,6 +5445,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); @@ -5693,6 +6146,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: @@ -6243,6 +6697,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 */ @@ -6296,7 +6751,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; @@ -6337,7 +6792,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; @@ -6379,7 +6834,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"); @@ -6408,6 +6863,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; @@ -6504,6 +6960,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; @@ -6589,6 +7046,11 @@ H5T__upgrade_version_cb(H5T_t *dt, void *op_value) dt->shared->version = dt->shared->parent->shared->version; break; + case H5T_COMPLEX: + if (dt->shared->parent->shared->version > dt->shared->version) + dt->shared->version = dt->shared->parent->shared->version; + break; + case H5T_NO_CLASS: case H5T_INTEGER: case H5T_FLOAT: @@ -6627,7 +7089,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 47f46614f5f..06fd1a34d0e 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..c073ddadbf8 --- /dev/null +++ b/src/H5Tcomplex.c @@ -0,0 +1,152 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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"); + + /* Set complex number-specific fields */ + dt->shared->u.cplx.form = H5T_COMPLEX_RECTANGULAR; /* Only rectangular form is currently supported */ + + /* Complex number datatypes use a later version of the datatype object header message */ + dt->shared->version = MAX(base->shared->version, H5O_DTYPE_VERSION_5); + + 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 cea7c03665c..4131c61e474 100644 --- a/src/H5Tcompound.c +++ b/src/H5Tcompound.c @@ -503,6 +503,8 @@ 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) + dt->shared->size = 2 * dt->shared->parent->shared->size; 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 6d6d023a9c0..7ca3ca6ca3e 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 be822247b6e..fb9ba26e311 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 f9b227196f4..8b46c75c5c5 100644 --- a/src/H5Tconv_bitfield.c +++ b/src/H5Tconv_bitfield.c @@ -106,7 +106,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); @@ -162,8 +164,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..cdd2402cb0f --- /dev/null +++ b/src/H5Tconv_complex.c @@ -0,0 +1,2315 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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); +static herr_t H5T__conv_complex_part(const H5T_t *src_p, const H5T_t *dst_p, uint8_t *s, uint8_t *d, + const H5T_conv_ctx_t *conv_ctx, uint8_t *src_rev, + bool *exception_handled); + +/*------------------------------------------------------------------------- + * 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"); + 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 > 2 * 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. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +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_conv_ret_t except_ret; /* return of conversion exception callback function */ + 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[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(dst_p); + assert(dst_p->shared->type == H5T_COMPLEX); + 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; + + /* + * 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++) { + bool reverse = true; /* if reversed the order of destination */ + bool real_zero = false; /* if real part is +/-0 */ + bool imag_zero = false; /* if imaginary part is +/-0 */ + bool real_except = false; /* if an exception happened for the real part */ + bool imag_except = false; /* if an exception happened for the imaginary part */ + + /* + * 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); + + real_zero = (realval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO || + realval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO); + imag_zero = (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSZERO || + imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGZERO); + real_except = + (realval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || realval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF || + realval_type == H5T_CONV_FLOAT_SPECVAL_NAN); + imag_except = + (imagval_type == H5T_CONV_FLOAT_SPECVAL_POSINF || imagval_type == H5T_CONV_FLOAT_SPECVAL_NEGINF || + imagval_type == H5T_CONV_FLOAT_SPECVAL_NAN); + + /* A complex number is zero if both parts are +/-0 */ + if (real_zero && imag_zero) { + 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 (real_except || imag_except) { + except_ret = H5T_CONV_UNHANDLED; + + /* 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; + } + + if (real_zero) { + 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); + } + else { + bool exception_handled = false; + + if (H5T__conv_complex_part(src_p, dst_p, s, d, conv_ctx, src_rev, &exception_handled) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't convert real part of complex number"); + + /* If an exception was handled, go to the next element */ + if (exception_handled) { + reverse = false; + goto next; + } + } + + if (imag_zero) { + 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, false); + H5T__bit_set(d + dst_part_size, dst_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + } + else { + bool exception_handled = false; + + if (H5T__conv_complex_part(src_p, dst_p, s + src_part_size, d + dst_part_size, conv_ctx, src_rev, + &exception_handled) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, + "can't convert imaginary part of complex number"); + + /* If an exception was handled, go to the next element */ + if (exception_handled) { + reverse = false; + goto next; + } + } + +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_part + * + * Purpose: Helper function to convert a single part (real or + * imaginary) of a complex number. + * + * 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. Conversion exceptions also pose a + * problem since both parts of the complex number have to be + * taken into account when determining if an exception + * occurred. Application conversion exception callbacks would + * also 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 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5T__conv_complex_part(const H5T_t *src_p, const H5T_t *dst_p, uint8_t *s, uint8_t *d, + const H5T_conv_ctx_t *conv_ctx, uint8_t *src_rev, bool *exception_handled) +{ + H5T_conv_ret_t except_ret = H5T_CONV_UNHANDLED; /* return of conversion exception callback function */ + 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 mant_msb = 0; /* most significant bit set in mantissa */ + int64_t expo; /* exponent */ + size_t msize = 0; /* useful size of mantissa in src */ + size_t mpos; /* offset to useful mant in src */ + size_t mrsh; /* amount to right shift mantissa */ + size_t implied; /* destination implied bits */ + bool denormalized = false; /* is either source or destination denormalized? */ + bool carry = false; /* carry after rounding mantissa */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER_PACKAGE + + assert(src_p); + assert(dst_p); + assert(s); + assert(d); + assert(conv_ctx); + assert(exception_handled); + + if (conv_ctx->u.conv.cb_struct.func) + assert(src_rev); + + *exception_handled = false; + + src_atomic = src_p->shared->parent->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + expo_max = ((hssize_t)1 << dst_atomic.u.f.esize) - 1; + + /* + * 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; + + /* Determine size of mantissa */ + if (0 == expo || H5T_NORM_NONE == src_atomic.u.f.norm) { + if ((mant_msb = H5T__bit_find(s, src_atomic.u.f.mpos, src_atomic.u.f.msize, H5T_BIT_MSB, true)) > 0) + msize = (size_t)mant_msb; + else if (0 == mant_msb) { + 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(mant_msb >= 0); + expo -= (int64_t)((src_atomic.u.f.ebias - 1) + (src_atomic.u.f.msize - (size_t)mant_msb)); + } + 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. + */ + mrsh = 0; + 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); + + 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_atomic.u.f.mpos, dst_atomic.u.f.msize, false); + msize = 0; + } + else if (except_ret == H5T_CONV_HANDLED) { + *exception_handled = true; + goto done; + } + 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. + */ + implied = 1; + mpos = src_atomic.u.f.mpos; + if (msize > 0 && mrsh <= dst_atomic.u.f.msize && mrsh + msize > dst_atomic.u.f.msize) { + mant_msb = (ssize_t)(mrsh + msize - dst_atomic.u.f.msize); + assert(mant_msb >= 0 && (size_t)mant_msb <= msize); + /* If the 1st bit being cut off is set and source isn't denormalized. */ + if (H5T__bit_get_d(s, (mpos + (size_t)mant_msb) - 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)mant_msb, msize - (size_t)mant_msb, H5T_BIT_LSB, false) >= + 0 || + expo < expo_max - 1)) { + carry = H5T__bit_inc(s, mpos + (size_t)mant_msb - 1, 1 + msize - (size_t)mant_msb); + if (carry) + implied = 2; + } + } + else if (H5T__bit_get_d(s, (mpos + (size_t)mant_msb) - 1, (size_t)1) && denormalized) + /* For either source or destination, denormalized value doesn't increment carry. */ + H5T__bit_inc(s, mpos + (size_t)mant_msb - 1, 1 + msize - (size_t)mant_msb); + } + 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) { + /* + * 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) { + 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) { + *exception_handled = true; + goto done; + } + else if (except_ret == H5T_CONV_ABORT) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); + } + } + + 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); + +done: + FUNC_LEAVE_NOAPI(ret_value) +} + +/*------------------------------------------------------------------------- + * 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? + */ + 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_compat + * + * Purpose: Performs a no-op conversion between a complex number type + * and an equivalent datatype. Complex number types are + * considered equivalent to the following: + * + * - An array datatype consisting of two elements where each + * element is of the same floating-point datatype as the + * complex number type's base floating-point datatype + * + * - A compound datatype consisting of two fields where each + * field is of the same floating-point datatype as the + * complex number type's base floating-point datatype. The + * compound datatype must not have any leading or trailing + * structure padding or any padding between its two fields. + * The fields must also have compatible names, must have + * compatible offsets within the datatype and must be in + * the order of "real" part -> "imaginary" part, such that + * the compound datatype matches the following representation: + * + * H5T_COMPOUND { + * "r(e)(a)(l)"; OFFSET 0 + * "i(m)(a)(g)(i)(n)(a)(r)(y)"; OFFSET SIZEOF("r(e)(a)(l)") + * } + * + * where "r(e)(a)(l)" means the field may be named any + * substring of "real", such as "r", or "re" and + * "i(m)(a)(g)(i)(n)(a)(r)(y)" means the field may be named + * any substring of "imaginary", such as "im" or "imag". + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_complex_compat(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, + const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t H5_ATTR_UNUSED nelmts, + size_t H5_ATTR_UNUSED buf_stride, size_t H5_ATTR_UNUSED bkg_stride, + void H5_ATTR_UNUSED *_buf, void H5_ATTR_UNUSED *bkg) +{ + H5T_t *compound_copy = NULL; + herr_t ret_value = SUCCEED; + + FUNC_ENTER_PACKAGE + + switch (cdata->command) { + case H5T_CONV_INIT: { + const H5T_t *complex_type; + const H5T_t *other_type; + + if (src->shared->type == H5T_COMPLEX) { + if (dst->shared->type != H5T_ARRAY && dst->shared->type != H5T_COMPOUND) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported destination datatype for conversion"); + complex_type = src; + other_type = dst; + } + else { + if (dst->shared->type != H5T_COMPLEX) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported destination datatype for conversion"); + complex_type = dst; + other_type = src; + } + + if (complex_type->shared->u.cplx.form != H5T_COMPLEX_RECTANGULAR) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported form of complex number datatype for conversion"); + + if (other_type->shared->type == H5T_ARRAY) { + if (other_type->shared->u.array.nelem != 2) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "array datatype doesn't have the correct number of elements for conversion"); + if (H5T_cmp(other_type->shared->parent, complex_type->shared->parent, false)) + HGOTO_ERROR( + H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "array datatype's base datatype doesn't match complex number type's base datatype"); + } + else { + H5T_cmemb_t *fields; + size_t name_len; + + assert(other_type->shared->type == H5T_COMPOUND); + + if (other_type->shared->u.compnd.nmembs != 2) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype doesn't have the correct number of fields for conversion"); + if (!other_type->shared->u.compnd.packed) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype fields aren't packed together"); + if (other_type->shared->u.compnd.memb_size != complex_type->shared->size) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype size doesn't match size of complex number datatype"); + + /* Make sure members are unsorted or sorted according to + * their offsets before checking their names + */ + if (other_type->shared->u.compnd.sorted == H5T_SORT_NONE || + other_type->shared->u.compnd.sorted == H5T_SORT_VALUE) + fields = other_type->shared->u.compnd.memb; + else { + /* Make a copy so the sort order of the original type isn't disturbed */ + if (NULL == (compound_copy = H5T_copy(other_type, H5T_COPY_TRANSIENT))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, FAIL, "can't copy datatype"); + + H5T__sort_value(compound_copy, NULL); + fields = compound_copy->shared->u.compnd.memb; + } + + /* Check "real" part of compound datatype */ + if (fields[0].offset != 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'real' field is not at offset 0"); + if (fields[0].size != complex_type->shared->parent->shared->size) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'real' field is not the same size as the complex number " + "datatype's base datatype"); + + /* Match up to 5 characters (including the NUL terminator) from the + * field name to a substring of "real". + */ + name_len = strlen(fields[0].name); + if (strncmp(fields[0].name, "real", (name_len < 5) ? name_len : 5)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'real' field name ('%s') didn't match an expected name " + "for conversion", + fields[0].name); + + if (H5T_cmp(fields[0].type, complex_type->shared->parent, false)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'real' field is not the same datatype as the complex " + "number datatype's base datatype"); + + /* Check "imaginary" part of compound datatype */ + if (fields[1].offset != fields[0].size) + HGOTO_ERROR( + H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'imaginary' field is not at offset 'sizeof(real_field)'"); + if (fields[1].size != complex_type->shared->parent->shared->size) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'imaginary' field is not the same size as the complex " + "number datatype's base datatype"); + + /* Match up to 10 characters (including the NUL terminator) from the + * field name to a substring of "imaginary". + */ + name_len = strlen(fields[1].name); + if (strncmp(fields[1].name, "imaginary", (name_len < 10) ? name_len : 10)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'imaginary' field name ('%s') didn't match an expected " + "name for conversion", + fields[1].name); + + if (H5T_cmp(fields[1].type, complex_type->shared->parent, false)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "compound datatype's 'imaginary' field is not the same datatype as the " + "complex number datatype's base datatype"); + } + + cdata->need_bkg = H5T_BKG_NO; + + break; + } + + case H5T_CONV_FREE: + break; + + case H5T_CONV_CONV: + /* no-op as the types should be equivalent */ + break; + + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } + +done: + if (compound_copy && H5T_close(compound_copy) < 0) + HDONE_ERROR(H5E_DATATYPE, H5E_CANTCLOSEOBJ, FAIL, "can't close datatype"); + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_complex_compat() */ + +#ifdef H5_HAVE_COMPLEX_NUMBERS +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_schar + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, signed char, SCHAR_MIN, SCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_uchar + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, unsigned char, 0, UCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_short + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, short, SHRT_MIN, SHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ushort + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, unsigned short, 0, USHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_int + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, int, INT_MIN, INT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_uint + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, unsigned int, 0, UINT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_long + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, long, LONG_MIN, LONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ulong + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, unsigned long, 0, ULONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_llong + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, long long, LLONG_MIN, LLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ullong + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_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' / `_Fcomplex' 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, H5_float_complex, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} +#endif + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_float + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, float, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_double + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_ldouble + * + * Purpose: Converts `float _Complex' / `_Fcomplex' 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, H5_float_complex, long double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_dcomplex + * + * Purpose: Converts `float _Complex' / `_Fcomplex' to + * `double _Complex' / `_Dcomplex' + * + * 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, H5_float_complex, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_fcomplex_lcomplex + * + * Purpose: Converts `float _Complex' / `_Fcomplex' to + * `long double _Complex' / `_Lcomplex' + * + * 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, H5_float_complex, H5_ldouble_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_schar + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, signed char, SCHAR_MIN, SCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_uchar + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, unsigned char, 0, UCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_short + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, short, SHRT_MIN, SHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ushort + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, unsigned short, 0, USHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_int + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, int, INT_MIN, INT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_uint + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, unsigned int, 0, UINT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_long + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, long, LONG_MIN, LONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ulong + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, unsigned long, 0, ULONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_llong + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, long long, LLONG_MIN, LLONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ullong + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_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' / `_Dcomplex' 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, H5_double_complex, H5__Float16, -FLT16_MAX, FLT16_MAX); + H5_GCC_CLANG_DIAG_ON("pedantic") +} +#endif + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_float + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, float, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_double + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_ldouble + * + * Purpose: Converts `double _Complex' / `_Dcomplex' 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, H5_double_complex, long double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_fcomplex + * + * Purpose: Converts `double _Complex' / `_Dcomplex' to + * `float _Complex' / `_Fcomplex' + * + * 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, H5_double_complex, H5_float_complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_dcomplex_lcomplex + * + * Purpose: Converts `double _Complex' / `_Dcomplex' to + * `long double _Complex' / `_Lcomplex' + * + * 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, H5_double_complex, H5_ldouble_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_schar + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, signed char, SCHAR_MIN, SCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_uchar + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, unsigned char, 0, UCHAR_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_short + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, short, SHRT_MIN, SHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_ushort + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, unsigned short, 0, USHRT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_int + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, int, INT_MIN, INT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_uint + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, unsigned int, 0, UINT_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_long + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, long, LONG_MIN, LONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_ulong + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, unsigned long, 0, ULONG_MAX); + H5_GCC_CLANG_DIAG_ON("float-equal") +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_llong + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_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' / `_Lcomplex' 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, H5_ldouble_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' / `_Lcomplex' 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, H5_ldouble_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' / `_Lcomplex' 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, H5_ldouble_complex, float, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_double + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, double, -DBL_MAX, DBL_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_ldouble + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, long double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_fcomplex + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' to + * `float _Complex' / `_Fcomplex' + * + * 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, H5_ldouble_complex, H5_float_complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_lcomplex_dcomplex + * + * Purpose: Converts `long double _Complex' / `_Lcomplex' to + * `double _Complex' / `_Dcomplex' + * + * 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, H5_ldouble_complex, H5_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..604f04576cc --- /dev/null +++ b/src/H5Tconv_complex.h @@ -0,0 +1,214 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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_compat(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' / '_Fcomplex' */ +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' / '_Dcomplex' */ +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' / '_Lcomplex' */ +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); +#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG +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); +#endif +#ifdef H5T_CONV_INTERNAL_LDOUBLE_ULLONG +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); +#endif +#if defined(H5_HAVE__FLOAT16) && defined(H5T_CONV_INTERNAL_LDOUBLE_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 165c360ac4b..b7231657281 100644 --- a/src/H5Tconv_float.c +++ b/src/H5Tconv_float.c @@ -25,6 +25,8 @@ #include "H5private.h" /* Generic Functions */ #include "H5Tconv.h" /* Datatype conversions */ #include "H5Tconv_macros.h" +#include "H5Tconv_complex.h" +#include "H5Tconv_integer.h" #include "H5Tconv_float.h" /*------------------------------------------------------------------------- @@ -43,54 +45,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; @@ -101,524 +83,629 @@ 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; + break; - /* - * 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 + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } - /* - * 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); +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_f_f() */ - for (i = 0; i < tsize; i += 4) { - tmp1 = s[i]; - tmp2 = s[i + 1]; +/*------------------------------------------------------------------------- + * 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; - s[i] = s[(tsize - 2) - i]; - s[i + 1] = s[(tsize - 1) - i]; + FUNC_ENTER_PACKAGE - s[(tsize - 2) - i] = tmp1; - s[(tsize - 1) - i] = tmp2; - } - } + 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); - /* - * 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; + /* 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. + */ + } + + /* + * 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 (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 (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 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); + 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 == 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); - } - 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 @@ -636,49 +723,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; @@ -689,602 +760,627 @@ 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; + + FUNC_ENTER_PACKAGE + + 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); + + 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; - } - else { - s = sp; - d = elmtno + olap >= nelmts ? 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); } -#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 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); } - 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.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); + + 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); + } - for (i = 0; i < tsize; i += 4) { - tmp1 = s[i]; - tmp2 = s[i + 1]; + 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); - s[i] = s[(tsize - 2) - i]; - s[i + 1] = s[(tsize - 1) - i]; + 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); + + /* 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); - /* - * 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; + 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? + */ + 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 /*------------------------------------------------------------------------- @@ -1513,6 +1609,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' / `_Fcomplex' + * + * 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv__Float16_dcomplex + * + * Purpose: Converts `_Float16' to `double _Complex' / `_Dcomplex' + * + * 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv__Float16_lcomplex + * + * Purpose: Converts `_Float16' to `long double _Complex' / `_Lcomplex' + * + * 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, H5_ldouble_complex, -, -); +} +#endif #endif /*------------------------------------------------------------------------- @@ -1774,6 +1923,65 @@ 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' / `_Fcomplex' 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_float_dcomplex + * + * Purpose: Convert native `float' to native + * `double _Complex' / `_Dcomplex' 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_float_lcomplex + * + * Purpose: Convert native `float' to native + * `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_double_schar * @@ -2033,6 +2241,65 @@ 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' / `_Fcomplex' 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, H5_float_complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_double_dcomplex + * + * Purpose: Convert native `double' to native + * `double _Complex' / `_Dcomplex' 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_double_lcomplex + * + * Purpose: Convert native `double' to native + * `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_ldouble_schar * @@ -2297,3 +2564,62 @@ 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' / `_Fcomplex' 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, H5_float_complex, -FLT_MAX, FLT_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ldouble_dcomplex + * + * Purpose: Convert native `long double' to native + * `double _Complex' / `_Dcomplex' 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, H5_double_complex, -DBL_MAX, DBL_MAX); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ldouble_lcomplex + * + * Purpose: Convert native `long double' to native + * `long double _Complex' / `_Lcomplex' 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, H5_ldouble_complex, -, -); +} +#endif diff --git a/src/H5Tconv_float.h b/src/H5Tconv_float.h index b5ec3062856..e5413fc0d22 100644 --- a/src/H5Tconv_float.h +++ b/src/H5Tconv_float.h @@ -16,10 +16,40 @@ /* Private headers needed by this file */ #include "H5Tpkg.h" +/*************************/ +/* Module private macros */ +/*************************/ + +#define TEMP_FLOAT_CONV_BUFFER_SIZE 64 + +/****************************/ +/* Library Private Typedefs */ +/****************************/ + +/* floating-point value type (regular, +/-0, +/-Inf, NaN) */ +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 +63,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 +112,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 +167,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 +221,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 +277,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 01808ab5dd6..b2af085c064 100644 --- a/src/H5Tconv_integer.c +++ b/src/H5Tconv_integer.c @@ -119,7 +119,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++) { @@ -199,8 +201,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, @@ -235,8 +237,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, @@ -263,8 +265,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, @@ -296,8 +298,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, @@ -344,8 +346,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, @@ -387,8 +389,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, @@ -476,425 +478,537 @@ 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 */ + 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; FUNC_ENTER_PACKAGE - 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; - - 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"); - - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; + 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); + + 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) { + size_t half_size = dst_p->shared->size / 2; + + if (H5T_FLOAT == dst_p->shared->type) { + for (size_t i = 0; i < half_size; i++) + H5_SWAP_BYTES(d, i, dst_p->shared->size - (i + 1)); + } + else { + for (size_t i = 0; i < half_size / 2; i++) + H5_SWAP_BYTES(d, i, half_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 @@ -1122,6 +1236,65 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_schar_dcomplex + * + * Purpose: Convert native signed char to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_schar_lcomplex + * + * Purpose: Convert native signed char to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_uchar_schar * @@ -1348,6 +1521,65 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uchar_dcomplex + * + * Purpose: Convert native unsigned char to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uchar_lcomplex + * + * Purpose: Convert native unsigned char to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_short_schar * @@ -1574,6 +1806,65 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_short_dcomplex + * + * Purpose: Convert native short to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_short_lcomplex + * + * Purpose: Convert native short to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_ushort_schar * @@ -1782,26 +2073,85 @@ H5T__conv_ushort_double(const H5T_t *st, const H5T_t *dt, H5T_cdata_t *cdata, co 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, DOUBLE, unsigned short, double, -, -); + H5T_CONV_xF(USHORT, DOUBLE, unsigned short, double, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ushort_ldouble + * + * Purpose: Convert native unsigned short to native long double using + * hardware. This is a fast special case. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_ushort_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_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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ushort_dcomplex + * + * Purpose: Convert native unsigned short to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); } /*------------------------------------------------------------------------- - * Function: H5T__conv_ushort_ldouble + * Function: H5T__conv_ushort_lcomplex * - * Purpose: Convert native unsigned short to native long double using - * hardware. This is a fast special case. + * Purpose: Convert native unsigned short to native + * long double _Complex / _Lcomplex using hardware. This is a + * fast special case. * * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ herr_t -H5T__conv_ushort_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_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_xF(USHORT, LDOUBLE, unsigned short, long double, -, -); + H5T_CONV_xZ(USHORT, LDOUBLE_COMPLEX, unsigned short, H5_ldouble_complex, -, -); } +#endif /*------------------------------------------------------------------------- * Function: H5T__conv_int_schar @@ -2032,6 +2382,65 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_int_dcomplex + * + * Purpose: Convert native integer to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_int_lcomplex + * + * Purpose: Convert native integer to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_uint_schar * @@ -2261,6 +2670,65 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uint_dcomplex + * + * Purpose: Convert native unsigned integer to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_uint_lcomplex + * + * Purpose: Convert native unsigned integer to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_long_schar * @@ -2490,6 +2958,65 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_long_dcomplex + * + * Purpose: Convert native long to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_long_lcomplex + * + * Purpose: Convert native long to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_ulong_schar * @@ -2719,6 +3246,65 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ulong_dcomplex + * + * Purpose: Convert native unsigned long to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ulong_lcomplex + * + * Purpose: Convert native unsigned long to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif + /*------------------------------------------------------------------------- * Function: H5T__conv_llong_schar * @@ -2950,6 +3536,67 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_llong_dcomplex + * + * Purpose: Convert native long long to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE +/*------------------------------------------------------------------------- + * Function: H5T__conv_llong_lcomplex + * + * Purpose: Convert native long long to native + * long double _Complex / _Lcomplex 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, H5_ldouble_complex, -, -); +} +#endif /* H5T_CONV_INTERNAL_LLONG_LDOUBLE */ +#endif /* H5_HAVE_COMPLEX_NUMBERS */ + /*------------------------------------------------------------------------- * Function: H5T__conv_ullong_schar * @@ -3180,3 +3827,64 @@ 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 / _Fcomplex 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, H5_float_complex, -, -); +} + +/*------------------------------------------------------------------------- + * Function: H5T__conv_ullong_dcomplex + * + * Purpose: Convert native unsigned long long to native + * double _Complex / _Dcomplex 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, H5_double_complex, -, -); +} + +#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE +/*------------------------------------------------------------------------- + * Function: H5T__conv_ullong_lcomplex + * + * Purpose: Convert native unsigned long long to native + * long double _Complex / _Lcomplex 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, H5_ldouble_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 dbebfd4393f..22dee8c5979 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,19 @@ 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); +#ifdef H5T_CONV_INTERNAL_LLONG_LDOUBLE +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 +#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 +581,18 @@ 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); +#ifdef H5T_CONV_INTERNAL_ULLONG_LDOUBLE +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 #endif /* H5Tconv_integer_H */ diff --git a/src/H5Tconv_macros.h b/src/H5Tconv_macros.h index 33be7544bac..843255e51cc 100644 --- a/src/H5Tconv_macros.h +++ b/src/H5Tconv_macros.h @@ -99,8 +99,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 +118,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 +853,564 @@ 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)); + +/* + * Since MSVC defines complex numbers as structure types, they can't be cast + * directly to other types, so we have to simulate the behavior of the standard + * types here. When casting to a complex number type, a new complex number + * value is constructed from the given real and imaginary parts. When casting + * from a complex number type, the real and imaginary parts are extracted as + * needed and used as appropriate. With other platforms/compilers, the + * H5T_CONV_CAST_Z macro just maps this to direct casts. + */ +#ifndef H5_HAVE_C99_COMPLEX_NUMBERS +#define H5T_CONV_CAST_TO_FLOAT_COMPLEX(S_REAL, S_IMAG, D, DT) \ + { \ + *(D) = H5_CMPLXF(S_REAL, S_IMAG); \ + } +#define H5T_CONV_CAST_TO_DOUBLE_COMPLEX(S_REAL, S_IMAG, D, DT) \ + { \ + *(D) = H5_CMPLX(S_REAL, S_IMAG); \ + } +#define H5T_CONV_CAST_TO_LDOUBLE_COMPLEX(S_REAL, S_IMAG, D, DT) \ + { \ + *(D) = H5_CMPLXL(S_REAL, S_IMAG); \ + } + +#define H5T_CONV_CAST_zZ(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + H5T_CONV_##STYPE##_IMAGVAL(S); /* Extract "imaginary" part of complex number */ \ + H5T_CONV_CAST_TO_##DTYPE(sr_val, si_val, D, DT) \ + } +#define H5T_CONV_CAST_Zz(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_CAST_TO_##DTYPE(S_REAL, S_IMAG, D, DT) \ + } +#define H5T_CONV_CAST_zF(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + *(D) = (DT)(sr_val); \ + } +#define H5T_CONV_CAST_zf(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + *(D) = (DT)(sr_val); \ + } +#define H5T_CONV_CAST_zX(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_##STYPE##_REALVAL(S); /* Extract "real" part of complex number */ \ + *(D) = (DT)(sr_val); \ + } +#define H5T_CONV_CAST_fZ(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT) \ + } +#define H5T_CONV_CAST_Fz(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT) \ + } +#define H5T_CONV_CAST_fz(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT) \ + } +#define H5T_CONV_CAST_xZ(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + { \ + H5T_CONV_CAST_TO_##DTYPE(*(S), (ST)0.0, D, DT) \ + } + +#define H5T_CONV_CAST_Z(SYMBOLS, STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + do { \ + H5T_CONV_CAST_##SYMBOLS(STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + } while (0) + +#else + +/* Map all complex number casts to direct casts */ +#define H5T_CONV_CAST_Z(SYMBOLS, STYPE, DTYPE, S, S_REAL, S_IMAG, D, ST, DT) \ + do { \ + *(D) = (DT)(*(S)); \ + } while (0) + +#endif + +#define H5T_CONV_zZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + H5T_CONV_CAST_Z(zZ, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#define H5T_CONV_zZ_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_zZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) + +/* Identical logic to H5T_CONV_fF, but special implementation is needed + * here to deal with MSVC's complex number structure types. + */ +#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, 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) \ + H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, S, sr_val, si_val, D, ST, DT); \ + 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); \ + \ + H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, (DT *)tmp_val, tmp_val[0], tmp_val[1], D, ST, DT); \ + } \ + 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) \ + H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, S, sr_val, si_val, D, ST, DT); \ + 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); \ + \ + H5T_CONV_CAST_Z(Zz, STYPE, DTYPE, (DT *)tmp_val, tmp_val[0], tmp_val[1], D, ST, DT); \ + } \ + } +#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) + +#define H5T_CONV_zF_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + H5T_CONV_CAST_Z(zF, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#define H5T_CONV_zF_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_zF_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) + +/* Identical logic to H5T_CONV_fF, but special implementation is needed + * here to deal with MSVC's complex number structure types. + */ +#define H5T_CONV_zF(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + H5T_CONV(H5T_CONV_zF, 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) + +#define H5T_CONV_fZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + H5T_CONV_CAST_Z(fZ, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#define H5T_CONV_fZ_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_fZ_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) + +/* Identical logic to H5T_CONV_fF, but special implementation is needed + * here to deal with MSVC's complex number structure types. + */ +#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) + +#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 \ + H5T_CONV_CAST_Z(Fz, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#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 \ + H5T_CONV_CAST_Z(Fz, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } + +/* 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 { \ + H5T_CONV(H5T_CONV_Fz, STYPE, DTYPE, ST, DT, D_MIN, D_MAX, N) \ + } while (0) + +#define H5T_CONV_zf_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + H5T_CONV_CAST_Z(zf, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#define H5T_CONV_zf_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_zf_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) + +/* 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. + * Special implementation is needed here to deal with MSVC's complex number + * structure types. + */ +#define H5T_CONV_zf(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) == (2 * sizeof(DT))); \ + H5T_CONV(H5T_CONV_zf, 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) \ + { \ + H5T_CONV_CAST_Z(fz, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#define H5T_CONV_fz_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_fz_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) + +/* 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). Special + * implementation is needed here to deal with MSVC's complex number structure types. + */ +#define H5T_CONV_fz(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert((2 * sizeof(ST)) == sizeof(DT)); \ + H5T_CONV(H5T_CONV_fz, 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*/ \ + H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT); \ + 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 \ + H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } \ + else \ + H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#define H5T_CONV_xZ_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + H5T_CONV_CAST_Z(xZ, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } + +/* 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) + +#define H5T_CONV_zX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + { \ + H5T_CONV_CAST_Z(zX, STYPE, DTYPE, S, -, -, D, ST, DT); \ + } +#define H5T_CONV_zX_NOEX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) \ + H5T_CONV_zX_CORE(STYPE, DTYPE, S, D, ST, DT, D_MIN, D_MAX) + +/* Identical logic to H5T_CONV_fX, but special implementation is needed + * here to deal with MSVC's complex number structure types. + */ +#define H5T_CONV_zX(STYPE, DTYPE, ST, DT, D_MIN, D_MAX) \ + do { \ + HDcompile_assert(sizeof(ST) <= sizeof(DT)); \ + H5T_CONV(H5T_CONV_zX, 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, foH5T_CONV_zX(r 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 +1438,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 5f6c35f127b..8c5af35ef1e 100644 --- a/src/H5Tconv_vlen.c +++ b/src/H5Tconv_vlen.c @@ -57,7 +57,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. * @@ -101,6 +101,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 d54422a626c..7308279b35b 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, ", homogeneous"); + 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 2b6ab80a62c..87d1a9068b8 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 fab2159bb52..2a7c9030145 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 139414fcf78..266516478de 100644 --- a/src/H5Tmodule.h +++ b/src/H5Tmodule.h @@ -71,7 +71,7 @@ * An HDF5 datatype describes one specific layout of bits. A dataset has a single datatype which * applies to every data element. When a dataset is created, the storage datatype is defined. After * the dataset or attribute is created, the datatype cannot be changed. - * \li The datatype describes the storage layout of a singledata element + * \li The datatype describes the storage layout of a single data element * \li All elements of the dataset must have the same type * \li The datatype of a dataset is immutable * @@ -168,6 +168,8 @@ * \li Compound datatypes: structured records * \li Array: a multidimensional array of a datatype * \li Variable-length: a one-dimensional array of a datatype + * \li Enumeration: a set of (name, value) pairs, similar to the C/C++ enum type + * \li Complex: an aggregate of two similar floating-point datatypes * *
Predefined Standard Datatypes
C-style long double
#H5T_NATIVE_FLOAT_COMPLEXC-style float _Complex (MSVC _Fcomplex) (May be H5I_INVALID_HID if platform doesn't support float _Complex / _Fcomplex type)
#H5T_NATIVE_DOUBLE_COMPLEXC-style double _Complex (MSVC _Dcomplex) (May be H5I_INVALID_HID if platform doesn't support double _Complex / _Dcomplex type)
#H5T_NATIVE_LDOUBLE_COMPLEXC-style long double _Complex (MSVC _Lcomplex) (May be H5I_INVALID_HID if platform doesn't support long double _Complex / _Lcomplex type)
#H5T_NATIVE_B8 8-bit bitfield based on native types
* @@ -199,7 +201,7 @@ * - * * + * + * + * + * + * + * *
* Description * + * * Properties * @@ -351,6 +353,20 @@ * * *
+ * Complex + * + * Data elements of two floating point numbers + * + * Base floating point datatype + * + * Other properties inherited from base floating point datatype + *
* * \subsubsection subsubsec_datatype_model_predefine Predefined Datatypes @@ -745,6 +761,30 @@ * * * + * #H5T_NATIVE_FLOAT_COMPLEX + * + * + * float _Complex (MSVC _Fcomplex) + * + * + * + * + * #H5T_NATIVE_DOUBLE_COMPLEX + * + * + * double _Complex (MSVC _Dcomplex) + * + * + * + * + * #H5T_NATIVE_LDOUBLE_COMPLEX + * + * + * long double _Complex (MSVC _Lcomplex) + * + * + * + * * #H5T_NATIVE_HSIZE * * @@ -1005,12 +1045,51 @@ * \ref hid_t \ref H5Tcreate (\ref H5T_class_t class, size_t size) * * - * Create a new datatype object of datatype class . The following datatype classes care supported - * with this function: + * Create a new datatype object of the specified datatype class with the specified size. This + * function is only used with the following datatype classes: * \li #H5T_COMPOUND * \li #H5T_OPAQUE * \li #H5T_ENUM - * \li Other datatypes are created with \ref H5Tcopy(). + * \li #H5T_STRING + * \li Other datatypes are created with a specialized datatype creation function such as + * \ref H5Tarray_create2 or are copied from an existing predefined datatype with \ref H5Tcopy(). + * + * + * + * + * \ref hid_t \ref H5Tarray_create2 (\ref hid_t base_id, unsigned ndims, const \ref hsize_t dim[]); + * + * + * Create a new array datatype object. \p base_id is the datatype of every element of the array, i.e., + * of the number at each position in the array. \p ndims is the number of dimensions and the size of + * each dimension is specified in the array \p dim. + * + * + * + * + * \ref hid_t \ref H5Tvlen_create (\ref hid_t base_id); + * + * + * Create a new one-dimensional variable-length array datatype object. \p base_id is the datatype of + * every element of the array. + * + * + * + * + * \ref hid_t \ref H5Tenum_create (\ref hid_t base_id); + * + * + * Create a new enumeration datatype object. \p base_id is the datatype of every element of the + * enumeration datatype. + * + * + * + * + * \ref hid_t \ref H5Tcomplex_create (\ref hid_t base_type_id); + * + * + * Create a new complex number datatype object. \p base_type_id is the datatype of both parts + * of the complex number datatype and must be a floating point datatype. * * * @@ -1044,7 +1123,8 @@ * * * Releases resources associated with a datatype obtained from \ref H5Tcopy, \ref H5Topen, or - * \ref H5Tcreate. It is illegal to close an immutable transient datatype (for example, predefined types). + * \ref H5Tcreate / \ref H5Tarray_create2 / etc. It is illegal to close an immutable transient + * datatype (for example, predefined types). * * * @@ -1075,12 +1155,12 @@ * * * - * In order to use a datatype, the object must be created (\ref H5Tcreate), or a reference obtained by - * cloning from an existing type (\ref H5Tcopy), or opened (\ref H5Topen). In addition, a reference to the - * datatype of a dataset or attribute can be obtained with \ref H5Dget_type or \ref H5Aget_type. For - * composite datatypes a reference to the datatype for members or base types can be obtained - * (\ref H5Tget_member_type, \ref H5Tget_super). When the datatype object is no longer needed, the - * reference is discarded with \ref H5Tclose. + * In order to use a datatype, the object must be created (\ref H5Tcreate / \ref H5Tarray_create2 / etc.), + * or a reference obtained by cloning from an existing type (\ref H5Tcopy), or opened (\ref H5Topen). + * In addition, a reference to the datatype of a dataset or attribute can be obtained with + * \ref H5Dget_type or \ref H5Aget_type. For composite datatypes a reference to the datatype for + * members or base types can be obtained (\ref H5Tget_member_type, \ref H5Tget_super). When the datatype + * object is no longer needed, the reference is discarded with \ref H5Tclose. * * Two datatype objects can be tested to see if they are the same with \ref H5Tequal. This function * returns true if the two datatype references refer to the same datatype object. However, if two @@ -1088,7 +1168,7 @@ * they will not be considered ‘equal’. * * A datatype can be written to the file as a first class object (\ref H5Tcommit). This is a committed - * datatype and can be used in thesame way as any other datatype. + * datatype and can be used in the same way as any other datatype. * * \subsubsection subsubsec_datatype_program_discover Discovery of Datatype Properties * Any HDF5 datatype object can be queried to discover all of its datatype properties. For each @@ -1115,7 +1195,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 * * * @@ -1473,6 +1553,14 @@ * #H5Tvlen_create * * + * + * + * COMPLEX + * + * + * #H5Tcomplex_create + * + * * * * Once the datatype is created and the datatype properties set, the datatype object can be used. @@ -2408,7 +2496,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 @@ -2691,7 +2780,7 @@ filled according to the value of this property. The padding can be: * * * - * An array datatype may be multi-dimensional with 1 to #H5S_MAX_RANK(the maximum rank + * An array datatype may be multi-dimensional with 1 to #H5S_MAX_RANK (the maximum rank * of a dataset is currently 32) dimensions. The dimensions can be any size greater than 0, but * unlimited dimensions are not supported (although the datatype can be a variable-length datatype). * @@ -2727,7 +2816,7 @@ filled according to the value of this property. The padding can be: * * A variable-length (VL) datatype is a one-dimensional sequence of a datatype which are not fixed * in length from one dataset location to another. In other words, each data element may have a - * different number of members. Variable-length datatypes cannot be divided;the entire data + * different number of members. Variable-length datatypes cannot be divided; the entire data * element must be transferred. * * VL datatypes are useful to the scientific community in many different ways, possibly including: @@ -2780,14 +2869,14 @@ filled according to the value of this property. The padding can be: * data is laid out in memory. * * An analogous procedure must be used to read the data. See the second example below. An - * appropriate array of vl_t must be allocated, and the data read. It is then traversed one data - * element at a time. The #H5Dvlen_reclaim call frees the data buffer for the buffer. With each + * appropriate array of hvl_t must be allocated, and the data read. It is then traversed one data + * element at a time. The #H5Treclaim call frees the data buffer for the buffer. With each * element possibly being of different sequence lengths for a dataset with a VL datatype, the * memory for the VL datatype must be dynamically allocated. Currently there are two methods of * managing the memory for VL datatypes: the standard C malloc/free memory allocation routines * or a method of calling user-defined memory management routines to allocate or free memory * (set with #H5Pset_vlen_mem_manager). Since the memory allocated when reading (or writing) - * may be complicated to release, the #H5Dvlen_reclaim function is provided to traverse a memory + * may be complicated to release, the #H5Treclaim function is provided to traverse a memory * buffer and free the VL datatype information without leaking memory. * * Write VL data @@ -2815,7 +2904,7 @@ filled according to the value of this property. The padding can be: * printf(“ value: %u\n”,((unsigned int *)rdata[i].p)[j]); * } * } - * ret = H5Dvlen_reclaim(tid1, sid1, xfer_pid, rdata); + * ret = H5Treclaim(tid1, sid1, xfer_pid, rdata); * \endcode * * @@ -2827,10 +2916,10 @@ filled according to the value of this property. The padding can be: *
    * * The user program must carefully manage these relatively complex data structures. The - * #H5Dvlen_reclaim function performs a standard traversal, freeing all the data. This function + * #H5Treclaim function performs a standard traversal, freeing all the data. This function * analyzes the datatype and dataspace objects, and visits each VL data element, recursing through - * nested types. By default, the system free is called for the pointer in each vl_t. Obviously, this - * call assumes that all of this memory was allocated with the system malloc. + * nested types. By default, the system free is called for the pointer in each hvl_t. Obviously, + * this call assumes that all of this memory was allocated with the system malloc. * * The user program may specify custom memory manager routines, one for allocating and one for * freeing. These may be set with the #H5Pset_vlen_mem_manager, and must have the following @@ -2853,6 +2942,44 @@ filled according to the value of this property. The padding can be: * destination storage (memory). The size value is adjusted for data conversion and alignment in the * destination. * + *

    Complex

    + * + * A complex number datatype represents complex number data elements which consist of two floating + * point parts. Complex number datatypes cannot be divided for I/O; the entire data element must be + * transferred. + * + * A complex number datatype is created by calling #H5Tcomplex_create with a specified base floating + * point datatype. The example below shows code that creates a complex number datatype of 16-bit + * floating point values. + * + * Create a complex number datatype of 2 IEEE little-endian 16-bit floating point values + * \code + * tid1 = H5Tcomplex_create (H5T_IEEE_F16LE); + * + * dataset = H5Dcreate(fid1, “Dataset1”, tid1, sid1, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + * \endcode + * + * Data element storage of a complex number datatype + * + * Each part of a data element with a complex number datatype is stored contiguously. Complex number + * datatypes have the same storage representation as an array datatype of 2 elements of a floating + * point datatype or a compound datatype with 2 fields and no structure padding, where each field + * is of the same floating point datatype. Thus, the following representations are equivalent: + * + * \code + * float _Complex data; + * \endcode + * \code + * float data[2]; + * \endcode + * \code + * struct + * { + * float real; + * float imaginary; + * } data; + * \endcode + * * \subsection subsec_datatype_other Other Non-numeric Datatypes * Several datatype classes define special types of objects. * @@ -2917,13 +3044,13 @@ filled according to the value of this property. The padding can be: * is fast to access, but can waste storage space if the length of the Strings varies. * * A third alternative is to use a variable-length datatype. See item c in the figure above. This can - * be done using the standard mechanisms described above. The program would use vl_t structures + * be done using the standard mechanisms described above. The program would use hvl_t structures * to write and read the data. * * A fourth alternative is to use a special feature of the string datatype class to set the size of the * datatype to #H5T_VARIABLE. See item c in the figure above. The example below shows a * declaration of a datatype of type #H5T_C_S1 which is set to #H5T_VARIABLE. The HDF5 - * Library automatically translates between this and the vl_t structure. Note: the #H5T_VARIABLE + * Library automatically translates between this and the hvl_t structure. Note: the #H5T_VARIABLE * size can only be used with string datatypes. * * Set the string datatype size to H5T_VARIABLE @@ -2945,7 +3072,7 @@ filled according to the value of this property. The padding can be: * printf(“%d: len: %d, str is: %s\n”, i, strlen(rdata[i]), rdata[i]); * } * - * ret = H5Dvlen_reclaim(tid1, sid1, xfer_pid, rdata); + * ret = H5Treclaim(tid1, sid1, xfer_pid, rdata); * \endcode * * \subsubsection subsubsec_datatype_other_refs Reference @@ -3804,12 +3931,13 @@ filled according to the value of this property. The padding can be: * datatypes. * * The currently supported text format used by #H5LTtext_to_dtype and #H5LTdtype_to_text is the - * data description language (DDL) and conforms to the \ref DDLBNF114. The portion of the - * \ref DDLBNF114 that defines HDF5 datatypes appears below. + * data description language (DDL) and conforms to the \ref DDLBNF200. The portion of the + * \ref DDLBNF200 that defines HDF5 datatypes appears below. * * The definition of HDF5 datatypes from the HDF5 DDL * \code - * ::= | | | + * ::= | | | | + * * * ::= | |