From 11d6a348c24a8be58b9639b3e823f3b8653cd212 Mon Sep 17 00:00:00 2001 From: Jordan Henderson Date: Fri, 3 May 2024 11:30:44 -0500 Subject: [PATCH] Implement support for complex number datatypes Adds the new datatype class H5T_COMPLEX Adds the new API function H5Tcomplex_create which creates a complex number datatype from an ID of a base floating-point datatype Adds the new feature check macros H5_HAVE_COMPLEX_NUMBERS and H5_HAVE_C99_COMPLEX_NUMBERS Adds the new datatype size macros H5_SIZEOF_FLOAT_COMPLEX, H5_SIZEOF_DOUBLE_COMPLEX and H5_SIZEOF_LONG_DOUBLE_COMPLEX Adds the new datatype ID macros H5T_NATIVE_FLOAT_COMPLEX, H5T_NATIVE_DOUBLE_COMPLEX, H5T_NATIVE_LDOUBLE_COMPLEX, H5T_CPLX_IEEE_F16LE, H5T_CPLX_IEEE_F16BE, H5T_CPLX_IEEE_F32LE, H5T_CPLX_IEEE_F32BE, H5T_CPLX_IEEE_F64LE and H5T_CPLX_IEEE_F64BE Adds hard and soft datatype conversion paths between complex number datatypes and all the integer and floating-point datatypes, as well as between other complex number datatypes Adds a special conversion path 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 converted directly Adds support for complex number datatypes to the h5dump, h5ls and h5diff/ph5diff tools. Allows h5dump '-m' option to change floating-point printing format for float complex and double complex datatypes, as well as long double complex if it has the same size as double complex Adds minimal support to the h5watch and h5import tools Adds support for the predefined complex number datatypes and H5Tcomplex_create function to the Java wrappers. Also adds initial, untested support to the JNI for future use with HDFView Adds support for just the H5T_COMPLEX datatype class to the Fortran wrappers Adds support for the predefined complex number datatypes and H5Tcomplex_create function to the high level library H5LT interface for use with the H5LTtext_to_dtype and H5LTdtype_to_text functions Changes some usages of "complex" in the library since it conflicts with the "complex" keyword from the complex.h header. Also changes various usages of the word "complex" throughout the library to distinguish compound datatypes from complex datatypes. --- HDF5Examples/C/H5T/116/h5ex_t_complex.c | 137 + .../C/H5T/116/h5ex_t_complex_custom.c | 145 + HDF5Examples/C/H5T/116/h5ex_t_complex_msvc.c | 138 + HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java | 3 +- c++/test/tattr.cpp | 8 +- config/cmake/ConfigureChecks.cmake | 66 + config/cmake/H5pubconf.h.in | 18 + config/cmake/HDFTests.c | 62 + configure.ac | 52 + doxygen/aliases | 2 +- doxygen/dox/DDLBNF116.dox | 667 ++ doxygen/dox/IntroHDF5.dox | 2 +- doxygen/dox/LearnBasics1.dox | 4 +- doxygen/dox/PredefinedDatatypeTables.dox | 4 + doxygen/dox/Specifications.dox | 1 + doxygen/examples/H5.format.html | 133 + .../examples/tables/predefinedDatatypes.dox | 47 + fortran/src/H5Tf.c | 15 +- fortran/src/H5Tff.F90 | 6 +- fortran/src/H5_f.c | 1 + fortran/src/H5_ff.F90 | 3 +- fortran/src/H5f90global.F90 | 2 + hl/src/H5LT.c | 43 + hl/src/H5LTanalyze.c | 525 +- hl/src/H5LTanalyze.l | 11 + hl/src/H5LTparse.c | 896 +- hl/src/H5LTparse.h | 56 +- hl/src/H5LTparse.y | 20 + hl/test/test_lite.c | 223 + hl/tools/h5watch/h5watch.c | 33 +- java/src/hdf/hdf5lib/H5.java | 29 + java/src/hdf/hdf5lib/HDF5Constants.java | 40 + java/src/jni/h5Constants.c | 50 + java/src/jni/h5aImp.c | 42 +- java/src/jni/h5dImp.c | 42 +- java/src/jni/h5tImp.c | 19 + java/src/jni/h5tImp.h | 7 + java/src/jni/h5util.c | 282 + java/test/TestH5T.java | 54 + java/test/testfiles/JUnit-TestH5T.txt | 3 +- release_docs/RELEASE.txt | 192 + src/CMakeLists.txt | 13 +- src/H5Fmodule.h | 2 +- src/H5Gmodule.h | 2 +- src/H5Odtype.c | 97 + src/H5Pfapl.c | 6 +- src/H5Plapl.c | 6 +- src/H5S.c | 10 +- src/H5Spublic.h | 4 +- src/H5Sselect.c | 18 +- src/H5T.c | 659 +- src/H5Tbit.c | 2 +- src/H5Tcomplex.c | 153 + src/H5Tcompound.c | 7 + src/H5Tconv.c | 221 +- src/H5Tconv.h | 11 +- src/H5Tconv_bitfield.c | 7 +- src/H5Tconv_complex.c | 2323 +++++ src/H5Tconv_complex.h | 214 + src/H5Tconv_float.c | 2485 +++--- src/H5Tconv_float.h | 77 + src/H5Tconv_integer.c | 1456 ++- src/H5Tconv_integer.h | 127 + src/H5Tconv_macros.h | 623 +- src/H5Tconv_vlen.c | 3 +- src/H5Tdbg.c | 51 +- src/H5Tfields.c | 2 + src/H5Tfixed.c | 24 +- src/H5Tmodule.h | 206 +- src/H5Tnative.c | 138 +- src/H5Toffset.c | 7 + src/H5Tpkg.h | 93 +- src/H5Tprecis.c | 8 + src/H5Tpublic.h | 117 +- src/H5Tvisit.c | 11 +- src/H5Tvlen.c | 37 +- src/H5VL.c | 20 +- src/H5Znbit.c | 6 + src/H5Zscaleoffset.c | 1 + src/H5private.h | 42 + src/H5trace.c | 24 + src/H5win32defs.h | 18 + src/Makefile.am | 7 +- test/API/H5_api_dataset_test.c | 11 +- test/API/H5_api_test_util.c | 55 + test/dsets.c | 26 +- test/dt_arith.c | 7893 ++++++++++++----- test/dtypes.c | 2876 +++++- test/ntypes.c | 131 + test/tarray.c | 166 +- test/tattr.c | 8 +- test/tfile.c | 48 +- tools/lib/h5diff_array.c | 1007 ++- tools/lib/h5diff_dset.c | 1 + tools/lib/h5diff_util.c | 4 + tools/lib/h5tools.c | 22 + tools/lib/h5tools.h | 111 +- tools/lib/h5tools_dump.c | 72 +- tools/lib/h5tools_str.c | 70 +- tools/lib/h5tools_type.c | 18 + tools/src/h5dump/h5dump.c | 38 +- tools/src/h5dump/h5dump.h | 13 +- tools/src/h5dump/h5dump_ddl.c | 31 +- tools/src/h5dump/h5dump_extern.h | 1 + tools/src/h5dump/h5dump_xml.c | 268 +- tools/src/h5import/h5import.c | 4 + tools/src/h5ls/h5ls.c | 102 +- tools/src/h5repack/h5repack_opttable.c | 62 +- tools/test/h5diff/expected/h5diff_70.txt | 141 + tools/test/h5diff/expected/h5diff_700.txt | 147 +- tools/test/h5diff/expected/h5diff_701.txt | 156 +- tools/test/h5diff/expected/h5diff_702.txt | 147 +- tools/test/h5diff/expected/h5diff_703.txt | 156 +- tools/test/h5diff/expected/h5diff_80.txt | 50 + tools/test/h5diff/expected/h5diff_8639.txt | 6 + tools/test/h5diff/h5diffgentest.c | 140 +- tools/test/h5diff/testfiles/h5diff_attr1.h5 | Bin 27480 -> 29160 bytes tools/test/h5diff/testfiles/h5diff_attr2.h5 | Bin 27480 -> 29160 bytes tools/test/h5diff/testfiles/h5diff_attr3.h5 | Bin 27440 -> 29120 bytes tools/test/h5diff/testfiles/h5diff_dset1.h5 | Bin 23416 -> 24560 bytes tools/test/h5diff/testfiles/h5diff_dset2.h5 | Bin 23416 -> 24560 bytes tools/test/h5diff/testfiles/h5diff_dset3.h5 | Bin 23416 -> 24560 bytes tools/test/h5dump/CMakeTests.cmake | 27 + tools/test/h5dump/expected/tcomplex.ddl | 441 + tools/test/h5dump/expected/tcomplex_be.ddl | 441 + .../test/h5dump/expected/tcomplex_be_info.ddl | 103 + tools/test/h5dump/expected/tcomplex_info.ddl | 103 + tools/test/h5dump/expected/treference.ddl | 136 + tools/test/h5dump/h5dumpgentest.c | 609 +- tools/test/h5dump/testfiles/tattr2.h5 | Bin 33840 -> 38920 bytes tools/test/h5dump/testfiles/tcomplex.h5 | Bin 0 -> 15552 bytes tools/test/h5dump/testfiles/tcomplex_be.h5 | Bin 0 -> 15552 bytes tools/test/h5dump/testh5dump.sh.in | 23 + tools/test/h5ls/CMakeTests.cmake | 44 + tools/test/h5ls/expected/tattr2.ls | 48 +- tools/test/h5ls/expected/tcomplex.ls | 40 + tools/test/h5ls/expected/tcomplex_be.ls | 40 + .../h5ls/expected/tcomplex_be_nosupport.ls | 46 + .../test/h5ls/expected/tcomplex_nosupport.ls | 46 + tools/test/h5ls/testh5ls.sh.in | 22 + tools/test/h5repack/h5repacktst.c | 60 +- 141 files changed, 24708 insertions(+), 4923 deletions(-) create mode 100644 HDF5Examples/C/H5T/116/h5ex_t_complex.c create mode 100644 HDF5Examples/C/H5T/116/h5ex_t_complex_custom.c create mode 100644 HDF5Examples/C/H5T/116/h5ex_t_complex_msvc.c create mode 100644 doxygen/dox/DDLBNF116.dox create mode 100644 src/H5Tcomplex.c create mode 100644 src/H5Tconv_complex.c create mode 100644 src/H5Tconv_complex.h create mode 100644 tools/test/h5dump/expected/tcomplex.ddl create mode 100644 tools/test/h5dump/expected/tcomplex_be.ddl create mode 100644 tools/test/h5dump/expected/tcomplex_be_info.ddl create mode 100644 tools/test/h5dump/expected/tcomplex_info.ddl create mode 100644 tools/test/h5dump/testfiles/tcomplex.h5 create mode 100644 tools/test/h5dump/testfiles/tcomplex_be.h5 create mode 100644 tools/test/h5ls/expected/tcomplex.ls create mode 100644 tools/test/h5ls/expected/tcomplex_be.ls create mode 100644 tools/test/h5ls/expected/tcomplex_be_nosupport.ls create mode 100644 tools/test/h5ls/expected/tcomplex_nosupport.ls diff --git a/HDF5Examples/C/H5T/116/h5ex_t_complex.c b/HDF5Examples/C/H5T/116/h5ex_t_complex.c new file mode 100644 index 00000000000..a3b03145acc --- /dev/null +++ b/HDF5Examples/C/H5T/116/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_CPLX_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/116/h5ex_t_complex_custom.c b/HDF5Examples/C/H5T/116/h5ex_t_complex_custom.c new file mode 100644 index 00000000000..27f72ec125e --- /dev/null +++ b/HDF5Examples/C/H5T/116/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_CPLX_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/116/h5ex_t_complex_msvc.c b/HDF5Examples/C/H5T/116/h5ex_t_complex_msvc.c new file mode 100644 index 00000000000..2a7fe841302 --- /dev/null +++ b/HDF5Examples/C/H5T/116/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_CPLX_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 cd26a96e25b..db46cf38663 100644 --- a/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java +++ b/HDF5Examples/JAVA/H5T/H5Ex_T_Commit.java @@ -47,7 +47,8 @@ enum H5T_class { H5T_ENUM(HDF5Constants.H5T_ENUM), // enumeration types H5T_VLEN(HDF5Constants.H5T_VLEN), // Variable-Length types H5T_ARRAY(HDF5Constants.H5T_ARRAY), // Array types - H5T_NCLASSES(11); // this must be last + H5T_COMPLEX(HDF5Constants.H5T_COMPLEX), // Complex number types + H5T_NCLASSES(12); // this must be last private static final Map lookup = new HashMap(); diff --git a/c++/test/tattr.cpp b/c++/test/tattr.cpp index 5135e0c7fa7..0d5281f65ca 100644 --- a/c++/test/tattr.cpp +++ b/c++/test/tattr.cpp @@ -632,7 +632,7 @@ test_attr_compound_write(FileAccPropList &fapl) hsize_t dims2[] = {ATTR4_DIM1, ATTR4_DIM2}; DataSpace sid2(ATTR4_RANK, dims2); - // Create complex attribute for the dataset + // Create compound attribute for the dataset Attribute attr = dataset.createAttribute(ATTR4_NAME, comp_type, sid2); // Try to create the same attribute again (should fail) @@ -643,7 +643,7 @@ test_attr_compound_write(FileAccPropList &fapl) { } // do nothing, exception expected - // Write complex attribute data + // Write compound attribute data attr.write(comp_type, attr_data4); PASSED(); @@ -2001,8 +2001,8 @@ test_attr() test_attr_rename(curr_fapl); // Test renaming attribute test_attr_basic_read(curr_fapl); // Test basic H5A reading code - test_attr_compound_write(curr_fapl); // Test complex datatype H5A writing code - test_attr_compound_read(curr_fapl); // Test complex datatype H5A reading code + test_attr_compound_write(curr_fapl); // Test compound datatype H5A writing code + test_attr_compound_read(curr_fapl); // Test compound datatype H5A reading code test_attr_scalar_write(curr_fapl); // Test scalar dataspace H5A writing code test_attr_scalar_read(curr_fapl); // Test scalar dataspace H5A reading code diff --git a/config/cmake/ConfigureChecks.cmake b/config/cmake/ConfigureChecks.cmake index af2d13e5180..b18d71296ac 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") @@ -816,6 +817,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 c6e3a619162..27662cca422 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -104,12 +104,18 @@ /* 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 to 1 if CLOCK_MONOTONIC_COARSE is available */ #cmakedefine H5_HAVE_CLOCK_MONOTONIC_COARSE @H5_HAVE_CLOCK_MONOTONIC_COARSE@ +/* Define if complex number support is available */ +#cmakedefine H5_HAVE_COMPLEX_NUMBERS @H5_HAVE_COMPLEX_NUMBERS@ + /* Define to 1 if you have the header file. */ #cmakedefine H5_HAVE_CURL_CURL_H @H5_HAVE_CURL_H@ @@ -445,9 +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 8d0e78f46b7..9f222c2698c 100644 --- a/config/cmake/HDFTests.c +++ b/config/cmake/HDFTests.c @@ -118,3 +118,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 + +#ifdef _MSC_VER + +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 1cf3168b815..b3d0a17c1ab 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 fd0afb5d54e..30d03253965 100644 --- a/doxygen/aliases +++ b/doxygen/aliases @@ -370,7 +370,7 @@ ALIASES += ref_rfc20040811="Conve ALIASES += click4more="(Click on a enumerator, field, or type for more information.)" ALIASES += csets="
#H5T_CSET_ASCIIUS ASCII
#H5T_CSET_UTF8UTF-8 Unicode encoding
" -ALIASES += datatype_class=" \li #H5T_INTEGER \li #H5T_FLOAT \li #H5T_STRING \li #H5T_BITFIELD \li #H5T_OPAQUE \li #H5T_COMPOUND \li #H5T_REFERENCE \li #H5T_ENUM \li #H5T_VLEN \li #H5T_ARRAY" +ALIASES += datatype_class=" \li #H5T_INTEGER \li #H5T_FLOAT \li #H5T_STRING \li #H5T_BITFIELD \li #H5T_OPAQUE \li #H5T_COMPOUND \li #H5T_REFERENCE \li #H5T_ENUM \li #H5T_VLEN \li #H5T_ARRAY \li #H5T_COMPLEX" ALIASES += file_access="
#H5F_ACC_RDWRFile was opened with read/write access.
#H5F_ACC_RDONLYFile was opened with read-only access.
#H5F_ACC_SWMR_WRITEFile was opened with read/write access for a single-writer/multiple-reader (SWMR) scenario. Note that the writer process must also open the file with the #H5F_ACC_RDWR flag.
#H5F_ACC_SWMR_READFile was opened with read-only access for a single-writer/multiple-reader (SWMR) scenario. Note that the reader process must also open the file with the #H5F_ACC_RDONLY flag.
" ALIASES += id_types="
#H5I_FILEFile
#H5I_GROUPGroup
#H5I_DATATYPEDatatype
#H5I_DATASPACEDataspace
#H5I_DATASETDataset
#H5I_ATTRAttribute
" ALIASES += indexes="
#H5_INDEX_NAMELexicographic order on name
#H5_INDEX_CRT_ORDERIndex on creation order
" diff --git a/doxygen/dox/DDLBNF116.dox b/doxygen/dox/DDLBNF116.dox new file mode 100644 index 00000000000..094d67245a0 --- /dev/null +++ b/doxygen/dox/DDLBNF116.dox @@ -0,0 +1,667 @@ +/** \page DDLBNF116 DDL in BNF for HDF5 1.16.0 and above + +\todo Revise this & break it up! + +\section intro116 Introduction + +This document contains the data description language (DDL) for an HDF5 file. The +description is in Backus-Naur Form (BNF). + +\section expo116 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 ddl116 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 42f06d23099..cda3a1ce87a 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 DDLBNF116 \section File Format diff --git a/doxygen/examples/H5.format.html b/doxygen/examples/H5.format.html index 023c19d7c19..317ee6ae783 100644 --- a/doxygen/examples/H5.format.html +++ b/doxygen/examples/H5.format.html @@ -474,6 +474,16 @@ and do not represent any values or padding in the file.

+
+

I.B. Changes for HDF5 1.16

+

The following sections have been + changed or added for the 1.16 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 @@ -9683,6 +9693,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 @@ -9750,6 +9765,11 @@

IV.A.2.d. The Datatype Message

10 Array + + + 11 + Complex +

@@ -11523,6 +11543,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..9409872e107 100644 --- a/doxygen/examples/tables/predefinedDatatypes.dox +++ b/doxygen/examples/tables/predefinedDatatypes.dox @@ -35,6 +35,41 @@ //! [predefined_ieee_datatypes_table] * * +//! [predefined_cplx_datatypes_table] + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Predefined Complex Number Datatypes
DatatypeDescription
#H5T_CPLX_IEEE_F16BEComplex number of 2 16-bit big-endian IEEE floating point numbers
#H5T_CPLX_IEEE_F16LEComplex number of 2 16-bit little-endian IEEE floating point numbers
#H5T_CPLX_IEEE_F32BEComplex number of 2 32-bit big-endian IEEE floating point numbers
#H5T_CPLX_IEEE_F32LEComplex number of 2 32-bit little-endian IEEE floating point numbers
#H5T_CPLX_IEEE_F64BEComplex number of 2 64-bit big-endian IEEE floating point numbers
#H5T_CPLX_IEEE_F64LEComplex number of 2 64-bit little-endian IEEE floating point numbers
+//! [predefined_cplx_datatypes_table] + * + * //! [predefined_std_datatypes_table] @@ -489,6 +524,18 @@ + + + + + + + + + + + + diff --git a/fortran/src/H5Tf.c b/fortran/src/H5Tf.c index 393873e110b..746c21deb19 100644 --- a/fortran/src/H5Tf.c +++ b/fortran/src/H5Tf.c @@ -212,11 +212,12 @@ h5tequal_c(hid_t_f *type1_id, hid_t_f *type2_id, int_f *c_flag) * H5T_STRING_F (3) * H5T_BITFIELD_F (4) * H5T_OPAQUE_F (5) - * H5T_COMPOUNDF (6) + * H5T_COMPOUND_F (6) * H5T_REFERENCE_F (7) * H5T_ENUM_F (8) * H5T_VLEN_F (9) * H5T_ARRAY_F (10) + * H5T_COMPLEX_F (11) * RETURNS * 0 on success, -1 on failure * SOURCE @@ -239,17 +240,7 @@ h5tget_class_c(hid_t_f *type_id, int_f *classtype) return ret_value; } *classtype = c_classtype; - /* - if (c_classtype == H5T_INTEGER) *classtype = H5T_INTEGER_F; - if (c_classtype == H5T_FLOAT) *classtype = H5T_FLOAT_F; - if (c_classtype == H5T_TIME) *classtype = H5T_TIME_F; - if (c_classtype == H5T_STRING) *classtype = H5T_STRING_F; - if (c_classtype == H5T_BITFIELD) *classtype = H5T_BITFIELD_F; - if (c_classtype == H5T_OPAQUE) *classtype = H5T_OPAQUE_F; - if (c_classtype == H5T_COMPOUND) *classtype = H5T_COMPOUND_F; - if (c_classtype == H5T_REFERENCE) *classtype = H5T_REFERENCE_F; - if (c_classtype == H5T_ENUM) *classtype = H5T_ENUM_F; - */ + return ret_value; } diff --git a/fortran/src/H5Tff.F90 b/fortran/src/H5Tff.F90 index b93e3c3a03c..7c1e84a60e7 100644 --- a/fortran/src/H5Tff.F90 +++ b/fortran/src/H5Tff.F90 @@ -267,6 +267,7 @@ END SUBROUTINE h5tclose_f !! \li H5T_ENUM_F !! \li H5T_VLEN_F !! \li H5T_ARRAY_F +!! \li H5T_COMPLEX_F !! \param hdferr \fortran_error !! !! See C API: @ref H5Tget_class() @@ -1726,9 +1727,9 @@ END SUBROUTINE h5tis_variable_str_f !! !! \brief Returns datatype class of compound datatype member. !! -!! \param type_id Datartpe identifier. +!! \param type_id Datatype identifier. !! \param member_no Index of compound datatype member. -!! \param class Class type for compound dadtype member. Valid classes: +!! \param class Class type for compound datatype member. Valid classes: !! \li H5T_NO_CLASS_F (error) !! \li H5T_INTEGER_F !! \li H5T_FLOAT_F @@ -1741,6 +1742,7 @@ END SUBROUTINE h5tis_variable_str_f !! \li H5T_ENUM_F !! \li H5T_VLEN_F !! \li H5T_ARRAY_F +!! \li H5T_COMPLEX_F !! \param hdferr \fortran_error !! !! See C API: @ref H5Tget_member_class() diff --git a/fortran/src/H5_f.c b/fortran/src/H5_f.c index 3b278bbbc54..3cbf1285cde 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 f4bb211e0d1..8e3d41814be 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 6d8697da699..c288a02dd02 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 7d44792fbc0..742a7d038fd 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 3e6b20d322e..0c540fbfba4 100644 --- a/hl/src/H5LTanalyze.c +++ b/hl/src/H5LTanalyze.c @@ -647,8 +647,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 @@ -656,39 +656,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[338] = { 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, 0, 49, 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, 0, 0, 67, 48, 0, 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, - 0, 0, 0, 0, 0, 0, 0, 55, 0, 0, - 0, 0, 0, 0, 0, 0, 38, 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, - 0, 51, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 59, 0, 0, 56, 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, 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, 0, 0, 35, + 0, 26, 18, 20, 19, 0, 25, 0, 52, 54, + 0, 0, 0, 36, 0, 0, 0, 27, 21, 0, + + 0, 0, 0, 0, 0, 0, 34, 0, 37, 38, + 39, 40, 41, 42, 43, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 44, 0, 45, 0, 46, 0 } ; static const YY_CHAR yy_ec[256] = @@ -701,12 +707,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, @@ -723,166 +729,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[340] = { 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, 363, 364, 360, 0, 0, 364, 364, 12, + 352, 333, 328, 364, 364, 364, 364, 356, 354, 0, + 338, 320, 323, 325, 323, 364, 320, 323, 310, 309, + 17, 364, 329, 34, 15, 332, 323, 364, 315, 31, + 318, 316, 323, 326, 312, 307, 40, 315, 322, 318, + 298, 304, 308, 308, 312, 299, 296, 298, 308, 294, + 310, 45, 294, 304, 285, 300, 364, 301, 304, 290, + 282, 284, 309, 289, 281, 293, 288, 281, 269, 27, + 285, 281, 287, 364, 364, 269, 42, 264, 263, 364, + 364, 272, 261, 266, 266, 47, 272, 46, 282, 364, + + 364, 364, 277, 262, 271, 41, 278, 272, 272, 271, + 70, 77, 268, 255, 259, 270, 250, 258, 264, 251, + 249, 254, 84, 239, 364, 267, 270, 267, 63, 264, + 267, 264, 70, 364, 248, 256, 246, 364, 251, 249, + 250, 246, 225, 253, 256, 253, 79, 77, 82, 84, + 242, 241, 89, 91, 93, 240, 239, 233, 239, 236, + 364, 235, 230, 240, 220, 95, 98, 100, 228, 222, + 224, 221, 102, 101, 104, 227, 226, 225, 224, 223, + 222, 364, 364, 221, 220, 219, 218, 217, 216, 364, + 364, 102, 215, 364, 193, 209, 364, 225, 211, 210, + + 209, 208, 207, 206, 209, 190, 195, 189, 193, 192, + 192, 195, 189, 193, 188, 109, 191, 364, 364, 364, + 364, 364, 364, 364, 364, 364, 364, 364, 364, 197, + 192, 182, 189, 364, 364, 364, 364, 364, 364, 364, + 364, 178, 191, 191, 364, 172, 178, 182, 187, 171, + 185, 167, 171, 171, 169, 177, 164, 178, 131, 364, + 168, 159, 174, 168, 364, 158, 155, 156, 364, 159, + 163, 153, 364, 157, 163, 169, 172, 169, 158, 85, + 152, 364, 364, 364, 364, 154, 364, 142, 364, 364, + 116, 122, 125, 133, 161, 154, 151, 364, 364, 150, + + 149, 148, 147, 146, 145, 146, 364, 135, 121, 364, + 364, 364, 364, 364, 364, 133, 134, 141, 132, 128, + 128, 126, 129, 126, 124, 128, 117, 125, 108, 107, + 69, 364, 65, 364, 38, 364, 364, 148, 48 } ; -static const flex_int16_t yy_def[285] = +static const flex_int16_t yy_def[340] = { 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 + 337, 1, 337, 337, 337, 338, 339, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 338, 339, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 0, 337, 337 } ; -static const flex_int16_t yy_nxt[349] = +static const flex_int16_t yy_nxt[406] = { 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, 97, 40, + 20, 41, 42, 63, 120, 43, 53, 54, 44, 45, + 55, 79, 64, 46, 103, 98, 47, 104, 111, 56, + 114, 336, 121, 80, 126, 115, 127, 151, 112, 128, + 129, 130, 335, 131, 156, 152, 132, 133, 144, 295, + 145, 176, 157, 146, 169, 170, 178, 171, 180, 177, + + 172, 173, 334, 184, 179, 186, 181, 188, 174, 199, + 175, 185, 201, 187, 203, 189, 212, 200, 209, 214, + 202, 213, 204, 296, 210, 215, 216, 211, 230, 333, + 300, 253, 231, 217, 254, 276, 302, 277, 301, 304, + 278, 332, 331, 330, 303, 329, 328, 305, 19, 327, + 19, 326, 325, 324, 323, 322, 321, 320, 319, 318, + 317, 316, 315, 314, 313, 312, 311, 310, 309, 308, + 307, 306, 299, 298, 297, 294, 293, 292, 291, 290, + 289, 288, 287, 286, 285, 284, 283, 282, 281, 280, + 279, 275, 274, 273, 272, 271, 270, 269, 268, 267, + + 266, 265, 264, 263, 262, 261, 260, 259, 258, 257, + 256, 255, 252, 251, 250, 249, 248, 247, 246, 245, + 244, 243, 242, 241, 240, 239, 238, 237, 236, 235, + 234, 233, 232, 229, 228, 227, 226, 225, 224, 223, + 222, 221, 220, 219, 218, 208, 207, 206, 205, 198, + 197, 196, 195, 194, 193, 192, 191, 190, 183, 182, + 168, 167, 166, 165, 164, 163, 162, 161, 160, 159, + 158, 155, 154, 153, 150, 149, 148, 147, 143, 142, + 141, 140, 139, 138, 137, 136, 135, 134, 125, 124, + 123, 122, 119, 118, 117, 116, 113, 110, 109, 108, + + 107, 106, 105, 102, 101, 100, 99, 96, 95, 94, + 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, + 83, 82, 81, 78, 77, 76, 75, 74, 73, 72, + 71, 70, 69, 68, 67, 66, 65, 62, 61, 60, + 59, 58, 57, 52, 51, 50, 38, 35, 34, 33, + 32, 31, 30, 29, 28, 27, 26, 18, 25, 24, + 23, 18, 337, 3, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + + 337, 337, 337, 337, 337 } ; -static const flex_int16_t yy_chk[349] = +static const flex_int16_t yy_chk[406] = { 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, 80, 34, + 339, 34, 34, 47, 106, 34, 40, 40, 34, 34, + 40, 62, 47, 34, 87, 80, 34, 87, 96, 40, + 98, 335, 106, 62, 111, 98, 111, 129, 96, 111, + 111, 112, 333, 112, 133, 129, 112, 112, 123, 280, + 123, 148, 133, 123, 147, 147, 149, 147, 150, 148, + + 147, 147, 331, 153, 149, 154, 150, 155, 147, 166, + 147, 153, 167, 154, 168, 155, 174, 166, 173, 175, + 167, 174, 168, 280, 173, 175, 175, 173, 192, 330, + 291, 216, 192, 175, 216, 259, 292, 259, 291, 293, + 259, 329, 328, 327, 292, 326, 325, 293, 338, 324, + 338, 323, 322, 321, 320, 319, 318, 317, 316, 309, + 308, 306, 305, 304, 303, 302, 301, 300, 297, 296, + 295, 294, 288, 286, 281, 279, 278, 277, 276, 275, + 274, 272, 271, 270, 268, 267, 266, 264, 263, 262, + 261, 258, 257, 256, 255, 254, 253, 252, 251, 250, + + 249, 248, 247, 246, 244, 243, 242, 233, 232, 231, + 230, 217, 215, 214, 213, 212, 211, 210, 209, 208, + 207, 206, 205, 204, 203, 202, 201, 200, 199, 198, + 196, 195, 193, 189, 188, 187, 186, 185, 184, 181, + 180, 179, 178, 177, 176, 172, 171, 170, 169, 165, + 164, 163, 162, 160, 159, 158, 157, 156, 152, 151, + 146, 145, 144, 143, 142, 141, 140, 139, 137, 136, + 135, 132, 131, 130, 128, 127, 126, 124, 122, 121, + 120, 119, 118, 117, 116, 115, 114, 113, 110, 109, + 108, 107, 105, 104, 103, 99, 97, 95, 94, 93, + + 92, 89, 88, 86, 83, 82, 81, 79, 78, 77, + 76, 75, 74, 73, 72, 71, 70, 69, 68, 66, + 65, 64, 63, 61, 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, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, + + 337, 337, 337, 337, 337 } ; static yy_state_type yy_last_accepting_state; @@ -941,8 +974,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 @@ -1154,7 +1187,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 */ { @@ -1181,13 +1214,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 >= 338 ) 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] != 364 ); yy_find_action: yy_act = yy_accept[yy_current_state]; @@ -1399,162 +1432,212 @@ YY_RULE_SETUP case 38: YY_RULE_SETUP #line 96 "hl/src//H5LTanalyze.l" -{return token(H5T_STRING_TOKEN);} +{return hid(H5T_CPLX_IEEE_F16BE_TOKEN);} YY_BREAK case 39: YY_RULE_SETUP #line 97 "hl/src//H5LTanalyze.l" -{return token(STRSIZE_TOKEN);} +{return hid(H5T_CPLX_IEEE_F16LE_TOKEN);} YY_BREAK case 40: YY_RULE_SETUP #line 98 "hl/src//H5LTanalyze.l" -{return token(STRPAD_TOKEN);} +{return hid(H5T_CPLX_IEEE_F32BE_TOKEN);} YY_BREAK case 41: YY_RULE_SETUP #line 99 "hl/src//H5LTanalyze.l" -{return token(CSET_TOKEN);} +{return hid(H5T_CPLX_IEEE_F32LE_TOKEN);} YY_BREAK case 42: YY_RULE_SETUP #line 100 "hl/src//H5LTanalyze.l" -{return token(CTYPE_TOKEN);} +{return hid(H5T_CPLX_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_CPLX_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(); @@ -1851,7 +1934,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 >= 338 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -1879,11 +1962,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 >= 338 ) 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 == 337); return yy_is_jam ? 0 : yy_current_state; } @@ -2559,7 +2642,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 a573f8137f3..8cbdd32b4b3 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_CPLX_IEEE_F16BE {return hid(H5T_CPLX_IEEE_F16BE_TOKEN);} +H5T_CPLX_IEEE_F16LE {return hid(H5T_CPLX_IEEE_F16LE_TOKEN);} +H5T_CPLX_IEEE_F32BE {return hid(H5T_CPLX_IEEE_F32BE_TOKEN);} +H5T_CPLX_IEEE_F32LE {return hid(H5T_CPLX_IEEE_F32LE_TOKEN);} +H5T_CPLX_IEEE_F64BE {return hid(H5T_CPLX_IEEE_F64BE_TOKEN);} +H5T_CPLX_IEEE_F64LE {return hid(H5T_CPLX_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 bb7137630a5..a853f4b03f1 100644 --- a/hl/src/H5LTparse.c +++ b/hl/src/H5LTparse.c @@ -223,77 +223,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_CPLX_IEEE_F16BE_TOKEN = 40, /* H5T_CPLX_IEEE_F16BE_TOKEN */ + YYSYMBOL_H5T_CPLX_IEEE_F16LE_TOKEN = 41, /* H5T_CPLX_IEEE_F16LE_TOKEN */ + YYSYMBOL_H5T_CPLX_IEEE_F32BE_TOKEN = 42, /* H5T_CPLX_IEEE_F32BE_TOKEN */ + YYSYMBOL_H5T_CPLX_IEEE_F32LE_TOKEN = 43, /* H5T_CPLX_IEEE_F32LE_TOKEN */ + YYSYMBOL_H5T_CPLX_IEEE_F64BE_TOKEN = 44, /* H5T_CPLX_IEEE_F64BE_TOKEN */ + YYSYMBOL_H5T_CPLX_IEEE_F64LE_TOKEN = 45, /* H5T_CPLX_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; @@ -619,21 +630,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 @@ -652,14 +663,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, @@ -678,23 +689,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 @@ -726,18 +739,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_CPLX_IEEE_F16BE_TOKEN", "H5T_CPLX_IEEE_F16LE_TOKEN", + "H5T_CPLX_IEEE_F32BE_TOKEN", "H5T_CPLX_IEEE_F32LE_TOKEN", + "H5T_CPLX_IEEE_F64BE_TOKEN", "H5T_CPLX_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 @@ -750,7 +768,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) @@ -764,20 +782,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. @@ -785,40 +805,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 @@ -829,24 +851,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[] = @@ -854,24 +879,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 @@ -881,32 +909,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. */ @@ -917,11 +948,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 }; @@ -1385,263 +1417,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; @@ -1676,108 +1708,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_CPLX_IEEE_F16LE_TOKEN */ +#line 258 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_CPLX_IEEE_F16LE); } +#line 1766 "hl/src//H5LTparse.c" + break; + + case 74: /* complex_type: H5T_CPLX_IEEE_F16BE_TOKEN */ +#line 259 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_CPLX_IEEE_F16BE); } +#line 1772 "hl/src//H5LTparse.c" break; - case 69: /* @6: %empty */ -#line 251 "hl/src//H5LTparse.y" + case 75: /* complex_type: H5T_CPLX_IEEE_F32LE_TOKEN */ +#line 260 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_CPLX_IEEE_F32LE); } +#line 1778 "hl/src//H5LTparse.c" + break; + + case 76: /* complex_type: H5T_CPLX_IEEE_F32BE_TOKEN */ +#line 261 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_CPLX_IEEE_F32BE); } +#line 1784 "hl/src//H5LTparse.c" + break; + + case 77: /* complex_type: H5T_CPLX_IEEE_F64LE_TOKEN */ +#line 262 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_CPLX_IEEE_F64LE); } +#line 1790 "hl/src//H5LTparse.c" + break; + + case 78: /* complex_type: H5T_CPLX_IEEE_F64BE_TOKEN */ +#line 263 "hl/src//H5LTparse.y" + { (yyval.hid) = H5Tcopy(H5T_CPLX_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; @@ -1786,33 +1878,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); @@ -1829,82 +1921,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; @@ -1947,11 +2039,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..3d2342297b1 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_CPLX_IEEE_F16BE_TOKEN = 295, /* H5T_CPLX_IEEE_F16BE_TOKEN */ + H5T_CPLX_IEEE_F16LE_TOKEN = 296, /* H5T_CPLX_IEEE_F16LE_TOKEN */ + H5T_CPLX_IEEE_F32BE_TOKEN = 297, /* H5T_CPLX_IEEE_F32BE_TOKEN */ + H5T_CPLX_IEEE_F32LE_TOKEN = 298, /* H5T_CPLX_IEEE_F32LE_TOKEN */ + H5T_CPLX_IEEE_F64BE_TOKEN = 299, /* H5T_CPLX_IEEE_F64BE_TOKEN */ + H5T_CPLX_IEEE_F64LE_TOKEN = 300, /* H5T_CPLX_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 3a14e769419..33e983c3eba 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_CPLX_IEEE_F16BE_TOKEN H5T_CPLX_IEEE_F16LE_TOKEN +%token H5T_CPLX_IEEE_F32BE_TOKEN H5T_CPLX_IEEE_F32LE_TOKEN +%token H5T_CPLX_IEEE_F64BE_TOKEN H5T_CPLX_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_CPLX_IEEE_F16LE_TOKEN { $$ = H5Tcopy(H5T_CPLX_IEEE_F16LE); } + | H5T_CPLX_IEEE_F16BE_TOKEN { $$ = H5Tcopy(H5T_CPLX_IEEE_F16BE); } + | H5T_CPLX_IEEE_F32LE_TOKEN { $$ = H5Tcopy(H5T_CPLX_IEEE_F32LE); } + | H5T_CPLX_IEEE_F32BE_TOKEN { $$ = H5Tcopy(H5T_CPLX_IEEE_F32BE); } + | H5T_CPLX_IEEE_F64LE_TOKEN { $$ = H5Tcopy(H5T_CPLX_IEEE_F64LE); } + | H5T_CPLX_IEEE_F64BE_TOKEN { $$ = H5Tcopy(H5T_CPLX_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 9bbad45d609..b403645b3f6 100644 --- a/hl/test/test_lite.c +++ b/hl/test/test_lite.c @@ -1872,6 +1872,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_CPLX_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_CPLX_IEEE_F16LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_CPLX_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_CPLX_IEEE_F16BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_CPLX_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_CPLX_IEEE_F32LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_CPLX_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_CPLX_IEEE_F32BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_CPLX_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_CPLX_IEEE_F64LE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + if ((dtype = H5LTtext_to_dtype("H5T_CPLX_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_CPLX_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_CPLX_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_CPLX_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_CPLX_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_CPLX_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_CPLX_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_CPLX_IEEE_F64BE)) + goto out; + if (H5Tclose(dtype) < 0) + goto out; + + PASSED(); + return 0; + +out: + H5_FAILED(); + return -1; +} + /*------------------------------------------------------------------------- * test H5LTtext_to_dtype function *------------------------------------------------------------------------- @@ -1911,6 +2131,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 b4dd62fd70c..0d51305ae6c 100644 --- a/hl/tools/h5watch/h5watch.c +++ b/hl/tools/h5watch/h5watch.c @@ -94,16 +94,21 @@ static struct h5_long_options l_opts[] = {{"help", no_arg, 'h'}, {"hel", static herr_t doprint(hid_t did, const hsize_t *start, const hsize_t *block, int rank) { - h5tools_context_t ctx; /* print context */ - h5tool_format_t info; /* Format info for the tools library */ - static char fmt_double[16], fmt_float[16]; /* Format info */ - struct subset_t subset; /* Subsetting info */ - hsize_t ss_start[H5S_MAX_RANK]; /* Info for hyperslab */ - hsize_t ss_stride[H5S_MAX_RANK]; /* Info for hyperslab */ - hsize_t ss_block[H5S_MAX_RANK]; /* Info for hyperslab */ - hsize_t ss_count[H5S_MAX_RANK]; /* Info for hyperslab */ - int i; /* Local index variable */ - herr_t ret_value = SUCCEED; /* Return value */ + h5tools_context_t ctx; /* print context */ + h5tool_format_t info; /* Format info for the tools library */ + static char fmt_ldouble[16]; /* Format info */ + static char fmt_double[16]; /* Format info */ + static char fmt_float[16]; /* Format info */ + static char fmt_ldouble_complex[32]; /* Format info */ + static char fmt_double_complex[32]; /* Format info */ + static char fmt_float_complex[16]; /* Format info */ + struct subset_t subset; /* Subsetting info */ + hsize_t ss_start[H5S_MAX_RANK]; /* Info for hyperslab */ + hsize_t ss_stride[H5S_MAX_RANK]; /* Info for hyperslab */ + hsize_t ss_block[H5S_MAX_RANK]; /* Info for hyperslab */ + hsize_t ss_count[H5S_MAX_RANK]; /* Info for hyperslab */ + int i; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ /* Subsetting information for the tools library printing routines */ subset.start.data = ss_start; @@ -175,6 +180,14 @@ doprint(hid_t did, const hsize_t *start, const hsize_t *block, int rank) info.fmt_float = fmt_float; snprintf(fmt_double, sizeof(fmt_double), "%%1.%dg", DBL_DIG); info.fmt_double = fmt_double; + snprintf(fmt_ldouble, sizeof(fmt_ldouble), "%%1.%dLg", LDBL_DIG); + info.fmt_ldouble = fmt_ldouble; + snprintf(fmt_float_complex, sizeof(fmt_float_complex), "%%1.%dg%%+1.%dgi", FLT_DIG, FLT_DIG); + info.fmt_float_complex = fmt_float_complex; + snprintf(fmt_double_complex, sizeof(fmt_double_complex), "%%1.%dg%%+1.%dgi", DBL_DIG, DBL_DIG); + info.fmt_double_complex = fmt_double_complex; + snprintf(fmt_ldouble_complex, sizeof(fmt_ldouble_complex), "%%1.%dLg%%+1.%dLgi", LDBL_DIG, LDBL_DIG); + info.fmt_ldouble_complex = fmt_ldouble_complex; info.dset_format = "DSET-%s "; info.dset_hidefileno = 0; diff --git a/java/src/hdf/hdf5lib/H5.java b/java/src/hdf/hdf5lib/H5.java index 388ba18f87a..060d87ac6bf 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 55b6f4be913..7f9829c0e7d 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_CPLX_IEEE_F16BE = H5T_CPLX_IEEE_F16BE(); + /** */ + public static final long H5T_CPLX_IEEE_F16LE = H5T_CPLX_IEEE_F16LE(); + /** */ + public static final long H5T_CPLX_IEEE_F32BE = H5T_CPLX_IEEE_F32BE(); + /** */ + public static final long H5T_CPLX_IEEE_F32LE = H5T_CPLX_IEEE_F32LE(); + /** */ + public static final long H5T_CPLX_IEEE_F64BE = H5T_CPLX_IEEE_F64BE(); + /** */ + public static final long H5T_CPLX_IEEE_F64LE = H5T_CPLX_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_CPLX_IEEE_F16BE(); + + private static native final long H5T_CPLX_IEEE_F16LE(); + + private static native final long H5T_CPLX_IEEE_F32BE(); + + private static native final long H5T_CPLX_IEEE_F32LE(); + + private static native final long H5T_CPLX_IEEE_F64BE(); + + private static native final long H5T_CPLX_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 41395a4413f..b27c35e3af8 100644 --- a/java/src/jni/h5Constants.c +++ b/java/src/jni/h5Constants.c @@ -2543,6 +2543,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1C_1S1(JNIEnv *env, jclass cls) return H5T_C_S1; } JNIEXPORT jint JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_COMPLEX; +} +JNIEXPORT jint JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1COMPOUND(JNIEnv *env, jclass cls) { return H5T_COMPOUND; @@ -2562,6 +2567,36 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1CONV_1INIT(JNIEnv *env, jclass cls) { return H5T_CONV_INIT; } +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1CPLX_1IEEE_1F16BE(JNIEnv *env, jclass cls) +{ + return H5T_CPLX_IEEE_F16BE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1CPLX_1IEEE_1F16LE(JNIEnv *env, jclass cls) +{ + return H5T_CPLX_IEEE_F16LE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1CPLX_1IEEE_1F32BE(JNIEnv *env, jclass cls) +{ + return H5T_CPLX_IEEE_F32BE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1CPLX_1IEEE_1F32LE(JNIEnv *env, jclass cls) +{ + return H5T_CPLX_IEEE_F32LE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1CPLX_1IEEE_1F64BE(JNIEnv *env, jclass cls) +{ + return H5T_CPLX_IEEE_F64BE; +} +JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1CPLX_1IEEE_1F64LE(JNIEnv *env, jclass cls) +{ + return H5T_CPLX_IEEE_F64LE; +} JNIEXPORT jint JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1CSET_1ERROR(JNIEnv *env, jclass cls) { @@ -2883,6 +2918,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1DOUBLE(JNIEnv *env, jclass cls) return H5T_NATIVE_DOUBLE; } JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1DOUBLE_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_NATIVE_DOUBLE_COMPLEX; +} +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1FLOAT(JNIEnv *env, jclass cls) { return H5T_NATIVE_FLOAT; @@ -2893,6 +2933,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1FLOAT16(JNIEnv *env, jclass cls) return H5T_NATIVE_FLOAT16; } JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1FLOAT_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_NATIVE_FLOAT_COMPLEX; +} +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1HADDR(JNIEnv *env, jclass cls) { return H5T_NATIVE_HADDR; @@ -2998,6 +3043,11 @@ Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1LONG(JNIEnv *env, jclass cls) return H5T_NATIVE_LONG; } JNIEXPORT jlong JNICALL +Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1LDOUBLE_1COMPLEX(JNIEnv *env, jclass cls) +{ + return H5T_NATIVE_LDOUBLE_COMPLEX; +} +JNIEXPORT jlong JNICALL Java_hdf_hdf5lib_HDF5Constants_H5T_1NATIVE_1OPAQUE(JNIEnv *env, jclass cls) { return H5T_NATIVE_OPAQUE; diff --git a/java/src/jni/h5aImp.c b/java/src/jni/h5aImp.c index 54c862eff6c..73b4d0fef18 100644 --- a/java/src/jni/h5aImp.c +++ b/java/src/jni/h5aImp.c @@ -1243,12 +1243,13 @@ Java_hdf_hdf5lib_H5_H5Aread_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1272,13 +1273,13 @@ Java_hdf_hdf5lib_H5_H5Aread_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1289,7 +1290,7 @@ Java_hdf_hdf5lib_H5_H5Aread_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5AreadVL_asstr(env, (hid_t)attr_id, (hid_t)mem_type_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); } @@ -1447,12 +1448,13 @@ Java_hdf_hdf5lib_H5_H5Awrite_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1476,13 +1478,13 @@ Java_hdf_hdf5lib_H5_H5Awrite_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1493,7 +1495,7 @@ Java_hdf_hdf5lib_H5_H5Awrite_1VLStrings(JNIEnv *env, jclass clss, jlong attr_id, isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5AwriteVL_asstr(env, (hid_t)attr_id, (hid_t)mem_type_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); } diff --git a/java/src/jni/h5dImp.c b/java/src/jni/h5dImp.c index f6318b222d4..7447eca2e88 100644 --- a/java/src/jni/h5dImp.c +++ b/java/src/jni/h5dImp.c @@ -1259,12 +1259,13 @@ Java_hdf_hdf5lib_H5_H5Dread_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_i jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1288,13 +1289,13 @@ Java_hdf_hdf5lib_H5_H5Dread_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_i if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1305,7 +1306,7 @@ Java_hdf_hdf5lib_H5_H5Dread_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_i isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5DreadVL_asstr(env, (hid_t)dataset_id, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)xfer_plist_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); @@ -1484,12 +1485,13 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_ jobjectArray buf) { H5T_class_t type_class; - htri_t isStr = 0; - htri_t isVlenStr = 0; - htri_t isComplex = 0; - htri_t isComplex2 = 0; - hid_t nested_tid = H5I_INVALID_HID; - herr_t status = FAIL; + htri_t isStr = 0; + htri_t isVlenStr = 0; + htri_t isCompound = 0; + htri_t isVlen = 0; + hid_t nested_tid = H5I_INVALID_HID; + bool isComposite = false; + herr_t status = FAIL; UNUSED(clss); @@ -1513,13 +1515,13 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_ if ((nested_tid = H5Tget_member_type((hid_t)mem_type_id, i)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) + if ((isCompound = H5Tdetect_class((hid_t)nested_tid, H5T_COMPOUND)) < 0) H5_LIBRARY_ERROR(ENVONLY); - if ((isComplex2 = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) + if ((isVlen = H5Tdetect_class((hid_t)nested_tid, H5T_VLEN)) < 0) H5_LIBRARY_ERROR(ENVONLY); - isComplex = isComplex || isComplex2; + isComposite = isCompound || isVlen; if (H5Tclose(nested_tid) < 0) H5_LIBRARY_ERROR(ENVONLY); @@ -1530,7 +1532,7 @@ Java_hdf_hdf5lib_H5_H5Dwrite_1VLStrings(JNIEnv *env, jclass clss, jlong dataset_ isVlenStr = 1; /* Strings created by H5Tvlen_create(H5T_C_S1) */ } - if (!isStr || isComplex || isVlenStr) { + if (!isStr || isComposite || isVlenStr) { if ((status = H5DwriteVL_asstr(env, (hid_t)dataset_id, (hid_t)mem_type_id, (hid_t)mem_space_id, (hid_t)file_space_id, (hid_t)xfer_plist_id, buf)) < 0) CHECK_JNI_EXCEPTION(ENVONLY, JNI_FALSE); diff --git a/java/src/jni/h5tImp.c b/java/src/jni/h5tImp.c index 309454b16e4..64145485065 100644 --- a/java/src/jni/h5tImp.c +++ b/java/src/jni/h5tImp.c @@ -1647,6 +1647,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 e671456a9a6..ce99ab8f18a 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 9c441729a39..f203e8ed903 100644 --- a/java/src/jni/h5util.c +++ b/java/src/jni/h5util.c @@ -620,6 +620,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"); @@ -1482,6 +1519,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"); @@ -2116,6 +2195,17 @@ h5str_get_little_endian_type(hid_t tid) break; } + case H5T_COMPLEX: { + if (size == 4) + p_type = H5Tcopy(H5T_CPLX_IEEE_F16LE); + else if (size == 8) + p_type = H5Tcopy(H5T_CPLX_IEEE_F32LE); + else if (size == 16) + p_type = H5Tcopy(H5T_CPLX_IEEE_F64LE); + + break; + } + case H5T_NO_CLASS: case H5T_NCLASSES: { goto done; @@ -2212,6 +2302,17 @@ h5str_get_big_endian_type(hid_t tid) break; } + case H5T_COMPLEX: { + if (size == 4) + p_type = H5Tcopy(H5T_CPLX_IEEE_F16BE); + else if (size == 8) + p_type = H5Tcopy(H5T_CPLX_IEEE_F32BE); + else if (size == 16) + p_type = H5Tcopy(H5T_CPLX_IEEE_F64BE); + + break; + } + case H5T_NO_CLASS: case H5T_NCLASSES: { goto done; @@ -2468,6 +2569,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; @@ -4312,6 +4439,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: @@ -4536,6 +4696,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: @@ -4758,6 +4953,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: @@ -4920,6 +5169,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 0121cc24297..6b8ad9640a3 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 8b43f5ecddb..2b095f7fa52 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -431,6 +431,198 @@ 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_V116, 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_CPLX_IEEE_F16LE / H5T_CPLX_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_CPLX_IEEE_F32LE / H5T_CPLX_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_CPLX_IEEE_F64LE / H5T_CPLX_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. + + 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/116/h5ex_t_complex.c (Uses C99 complex number types) + - HDF5Examples/C/H5T/116/h5ex_t_complex_msvc.c (Uses MSVC complex number types) + - HDF5Examples/C/H5T/116/h5ex_t_complex_custom.c (Uses H5Tcomplex_create to create + a custom complex number type) + - Added new routines for interacting with error stacks: H5Epause_stack, H5Eresume_stack, and H5Eis_paused. These routines can be used to indicate that errors from a call to an HDF5 routine should not be diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c6743a85ff7..6c47ed9c90d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -600,17 +600,19 @@ set (H5T_SOURCES ${HDF5_SRC_DIR}/H5Tarray.c ${HDF5_SRC_DIR}/H5Tbit.c ${HDF5_SRC_DIR}/H5Tcommit.c + ${HDF5_SRC_DIR}/H5Tcomplex.c ${HDF5_SRC_DIR}/H5Tcompound.c ${HDF5_SRC_DIR}/H5Tconv.c - ${HDF5_SRC_DIR}/H5Tconv_integer.c - ${HDF5_SRC_DIR}/H5Tconv_float.c - ${HDF5_SRC_DIR}/H5Tconv_string.c + ${HDF5_SRC_DIR}/H5Tconv_array.c ${HDF5_SRC_DIR}/H5Tconv_bitfield.c + ${HDF5_SRC_DIR}/H5Tconv_complex.c ${HDF5_SRC_DIR}/H5Tconv_compound.c - ${HDF5_SRC_DIR}/H5Tconv_reference.c ${HDF5_SRC_DIR}/H5Tconv_enum.c + ${HDF5_SRC_DIR}/H5Tconv_float.c + ${HDF5_SRC_DIR}/H5Tconv_integer.c + ${HDF5_SRC_DIR}/H5Tconv_reference.c + ${HDF5_SRC_DIR}/H5Tconv_string.c ${HDF5_SRC_DIR}/H5Tconv_vlen.c - ${HDF5_SRC_DIR}/H5Tconv_array.c ${HDF5_SRC_DIR}/H5Tcset.c ${HDF5_SRC_DIR}/H5Tdbg.c ${HDF5_SRC_DIR}/H5Tdeprec.c @@ -958,6 +960,7 @@ set (H5_PRIVATE_HEADERS ${HDF5_SRC_DIR}/H5Tconv.h ${HDF5_SRC_DIR}/H5Tconv_array.h ${HDF5_SRC_DIR}/H5Tconv_bitfield.h + ${HDF5_SRC_DIR}/H5Tconv_complex.h ${HDF5_SRC_DIR}/H5Tconv_compound.h ${HDF5_SRC_DIR}/H5Tconv_enum.h ${HDF5_SRC_DIR}/H5Tconv_float.h diff --git a/src/H5Fmodule.h b/src/H5Fmodule.h index 8a65d17ae87..ee3173004b2 100644 --- a/src/H5Fmodule.h +++ b/src/H5Fmodule.h @@ -239,7 +239,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 DDLBNF116. * * \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 a06d44cea75..440c3d6a761 100644 --- a/src/H5Gmodule.h +++ b/src/H5Gmodule.h @@ -343,7 +343,7 @@ * * h5dump is described on the “HDF5 Tools” page of the \ref RM. * - * The HDF5 DDL grammar is described in the @ref DDLBNF114. + * The HDF5 DDL grammar is described in the @ref DDLBNF116. * * \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 24671b02107..0c3f0b7dfc0 100644 --- a/src/H5Odtype.c +++ b/src/H5Odtype.c @@ -830,6 +830,44 @@ H5O__dtype_decode_helper(unsigned *ioflags /*in,out*/, const uint8_t **pp, H5T_t dt->shared->force_conv = true; break; + case H5T_COMPLEX: + /* + * Complex number datatypes... + */ + + /* Set whether the complex number datatype is homogeneous */ + dt->shared->u.cplx.homogeneous = (bool)(flags & 0x01); + + if (!dt->shared->u.cplx.homogeneous) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + + /* Set the form of the complex number datatype */ + dt->shared->u.cplx.form = (H5T_complex_form_t)((flags >> 1) & 0x03); + + if (dt->shared->u.cplx.form != H5T_COMPLEX_RECTANGULAR) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "only complex number datatypes in rectangular form are currently supported"); + + /* Decode the base datatype of the complex number */ + if (NULL == (dt->shared->parent = H5T__alloc())) + HGOTO_ERROR(H5E_DATATYPE, H5E_NOSPACE, FAIL, + "unable to allocate complex number base datatype"); + if (H5O__dtype_decode_helper(ioflags, pp, dt->shared->parent, skip, p_end) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTDECODE, FAIL, + "unable to decode complex number base datatype"); + + /* 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 +1385,34 @@ 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.homogeneous) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + if (dt->shared->u.cplx.form != H5T_COMPLEX_RECTANGULAR) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, + "complex number datatypes not in rectangular form are currently unsupported"); + + /* Store whether complex number is homogeneous in first flag bit */ + if (dt->shared->u.cplx.homogeneous) + flags |= 0x01; + + /* Store complex number form in next two bits */ + flags = (unsigned)(flags | (((unsigned)dt->shared->u.cplx.form & 0x03) << 1)); + + /* Encode the base datatype of the complex number */ + if (H5O__dtype_encode_helper(pp, dt->shared->parent) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTENCODE, FAIL, + "unable to encode complex number base datatype"); + + break; + case H5T_NO_CLASS: case H5T_NCLASSES: default: @@ -1644,6 +1710,13 @@ H5O__dtype_size(const H5F_t *f, const void *_mesg) ret_value += H5O__dtype_size(f, dt->shared->parent); break; + case H5T_COMPLEX: + if (dt->shared->u.cplx.homogeneous) + ret_value += H5O__dtype_size(f, dt->shared->parent); + else + ret_value = 0; + break; + case H5T_NO_CLASS: case H5T_STRING: case H5T_REFERENCE: @@ -2001,6 +2074,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 +2321,26 @@ H5O__dtype_debug(H5F_t *f, const void *mesg, FILE *stream, int indent, int fwidt fprintf(stream, "%*s%s\n", indent, "", "Base type:"); H5O__dtype_debug(f, dt->shared->parent, stream, indent + 3, MAX(0, fwidth - 3)); } /* end else if */ + else if (H5T_COMPLEX == dt->shared->type) { + switch (dt->shared->u.cplx.form) { + case H5T_COMPLEX_RECTANGULAR: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "rectangular"); + break; + case H5T_COMPLEX_POLAR: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "polar"); + break; + case H5T_COMPLEX_EXPONENTIAL: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "exponential"); + break; + default: + fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, "Form:", "invalid"); + break; + } + if (dt->shared->u.cplx.homogeneous) { + fprintf(stream, "%*s%s\n", indent, "", "Base type:"); + H5O__dtype_debug(f, dt->shared->parent, stream, indent + 3, MAX(0, fwidth - 3)); + } + } else { switch (dt->shared->u.atomic.order) { case H5T_ORDER_LE: diff --git a/src/H5Pfapl.c b/src/H5Pfapl.c index 03a65fb7870..b5285248e88 100644 --- a/src/H5Pfapl.c +++ b/src/H5Pfapl.c @@ -1461,14 +1461,14 @@ H5Pget_driver(hid_t plist_id) H5P_genplist_t *plist; /* Property list pointer */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) if (NULL == (plist = (H5P_genplist_t *)H5I_object_verify(plist_id, H5I_GENPROP_LST))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a property list"); /* Get the driver */ if ((ret_value = H5P_peek_driver(plist)) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get driver"); + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't get driver"); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5Plapl.c b/src/H5Plapl.c index 64cd2996fc4..460d0842cca 100644 --- a/src/H5Plapl.c +++ b/src/H5Plapl.c @@ -1035,14 +1035,14 @@ H5Pget_elink_fapl(hid_t lapl_id) H5P_genplist_t *plist; /* Property list pointer */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* Get the plist structure */ if (NULL == (plist = H5P_object_verify(lapl_id, H5P_LINK_ACCESS))) - HGOTO_ERROR(H5E_ID, H5E_BADID, FAIL, "can't find object for ID"); + HGOTO_ERROR(H5E_ID, H5E_BADID, H5I_INVALID_HID, "can't find object for ID"); if (H5P_get(plist, H5L_ACS_ELINK_FAPL_NAME, &ret_value) < 0) - HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, FAIL, "can't get fapl for links"); + HGOTO_ERROR(H5E_PLIST, H5E_CANTGET, H5I_INVALID_HID, "can't get fapl for links"); done: FUNC_LEAVE_API(ret_value) diff --git a/src/H5S.c b/src/H5S.c index d6611654729..cb069a39a27 100644 --- a/src/H5S.c +++ b/src/H5S.c @@ -329,23 +329,23 @@ H5Screate(H5S_class_t type) H5S_t *new_ds = NULL; /* New dataspace structure */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* Check args */ if (type <= H5S_NO_CLASS || type > H5S_NULL) /* don't allow complex dataspace yet */ - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dataspace type"); + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid dataspace type"); if (NULL == (new_ds = H5S_create(type))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, H5I_INVALID_HID, "unable to create dataspace"); /* Register */ if ((ret_value = H5I_register(H5I_DATASPACE, new_ds, true)) < 0) - HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID"); + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID"); done: if (ret_value < 0) if (new_ds && H5S_close(new_ds) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace"); FUNC_LEAVE_API(ret_value) } /* end H5Screate() */ diff --git a/src/H5Spublic.h b/src/H5Spublic.h index 3697374d49c..9d6fe6a226d 100644 --- a/src/H5Spublic.h +++ b/src/H5Spublic.h @@ -251,10 +251,10 @@ H5_DLL hid_t H5Scopy(hid_t space_id); * Further dataspace types may be added later. * * A scalar dataspace, #H5S_SCALAR, has a single element, though that - * element may be of a complex datatype, such as a compound or array + * element may be of a composite datatype, such as a compound or array * datatype. By convention, the rank of a scalar dataspace is always \p 0 * (zero); think of it geometrically as a single, dimensionless point, - * though that point can be complex. + * though that point can be composite. * * A simple dataspace, #H5S_SIMPLE, consists of a regular array of elements. * diff --git a/src/H5Sselect.c b/src/H5Sselect.c index 5625de3aab4..651f73b6c03 100644 --- a/src/H5Sselect.c +++ b/src/H5Sselect.c @@ -2655,39 +2655,39 @@ H5Sselect_project_intersection(hid_t src_space_id, hid_t dst_space_id, hid_t src H5S_t *proj_space = NULL; /* Output dataspace */ hid_t ret_value; /* Return value */ - FUNC_ENTER_API(FAIL) + FUNC_ENTER_API(H5I_INVALID_HID) /* Check args */ if (NULL == (src_space = (H5S_t *)H5I_object_verify(src_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace"); if (NULL == (dst_space = (H5S_t *)H5I_object_verify(dst_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace"); if (NULL == (src_intersect_space = (H5S_t *)H5I_object_verify(src_intersect_space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, FAIL, "not a dataspace"); + HGOTO_ERROR(H5E_DATASPACE, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace"); /* Check numbers of points selected matches in source and destination */ if (H5S_GET_SELECT_NPOINTS(src_space) != H5S_GET_SELECT_NPOINTS(dst_space)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "number of points selected in source space does not match that in destination space"); /* Check numbers of dimensions matches in source and source intersect spaces */ if (H5S_GET_EXTENT_NDIMS(src_space) != H5S_GET_EXTENT_NDIMS(src_intersect_space)) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, + HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, H5I_INVALID_HID, "rank of source space does not match rank of source intersect space"); /* Perform operation */ if (H5S_select_project_intersection(src_space, dst_space, src_intersect_space, &proj_space, false) < 0) - HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, FAIL, "can't project dataspace intersection"); + HGOTO_ERROR(H5E_DATASET, H5E_CANTCLIP, H5I_INVALID_HID, "can't project dataspace intersection"); /* Register */ if ((ret_value = H5I_register(H5I_DATASPACE, proj_space, true)) < 0) - HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, FAIL, "unable to register dataspace ID"); + HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID"); done: if (ret_value < 0) if (proj_space && H5S_close(proj_space) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace"); + HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace"); FUNC_LEAVE_API(ret_value) } /* end H5Sselect_project_intersection() */ diff --git a/src/H5T.c b/src/H5T.c index dcf0a679fed..177191f275e 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 */ @@ -429,6 +430,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_CPLX_IEEE_F16BE_g = H5I_INVALID_HID; +hid_t H5T_CPLX_IEEE_F16LE_g = H5I_INVALID_HID; +hid_t H5T_CPLX_IEEE_F32BE_g = H5I_INVALID_HID; +hid_t H5T_CPLX_IEEE_F32LE_g = H5I_INVALID_HID; +hid_t H5T_CPLX_IEEE_F64BE_g = H5I_INVALID_HID; +hid_t H5T_CPLX_IEEE_F64LE_g = H5I_INVALID_HID; + hid_t H5T_VAX_F32_g = H5I_INVALID_HID; hid_t H5T_VAX_F64_g = H5I_INVALID_HID; @@ -469,30 +477,33 @@ hid_t H5T_C_S1_g = H5I_INVALID_HID; hid_t H5T_FORTRAN_S1_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_SCHAR_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_UCHAR_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_SHORT_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_USHORT_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_INT_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_UINT_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_LONG_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_ULONG_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_LLONG_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_ULLONG_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_FLOAT16_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_FLOAT_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_DOUBLE_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_LDOUBLE_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_B8_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_B16_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_B32_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_B64_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_OPAQUE_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_HADDR_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_HSIZE_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_HSSIZE_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_HERR_g = H5I_INVALID_HID; -hid_t H5T_NATIVE_HBOOL_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_SCHAR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UCHAR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_SHORT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_USHORT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_INT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_UINT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_ULONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LLONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_ULLONG_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_FLOAT16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_FLOAT_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_DOUBLE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LDOUBLE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_FLOAT_COMPLEX_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_DOUBLE_COMPLEX_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_LDOUBLE_COMPLEX_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B8_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B16_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B32_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_B64_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_OPAQUE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HADDR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HSIZE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HSSIZE_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HERR_g = H5I_INVALID_HID; +hid_t H5T_NATIVE_HBOOL_g = H5I_INVALID_HID; hid_t H5T_NATIVE_INT8_g = H5I_INVALID_HID; hid_t H5T_NATIVE_UINT8_g = H5I_INVALID_HID; @@ -538,20 +549,23 @@ size_t H5T_HOBJREF_ALIGN_g = 0; size_t H5T_HDSETREGREF_ALIGN_g = 0; size_t H5T_REF_ALIGN_g = 0; -size_t H5T_NATIVE_SCHAR_ALIGN_g = 0; -size_t H5T_NATIVE_UCHAR_ALIGN_g = 0; -size_t H5T_NATIVE_SHORT_ALIGN_g = 0; -size_t H5T_NATIVE_USHORT_ALIGN_g = 0; -size_t H5T_NATIVE_INT_ALIGN_g = 0; -size_t H5T_NATIVE_UINT_ALIGN_g = 0; -size_t H5T_NATIVE_LONG_ALIGN_g = 0; -size_t H5T_NATIVE_ULONG_ALIGN_g = 0; -size_t H5T_NATIVE_LLONG_ALIGN_g = 0; -size_t H5T_NATIVE_ULLONG_ALIGN_g = 0; -size_t H5T_NATIVE_FLOAT16_ALIGN_g = 0; -size_t H5T_NATIVE_FLOAT_ALIGN_g = 0; -size_t H5T_NATIVE_DOUBLE_ALIGN_g = 0; -size_t H5T_NATIVE_LDOUBLE_ALIGN_g = 0; +size_t H5T_NATIVE_SCHAR_ALIGN_g = 0; +size_t H5T_NATIVE_UCHAR_ALIGN_g = 0; +size_t H5T_NATIVE_SHORT_ALIGN_g = 0; +size_t H5T_NATIVE_USHORT_ALIGN_g = 0; +size_t H5T_NATIVE_INT_ALIGN_g = 0; +size_t H5T_NATIVE_UINT_ALIGN_g = 0; +size_t H5T_NATIVE_LONG_ALIGN_g = 0; +size_t H5T_NATIVE_ULONG_ALIGN_g = 0; +size_t H5T_NATIVE_LLONG_ALIGN_g = 0; +size_t H5T_NATIVE_ULLONG_ALIGN_g = 0; +size_t H5T_NATIVE_FLOAT16_ALIGN_g = 0; +size_t H5T_NATIVE_FLOAT_ALIGN_g = 0; +size_t H5T_NATIVE_DOUBLE_ALIGN_g = 0; +size_t H5T_NATIVE_LDOUBLE_ALIGN_g = 0; +size_t H5T_NATIVE_FLOAT_COMPLEX_ALIGN_g = 0; +size_t H5T_NATIVE_DOUBLE_COMPLEX_ALIGN_g = 0; +size_t H5T_NATIVE_LDOUBLE_COMPLEX_ALIGN_g = 0; /* Alignment constraints for C99 types */ size_t H5T_NATIVE_INT8_ALIGN_g = 0; @@ -593,10 +607,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); @@ -609,7 +633,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_V116 */ + H5O_DTYPE_VERSION_5, /* H5F_LIBVER_V116 */ H5O_DTYPE_VERSION_LATEST /* H5F_LIBVER_LATEST */ }; @@ -746,6 +770,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))) @@ -789,6 +854,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() */ @@ -827,6 +908,7 @@ H5T_init(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 */ @@ -835,6 +917,7 @@ H5T_init(void) H5T_t *enum_type = NULL; /* Datatype structure for enum objects */ H5T_t *vlen = NULL; /* Datatype structure for vlen objects */ H5T_t *array = NULL; /* Datatype structure for array objects */ + H5T_t *cplx = NULL; /* Datatype structure for complex number objects */ H5T_t *objref = NULL; /* Datatype structure for deprecated reference objects */ H5T_t *regref = NULL; /* Datatype structure for deprecated region references */ H5T_t *ref = NULL; /* Datatype structure for opaque references */ @@ -844,6 +927,12 @@ H5T_init(void) true; /* Flag to indicate whether datatype was copied or allocated (for error cleanup) */ #ifdef H5_HAVE__FLOAT16 H5T_t *native_float16 = NULL; /* Datatype structure for native _Float16 type */ +#endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + H5T_t *native_float_complex = NULL; /* Datatype structure for native float _Complex / _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 */ @@ -861,6 +950,12 @@ H5T_init(void) if (H5T__init_native_float_types() < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize floating-point types"); +#ifdef H5_HAVE_COMPLEX_NUMBERS + /* Initialize native complex number datatypes */ + if (H5T__init_native_complex_types() < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize complex number types"); +#endif + /* Initialize all other native types */ if (H5T__init_native_internal() < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to initialize integers"); @@ -896,6 +991,14 @@ H5T_init(void) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); if (NULL == (native_ldouble = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_g))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); +#ifdef H5_HAVE_COMPLEX_NUMBERS + if (NULL == (native_float_complex = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT_COMPLEX_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (native_double_complex = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE_COMPLEX_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); + if (NULL == (native_ldouble_complex = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE_COMPLEX_g))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype object"); +#endif /*------------------------------------------------------------ * Derived native types @@ -1119,6 +1222,59 @@ H5T_init(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_CPLX_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_CPLX_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_CPLX_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_CPLX_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_CPLX_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_CPLX_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. @@ -1133,18 +1289,27 @@ H5T_init(void) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); if (NULL == (array = H5T__array_create(native_int, 1, dim))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == (cplx = H5T__complex_create(native_float))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); status = 0; status |= H5T__register_int(H5T_PERS_SOFT, "i_i", fixedpt, fixedpt, H5T__conv_i_i); status |= H5T__register_int(H5T_PERS_SOFT, "i_f", fixedpt, floatpt, H5T__conv_i_f); + status |= H5T__register_int(H5T_PERS_SOFT, "i_complex", fixedpt, cplx, H5T__conv_i_complex); + status |= H5T__register_int(H5T_PERS_SOFT, "complex_i", cplx, fixedpt, H5T__conv_complex_i); status |= H5T__register_int(H5T_PERS_SOFT, "f_f", floatpt, floatpt, H5T__conv_f_f); status |= H5T__register_int(H5T_PERS_SOFT, "f_i", floatpt, fixedpt, H5T__conv_f_i); + status |= H5T__register_int(H5T_PERS_SOFT, "f_complex", floatpt, cplx, H5T__conv_f_complex); + status |= H5T__register_int(H5T_PERS_SOFT, "complex_f", cplx, floatpt, H5T__conv_complex_f); + status |= H5T__register_int(H5T_PERS_SOFT, "complex_complex", cplx, cplx, H5T__conv_complex); status |= H5T__register_int(H5T_PERS_SOFT, "s_s", string, string, H5T__conv_s_s); status |= H5T__register_int(H5T_PERS_SOFT, "b_b", bitfield, bitfield, H5T__conv_b_b); status |= H5T__register_int(H5T_PERS_SOFT, "ibo", fixedpt, fixedpt, H5T__conv_order); status |= H5T__register_int(H5T_PERS_SOFT, "ibo(opt)", fixedpt, fixedpt, H5T__conv_order_opt); status |= H5T__register_int(H5T_PERS_SOFT, "fbo", floatpt, floatpt, H5T__conv_order); status |= H5T__register_int(H5T_PERS_SOFT, "fbo(opt)", floatpt, floatpt, H5T__conv_order_opt); + status |= H5T__register_int(H5T_PERS_SOFT, "complexbo", cplx, cplx, H5T__conv_order); + status |= H5T__register_int(H5T_PERS_SOFT, "complexbo(opt)", cplx, cplx, H5T__conv_order_opt); status |= H5T__register_int(H5T_PERS_SOFT, "struct(no-opt)", compound, compound, H5T__conv_struct); status |= H5T__register_int(H5T_PERS_SOFT, "struct(opt)", compound, compound, H5T__conv_struct_opt); status |= H5T__register_int(H5T_PERS_SOFT, "enum", enum_type, enum_type, H5T__conv_enum); @@ -1157,6 +1322,12 @@ H5T_init(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 @@ -1194,6 +1365,34 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ldbl_flt16", native_ldouble, native_float16, H5T__conv_ldouble__Float16); #endif +#endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "flt_fcomplex", native_float, native_float_complex, + H5T__conv_float_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt_dcomplex", native_float, native_double_complex, + H5T__conv_float_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt_lcomplex", native_float, native_ldouble_complex, + H5T__conv_float_lcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dbl_fcomplex", native_double, native_float_complex, + H5T__conv_double_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dbl_dcomplex", native_double, native_double_complex, + H5T__conv_double_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "dbl_lcomplex", native_double, native_ldouble_complex, + H5T__conv_double_lcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ldbl_fcomplex", native_ldouble, native_float_complex, + H5T__conv_ldouble_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ldbl_dcomplex", native_ldouble, native_double_complex, + H5T__conv_ldouble_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ldbl_lcomplex", native_ldouble, native_ldouble_complex, + H5T__conv_ldouble_lcomplex); +#ifdef H5_HAVE__FLOAT16 + status |= H5T__register_int(H5T_PERS_HARD, "flt16_fcomplex", native_float16, native_float_complex, + H5T__conv__Float16_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt16_dcomplex", native_float16, native_double_complex, + H5T__conv__Float16_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "flt16_lcomplex", native_float16, native_ldouble_complex, + H5T__conv__Float16_lcomplex); +#endif #endif /* from long long */ @@ -1357,6 +1556,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "schar_flt16", native_schar, native_float16, H5T__conv_schar__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "schar_fcomplex", native_schar, native_float_complex, + H5T__conv_schar_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "schar_dcomplex", native_schar, native_double_complex, + H5T__conv_schar_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "schar_lcomplex", native_schar, native_ldouble_complex, + H5T__conv_schar_lcomplex); +#endif /* From unsigned char to floats */ status |= @@ -1369,6 +1576,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "uchar_flt16", native_uchar, native_float16, H5T__conv_uchar__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "uchar_fcomplex", native_uchar, native_float_complex, + H5T__conv_uchar_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uchar_dcomplex", native_uchar, native_double_complex, + H5T__conv_uchar_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uchar_lcomplex", native_uchar, native_ldouble_complex, + H5T__conv_uchar_lcomplex); +#endif /* From short to floats */ status |= @@ -1381,6 +1596,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "short_flt16", native_short, native_float16, H5T__conv_short__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "short_fcomplex", native_short, native_float_complex, + H5T__conv_short_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "short_dcomplex", native_short, native_double_complex, + H5T__conv_short_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "short_lcomplex", native_short, native_ldouble_complex, + H5T__conv_short_lcomplex); +#endif /* From unsigned short to floats */ status |= @@ -1393,6 +1616,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ushort_flt16", native_ushort, native_float16, H5T__conv_ushort__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "ushort_fcomplex", native_ushort, native_float_complex, + H5T__conv_ushort_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ushort_dcomplex", native_ushort, native_double_complex, + H5T__conv_ushort_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ushort_lcomplex", native_ushort, native_ldouble_complex, + H5T__conv_ushort_lcomplex); +#endif /* From int to floats */ status |= H5T__register_int(H5T_PERS_HARD, "int_flt", native_int, native_float, H5T__conv_int_float); @@ -1402,6 +1633,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "int_flt16", native_int, native_float16, H5T__conv_int__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "int_fcomplex", native_int, native_float_complex, + H5T__conv_int_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "int_dcomplex", native_int, native_double_complex, + H5T__conv_int_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "int_lcomplex", native_int, native_ldouble_complex, + H5T__conv_int_lcomplex); +#endif /* From unsigned int to floats */ status |= H5T__register_int(H5T_PERS_HARD, "uint_flt", native_uint, native_float, H5T__conv_uint_float); @@ -1412,6 +1651,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "uint_flt16", native_uint, native_float16, H5T__conv_uint__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "uint_fcomplex", native_uint, native_float_complex, + H5T__conv_uint_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uint_dcomplex", native_uint, native_double_complex, + H5T__conv_uint_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "uint_lcomplex", native_uint, native_ldouble_complex, + H5T__conv_uint_lcomplex); +#endif /* From long to floats */ status |= H5T__register_int(H5T_PERS_HARD, "long_flt", native_long, native_float, H5T__conv_long_float); @@ -1422,6 +1669,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "long_flt16", native_long, native_float16, H5T__conv_long__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "long_fcomplex", native_long, native_float_complex, + H5T__conv_long_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "long_dcomplex", native_long, native_double_complex, + H5T__conv_long_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "long_lcomplex", native_long, native_ldouble_complex, + H5T__conv_long_lcomplex); +#endif /* From unsigned long to floats */ status |= @@ -1434,6 +1689,14 @@ H5T_init(void) status |= H5T__register_int(H5T_PERS_HARD, "ulong_flt16", native_ulong, native_float16, H5T__conv_ulong__Float16); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + status |= H5T__register_int(H5T_PERS_HARD, "ulong_fcomplex", native_ulong, native_float_complex, + H5T__conv_ulong_fcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ulong_dcomplex", native_ulong, native_double_complex, + H5T__conv_ulong_dcomplex); + status |= H5T__register_int(H5T_PERS_HARD, "ulong_lcomplex", native_ulong, native_ldouble_complex, + H5T__conv_ulong_lcomplex); +#endif /* From long long to floats */ status |= @@ -1447,6 +1710,16 @@ H5T_init(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 */ @@ -1461,6 +1734,16 @@ H5T_init(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 */ @@ -1571,7 +1854,7 @@ H5T_init(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 */ @@ -1580,6 +1863,138 @@ H5T_init(void) H5T__conv__Float16_ullong); #endif +#ifdef H5_HAVE_COMPLEX_NUMBERS + /* From complex numbers to char */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_schar", native_float_complex, native_schar, + H5T__conv_fcomplex_schar); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_schar", native_double_complex, native_schar, + H5T__conv_dcomplex_schar); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_schar", native_ldouble_complex, native_schar, + H5T__conv_lcomplex_schar); + + /* From complex numbers to unsigned char */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_uchar", native_float_complex, native_uchar, + H5T__conv_fcomplex_uchar); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_uchar", native_double_complex, native_uchar, + H5T__conv_dcomplex_uchar); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_uchar", native_ldouble_complex, native_uchar, + H5T__conv_lcomplex_uchar); + + /* From complex numbers to short */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_short", native_float_complex, native_short, + H5T__conv_fcomplex_short); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_short", native_double_complex, native_short, + H5T__conv_dcomplex_short); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_short", native_ldouble_complex, native_short, + H5T__conv_lcomplex_short); + + /* From complex numbers to unsigned short */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ushort", native_float_complex, native_ushort, + H5T__conv_fcomplex_ushort); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ushort", native_double_complex, native_ushort, + H5T__conv_dcomplex_ushort); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ushort", native_ldouble_complex, native_ushort, + H5T__conv_lcomplex_ushort); + + /* From complex numbers to int */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_int", native_float_complex, native_int, + H5T__conv_fcomplex_int); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_int", native_double_complex, native_int, + H5T__conv_dcomplex_int); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_int", native_ldouble_complex, native_int, + H5T__conv_lcomplex_int); + + /* From complex numbers to unsigned int */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_uint", native_float_complex, native_uint, + H5T__conv_fcomplex_uint); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_uint", native_double_complex, native_uint, + H5T__conv_dcomplex_uint); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_uint", native_ldouble_complex, native_uint, + H5T__conv_lcomplex_uint); + + /* From complex numbers to long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_long", native_float_complex, native_long, + H5T__conv_fcomplex_long); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_long", native_double_complex, native_long, + H5T__conv_dcomplex_long); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_long", native_ldouble_complex, native_long, + H5T__conv_lcomplex_long); + + /* From complex numbers to unsigned long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ulong", native_float_complex, native_ulong, + H5T__conv_fcomplex_ulong); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ulong", native_double_complex, native_ulong, + H5T__conv_dcomplex_ulong); + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_ulong", native_ldouble_complex, native_ulong, + H5T__conv_lcomplex_ulong); + + /* From complex numbers to long long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_llong", native_float_complex, native_llong, + H5T__conv_fcomplex_llong); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_llong", native_double_complex, native_llong, + H5T__conv_dcomplex_llong); +#ifdef H5T_CONV_INTERNAL_LDOUBLE_LLONG + status |= H5T__register_int(H5T_PERS_HARD, "lcomplex_llong", native_ldouble_complex, native_llong, + H5T__conv_lcomplex_llong); +#endif + + /* From complex numbers to unsigned long long */ + status |= H5T__register_int(H5T_PERS_HARD, "fcomplex_ullong", native_float_complex, native_ullong, + H5T__conv_fcomplex_ullong); + status |= H5T__register_int(H5T_PERS_HARD, "dcomplex_ullong", native_double_complex, native_ullong, + H5T__conv_dcomplex_ullong); +#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 @@ -1617,6 +2032,8 @@ H5T_init(void) (void)H5T_close_real(vlen); if (array != NULL) (void)H5T_close_real(array); + if (cplx != NULL) + (void)H5T_close_real(cplx); /* Error cleanup */ if (ret_value < 0) { @@ -1729,6 +2146,13 @@ H5T_top_term_package(void) H5T_IEEE_F64BE_g = H5I_INVALID_HID; H5T_IEEE_F64LE_g = H5I_INVALID_HID; + H5T_CPLX_IEEE_F16BE_g = H5I_INVALID_HID; + H5T_CPLX_IEEE_F16LE_g = H5I_INVALID_HID; + H5T_CPLX_IEEE_F32BE_g = H5I_INVALID_HID; + H5T_CPLX_IEEE_F32LE_g = H5I_INVALID_HID; + H5T_CPLX_IEEE_F64BE_g = H5I_INVALID_HID; + H5T_CPLX_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; @@ -1766,30 +2190,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; @@ -1920,19 +2347,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) @@ -2341,7 +2768,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); @@ -2353,6 +2780,10 @@ H5T_detect_class(const H5T_t *dt, H5T_class_t cls, bool from_api) case H5T_ENUM: HGOTO_DONE(H5T_detect_class(dt->shared->parent, cls, from_api)); break; + case H5T_COMPLEX: + assert(dt->shared->u.cplx.homogeneous); + HGOTO_DONE(H5T_detect_class(dt->shared->parent, cls, from_api)); + break; case H5T_NO_CLASS: case H5T_INTEGER: case H5T_FLOAT: @@ -3220,11 +3651,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 @@ -3233,11 +3664,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) @@ -3443,6 +3874,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: @@ -3744,6 +4178,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; @@ -4112,6 +4547,7 @@ H5T__free(H5T_t *dt) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: break; @@ -4294,12 +4730,28 @@ H5T__set_size(H5T_t *dt, size_t size) assert(!(H5T_ENUM == dt->shared->type && 0 == dt->shared->u.enumer.nmembs)); if (dt->shared->parent) { - if (H5T__set_size(dt->shared->parent, size) < 0) + size_t new_size = size; + + if (dt->shared->type == H5T_COMPLEX) { + if (!dt->shared->u.cplx.homogeneous) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + + if ((new_size % 2) != 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, FAIL, + "new datatype size is not evenly divisible by 2"); + + new_size /= 2; + } + + if (H5T__set_size(dt->shared->parent, new_size) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, FAIL, "unable to set size for parent data type"); /* Adjust size of datatype appropriately */ if (dt->shared->type == H5T_ARRAY) dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem; + else if (dt->shared->type == H5T_COMPLEX) + dt->shared->size = 2 * dt->shared->parent->shared->size; else if (dt->shared->type != H5T_VLEN) dt->shared->size = dt->shared->parent->shared->size; } @@ -4423,6 +4875,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; @@ -4811,6 +5264,38 @@ H5T_cmp(const H5T_t *dt1, const H5T_t *dt2, bool superset) HGOTO_DONE(1); break; + case H5T_COMPLEX: + /* Make sure the complex number datatypes are both homogeneous or + * both heterogeneous + */ + tmp = (dt1->shared->u.cplx.homogeneous > dt2->shared->u.cplx.homogeneous) - + (dt1->shared->u.cplx.homogeneous < dt2->shared->u.cplx.homogeneous); + if (tmp < 0) + HGOTO_DONE(-1); + if (tmp > 0) + HGOTO_DONE(1); + + /* Make sure the complex number datatypes are both in the same form */ + tmp = (dt1->shared->u.cplx.form > dt2->shared->u.cplx.form) - + (dt1->shared->u.cplx.form < dt2->shared->u.cplx.form); + if (tmp < 0) + HGOTO_DONE(-1); + if (tmp > 0) + HGOTO_DONE(1); + + if (dt1->shared->u.cplx.homogeneous) { + tmp = H5T_cmp(dt1->shared->parent, dt2->shared->parent, superset); + if (tmp < 0) + HGOTO_DONE(-1); + if (tmp > 0) + HGOTO_DONE(1); + } + else + /* Heterogeneous complex number datatypes are currently unsupported */ + HGOTO_DONE(-1); + + break; + case H5T_NO_CLASS: case H5T_INTEGER: case H5T_FLOAT: @@ -4941,6 +5426,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); @@ -5641,6 +6127,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: @@ -6188,6 +6675,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 */ @@ -6240,7 +6728,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; @@ -6281,7 +6769,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; @@ -6323,7 +6811,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"); @@ -6352,6 +6840,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; @@ -6447,6 +6936,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; @@ -6531,6 +7021,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: @@ -6569,7 +7064,7 @@ H5T__upgrade_version(H5T_t *dt, unsigned new_version) assert(dt); /* Iterate over entire datatype, upgrading the version of components, if it's useful */ - if (H5T__visit(dt, (H5T_VISIT_SIMPLE | H5T_VISIT_COMPLEX_LAST), H5T__upgrade_version_cb, &new_version) < + if (H5T__visit(dt, (H5T_VISIT_SIMPLE | H5T_VISIT_COMPOSITE_LAST), H5T__upgrade_version_cb, &new_version) < 0) HGOTO_ERROR(H5E_DATATYPE, H5E_BADITER, FAIL, "iteration to upgrade datatype encoding version failed"); diff --git a/src/H5Tbit.c b/src/H5Tbit.c index c8300b85cde..503f298ae9e 100644 --- a/src/H5Tbit.c +++ b/src/H5Tbit.c @@ -231,7 +231,7 @@ H5T__bit_shift(uint8_t *buf, ssize_t shift_dist, size_t offset, size_t size) *------------------------------------------------------------------------- */ uint64_t -H5T__bit_get_d(uint8_t *buf, size_t offset, size_t size) +H5T__bit_get_d(const uint8_t *buf, size_t offset, size_t size) { uint64_t val = 0; size_t i, hs; diff --git a/src/H5Tcomplex.c b/src/H5Tcomplex.c new file mode 100644 index 00000000000..d4c50d895d0 --- /dev/null +++ b/src/H5Tcomplex.c @@ -0,0 +1,153 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * Copyright by The HDF Group. * + * All rights reserved. * + * * + * This file is part of HDF5. The full HDF5 copyright notice, including * + * terms governing use, modification, and redistribution, is contained in * + * the COPYING file, which can be found at the root of the source code * + * distribution tree, or in https://www.hdfgroup.org/licenses. * + * If you do not have access to either file, you may request a copy from * + * help@hdfgroup.org. * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/* + * Module Info: This module contains the functionality for complex number + * datatypes in the H5T interface. + */ + +/****************/ +/* Module Setup */ +/****************/ + +#include "H5Tmodule.h" /* This source code file is part of the H5T module */ + +/***********/ +/* Headers */ +/***********/ +#include "H5private.h" /* Generic Functions */ +#include "H5Eprivate.h" /* Error handling */ +#include "H5Iprivate.h" /* IDs */ +#include "H5Tpkg.h" /* Datatypes */ + +/****************/ +/* Local Macros */ +/****************/ + +/******************/ +/* Local Typedefs */ +/******************/ + +/********************/ +/* Package Typedefs */ +/********************/ + +/********************/ +/* Local Prototypes */ +/********************/ + +/*********************/ +/* Public Variables */ +/*********************/ + +/*********************/ +/* Package Variables */ +/*********************/ + +/*****************************/ +/* Library Private Variables */ +/*****************************/ + +/*******************/ +/* Local Variables */ +/*******************/ + +/*------------------------------------------------------------------------- + * Function: H5Tcomplex_create + * + * Purpose: Create a new complex number datatype based on the specified + * base datatype ID. + * + * Return: Success: ID of new complex number datatype + * Failure: H5I_INVALID_HID + * + *------------------------------------------------------------------------- + */ +hid_t +H5Tcomplex_create(hid_t base_type_id) +{ + H5T_t *base = NULL; /* base datatype */ + H5T_t *dt = NULL; /* new datatype */ + hid_t ret_value = H5I_INVALID_HID; /* return value */ + + FUNC_ENTER_API(H5I_INVALID_HID) + + if (NULL == (base = (H5T_t *)H5I_object_verify(base_type_id, H5I_DATATYPE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "invalid base datatype ID"); + + if (NULL == (dt = H5T__complex_create(base))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTINIT, H5I_INVALID_HID, + "can't create complex number datatype from base datatype"); + + if ((ret_value = H5I_register(H5I_DATATYPE, dt, true)) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register datatype"); + +done: + FUNC_LEAVE_API(ret_value); +} + +/*------------------------------------------------------------------------- + * Function: H5T__complex_create + * + * Purpose: Create a new complex number datatype based on the specified + * base datatype. + * + * Return: Success: new complex number datatype + * Failure: NULL + * + *------------------------------------------------------------------------- + */ +H5T_t * +H5T__complex_create(const H5T_t *base) +{ + H5T_t *dt = NULL; /* New complex number datatype */ + H5T_t *ret_value = NULL; /* Return value */ + + FUNC_ENTER_PACKAGE + + /* Check args */ + assert(base); + + /* Currently, only floating-point base datatypes are supported. */ + if (base->shared->type != H5T_FLOAT) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "base datatype is not a H5T_FLOAT datatype"); + if (base->shared->size == 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, "invalid base datatype size"); + if (base->shared->size > SIZE_MAX / 2) + HGOTO_ERROR(H5E_DATATYPE, H5E_BADVALUE, NULL, + "base datatype size too large - new datatype size would overflow"); + + /* Build new type */ + if (NULL == (dt = H5T__alloc())) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, NULL, "memory allocation failed"); + dt->shared->type = H5T_COMPLEX; + dt->shared->size = 2 * base->shared->size; + + if (NULL == (dt->shared->parent = H5T_copy(base, H5T_COPY_ALL))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCOPY, NULL, "can't copy base datatype"); + + /* Set complex number-specific fields */ + dt->shared->u.cplx.form = H5T_COMPLEX_RECTANGULAR; /* Only rectangular form is currently supported */ + dt->shared->u.cplx.homogeneous = true; + + /* 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 eb39dd4e98a..701929c3695 100644 --- a/src/H5Tcompound.c +++ b/src/H5Tcompound.c @@ -503,6 +503,13 @@ H5T__pack(const H5T_t *dt) /* Adjust size of datatype appropriately */ if (dt->shared->type == H5T_ARRAY) dt->shared->size = dt->shared->parent->shared->size * dt->shared->u.array.nelem; + else if (dt->shared->type == H5T_COMPLEX) { + if (dt->shared->u.cplx.homogeneous) + dt->shared->size = 2 * dt->shared->parent->shared->size; + else + HGOTO_ERROR(H5E_DATATYPE, H5E_BADTYPE, FAIL, + "heterogeneous complex number datatypes are currently unsupported"); + } else if (dt->shared->type != H5T_VLEN) dt->shared->size = dt->shared->parent->shared->size; } /* end if */ diff --git a/src/H5Tconv.c b/src/H5Tconv.c index 0a5e89ee99c..2ac1c2360b9 100644 --- a/src/H5Tconv.c +++ b/src/H5Tconv.c @@ -28,21 +28,13 @@ #include "H5private.h" /* Generic Functions */ #include "H5CXprivate.h" /* API Contexts */ #include "H5Eprivate.h" /* Error handling */ +#include "H5Tconv.h" /* Datatype Conversions */ #include "H5Tpkg.h" /* Datatypes */ /****************/ /* Local Macros */ /****************/ -/* Swap two elements (I & J) of an array using a temporary variable */ -#define H5_SWAP_BYTES(ARRAY, I, J) \ - do { \ - uint8_t _tmp; \ - _tmp = ARRAY[I]; \ - ARRAY[I] = ARRAY[J]; \ - ARRAY[J] = _tmp; \ - } while (0) - /******************/ /* Local Typedefs */ /******************/ @@ -185,27 +177,47 @@ H5T_get_force_conv(const H5T_t *dt) *------------------------------------------------------------------------- */ herr_t -H5T__reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order) +H5T__reverse_order(uint8_t *rev, uint8_t *s, const H5T_t *dtype) { - size_t i; + H5T_order_t order; + size_t size; FUNC_ENTER_PACKAGE_NOERR assert(s); - assert(size); + assert(dtype); + assert(H5T_IS_ATOMIC(dtype->shared) || H5T_COMPLEX == dtype->shared->type); + + size = dtype->shared->size; + + if (H5T_IS_ATOMIC(dtype->shared)) + order = dtype->shared->u.atomic.order; + else + order = dtype->shared->parent->shared->u.atomic.order; if (H5T_ORDER_VAX == order) { - for (i = 0; i < size; i += 2) { + for (size_t i = 0; i < size; i += 2) { rev[i] = s[(size - 2) - i]; rev[i + 1] = s[(size - 1) - i]; } } else if (H5T_ORDER_BE == order) { - for (i = 0; i < size; i++) - rev[size - (i + 1)] = s[i]; + if (H5T_IS_ATOMIC(dtype->shared)) { + for (size_t i = 0; i < size; i++) + rev[size - (i + 1)] = s[i]; + } + else { + size_t part_size = size / 2; + for (size_t i = 0; i < part_size; i++) + rev[part_size - (i + 1)] = s[i]; + rev += part_size; + s += part_size; + for (size_t i = 0; i < part_size; i++) + rev[part_size - (i + 1)] = s[i]; + } } else { - for (i = 0; i < size; i++) + for (size_t i = 0; i < size; i++) rev[i] = s[i]; } @@ -255,12 +267,12 @@ H5T__conv_noop(const H5T_t H5_ATTR_UNUSED *src, const H5T_t H5_ATTR_UNUSED *dst, /*------------------------------------------------------------------------- * Function: H5T__conv_order * - * Purpose: Convert one type to another when byte order is the only - * difference. + * Purpose: Convert one type to another when byte order is the only + * difference. * - * Note: This is a soft conversion function. + * Note: This is a soft conversion function. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ @@ -269,10 +281,13 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *_buf, void H5_ATTR_UNUSED *background) { - uint8_t *buf = (uint8_t *)_buf; - size_t i; - size_t j, md; - herr_t ret_value = SUCCEED; /* Return value */ + H5T_order_t src_order, dst_order; + uint8_t *buf = (uint8_t *)_buf; + size_t src_offset, dst_offset; + size_t src_size, dst_size; + size_t i; + size_t j, md; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -281,12 +296,38 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, /* Capability query */ if (NULL == src || NULL == dst) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - if (src->shared->size != dst->shared->size || 0 != src->shared->u.atomic.offset || - 0 != dst->shared->u.atomic.offset || - !((H5T_ORDER_BE == src->shared->u.atomic.order && - H5T_ORDER_LE == dst->shared->u.atomic.order) || - (H5T_ORDER_LE == src->shared->u.atomic.order && - H5T_ORDER_BE == dst->shared->u.atomic.order))) + + src_size = src->shared->size; + dst_size = dst->shared->size; + if (src_size != dst_size) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + if (src->shared->parent) { + if (!H5T_IS_ATOMIC(src->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + src_offset = src->shared->parent->shared->u.atomic.offset; + src_order = src->shared->parent->shared->u.atomic.order; + } + else { + src_offset = src->shared->u.atomic.offset; + src_order = src->shared->u.atomic.order; + } + if (dst->shared->parent) { + if (!H5T_IS_ATOMIC(dst->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + dst_offset = dst->shared->parent->shared->u.atomic.offset; + dst_order = dst->shared->parent->shared->u.atomic.order; + } + else { + dst_offset = dst->shared->u.atomic.offset; + dst_order = dst->shared->u.atomic.order; + } + + if (0 != src_offset || 0 != dst_offset) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + if (!((H5T_ORDER_BE == src_order && H5T_ORDER_LE == dst_order) || + (H5T_ORDER_LE == src_order && H5T_ORDER_BE == dst_order))) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); switch (src->shared->type) { case H5T_INTEGER: @@ -307,6 +348,23 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, } /* end if */ break; + case H5T_COMPLEX: { + const H5T_shared_t *src_base_sh = src->shared->parent->shared; + const H5T_shared_t *dst_base_sh = dst->shared->parent->shared; + + if (src_base_sh->u.atomic.u.f.sign != dst_base_sh->u.atomic.u.f.sign || + src_base_sh->u.atomic.u.f.epos != dst_base_sh->u.atomic.u.f.epos || + src_base_sh->u.atomic.u.f.esize != dst_base_sh->u.atomic.u.f.esize || + src_base_sh->u.atomic.u.f.ebias != dst_base_sh->u.atomic.u.f.ebias || + src_base_sh->u.atomic.u.f.mpos != dst_base_sh->u.atomic.u.f.mpos || + src_base_sh->u.atomic.u.f.msize != dst_base_sh->u.atomic.u.f.msize || + src_base_sh->u.atomic.u.f.norm != dst_base_sh->u.atomic.u.f.norm || + src_base_sh->u.atomic.u.f.pad != dst_base_sh->u.atomic.u.f.pad) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + break; + } + case H5T_NO_CLASS: case H5T_TIME: case H5T_STRING: @@ -328,11 +386,41 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, if (NULL == src) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - buf_stride = buf_stride ? buf_stride : src->shared->size; - md = src->shared->size / 2; - for (i = 0; i < nelmts; i++, buf += buf_stride) - for (j = 0; j < md; j++) - H5_SWAP_BYTES(buf, j, src->shared->size - (j + 1)); + src_size = src->shared->size; + buf_stride = buf_stride ? buf_stride : src_size; + md = src_size / 2; + + /* Complex number types are composed of two floating-point + * elements, each of which is half the size of the datatype + * and have to be converted separately. While halving the + * source datatype size and doubling the number elements to + * be converted works in some cases, structure padding can + * cause issues with that approach, so we special-case + * conversions on complex numbers here. + */ + if (H5T_COMPLEX == src->shared->type) { + size_t part_size = src_size / 2; + + md = part_size / 2; + for (i = 0; i < nelmts; i++, buf += buf_stride) { + uint8_t *cur_part = buf; + + /* Convert real part of complex number element */ + for (j = 0; j < md; j++) + H5_SWAP_BYTES(cur_part, j, part_size - (j + 1)); + + /* Convert imaginary part of complex number element */ + cur_part += part_size; + for (j = 0; j < md; j++) + H5_SWAP_BYTES(cur_part, j, part_size - (j + 1)); + } + } + else { + for (i = 0; i < nelmts; i++, buf += buf_stride) + for (j = 0; j < md; j++) + H5_SWAP_BYTES(buf, j, src_size - (j + 1)); + } + break; case H5T_CONV_FREE: @@ -350,13 +438,13 @@ H5T__conv_order(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, /*------------------------------------------------------------------------- * Function: H5T__conv_order_opt * - * Purpose: Convert one type to another when byte order is the only - * difference. This is the optimized version of H5T__conv_order() - * for a handful of different sizes. + * Purpose: Convert one type to another when byte order is the only + * difference. This is the optimized version of + * H5T__conv_order() for a handful of different sizes. * - * Note: This is a soft conversion function. + * Note: This is a soft conversion function. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ @@ -365,9 +453,12 @@ H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_conv_ctx_t H5_ATTR_UNUSED *conv_ctx, size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *_buf, void H5_ATTR_UNUSED *background) { - uint8_t *buf = (uint8_t *)_buf; - size_t i; - herr_t ret_value = SUCCEED; /* Return value */ + H5T_order_t src_order, dst_order; + uint8_t *buf = (uint8_t *)_buf; + size_t src_offset, dst_offset; + size_t src_size, dst_size; + size_t i; + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_PACKAGE @@ -376,19 +467,43 @@ H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, /* Capability query */ if (NULL == src || NULL == dst) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - if (src->shared->size != dst->shared->size || 0 != src->shared->u.atomic.offset || - 0 != dst->shared->u.atomic.offset) + + src_size = src->shared->size; + dst_size = dst->shared->size; + if (src_size != dst_size) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + + if (src->shared->parent) { + if (!H5T_IS_ATOMIC(src->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + src_offset = src->shared->parent->shared->u.atomic.offset; + src_order = src->shared->parent->shared->u.atomic.order; + } + else { + src_offset = src->shared->u.atomic.offset; + src_order = src->shared->u.atomic.order; + } + if (dst->shared->parent) { + if (!H5T_IS_ATOMIC(dst->shared->parent->shared)) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); + dst_offset = dst->shared->parent->shared->u.atomic.offset; + dst_order = dst->shared->parent->shared->u.atomic.order; + } + else { + dst_offset = dst->shared->u.atomic.offset; + dst_order = dst->shared->u.atomic.order; + } + + if (0 != src_offset || 0 != dst_offset) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); if ((src->shared->type == H5T_REFERENCE && dst->shared->type != H5T_REFERENCE) || (dst->shared->type == H5T_REFERENCE && src->shared->type != H5T_REFERENCE)) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); - if (src->shared->type != H5T_REFERENCE && !((H5T_ORDER_BE == src->shared->u.atomic.order && - H5T_ORDER_LE == dst->shared->u.atomic.order) || - (H5T_ORDER_LE == src->shared->u.atomic.order && - H5T_ORDER_BE == dst->shared->u.atomic.order))) + if (src->shared->type != H5T_REFERENCE && + !((H5T_ORDER_BE == src_order && H5T_ORDER_LE == dst_order) || + (H5T_ORDER_LE == src_order && H5T_ORDER_BE == dst_order))) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); - if (src->shared->size != 1 && src->shared->size != 2 && src->shared->size != 4 && - src->shared->size != 8 && src->shared->size != 16) + if (src_size != 1 && src_size != 2 && src_size != 4 && src_size != 8 && src_size != 16) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); switch (src->shared->type) { case H5T_INTEGER: @@ -417,6 +532,10 @@ H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, case H5T_ENUM: case H5T_VLEN: case H5T_ARRAY: + /* Complex numbers require some special-case logic for + * proper handling. Defer to H5T__conv_order for these types. + */ + case H5T_COMPLEX: case H5T_NCLASSES: default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "conversion not supported"); diff --git a/src/H5Tconv.h b/src/H5Tconv.h index 4dae848269d..03e74c18d8d 100644 --- a/src/H5Tconv.h +++ b/src/H5Tconv.h @@ -25,6 +25,15 @@ /* Length of debugging name buffer */ #define H5T_NAMELEN 32 +/* Swap two elements (I & J) of an array using a temporary variable */ +#define H5_SWAP_BYTES(ARRAY, I, J) \ + do { \ + uint8_t _tmp; \ + _tmp = ARRAY[I]; \ + ARRAY[I] = ARRAY[J]; \ + ARRAY[J] = _tmp; \ + } while (0) + /****************************/ /* Library Private Typedefs */ /****************************/ @@ -184,7 +193,7 @@ H5_DLL herr_t H5T__conv_order_opt(const H5T_t *src, const H5T_t *dst, H5T_cdata_ size_t bkg_stride, void *_buf, void *bkg); /* Utility functions */ -H5_DLL herr_t H5T__reverse_order(uint8_t *rev, uint8_t *s, size_t size, H5T_order_t order); +H5_DLL herr_t H5T__reverse_order(uint8_t *rev, uint8_t *s, const H5T_t *dtype); /* Debugging functions */ H5_DLL herr_t H5T__print_path_stats(H5T_path_t *path, int *nprint /*in,out*/); diff --git a/src/H5Tconv_bitfield.c b/src/H5Tconv_bitfield.c index 486036ad260..92d763d3636 100644 --- a/src/H5Tconv_bitfield.c +++ b/src/H5Tconv_bitfield.c @@ -105,7 +105,9 @@ H5T__conv_b_b(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ } /* Allocate space for order-reversed source buffer */ - src_rev = (uint8_t *)H5MM_calloc(src->shared->size); + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "unable to allocate temporary buffer"); /* The conversion loop */ H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); @@ -161,8 +163,7 @@ H5T__conv_b_b(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ if (src->shared->u.atomic.prec > dst->shared->u.atomic.prec) { /*overflow*/ if (conv_ctx->u.conv.cb_struct.func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + H5T__reverse_order(src_rev, s, src); /*reverse order first*/ except_ret = (conv_ctx->u.conv.cb_struct.func)( H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); diff --git a/src/H5Tconv_complex.c b/src/H5Tconv_complex.c new file mode 100644 index 00000000000..b8d4edef377 --- /dev/null +++ b/src/H5Tconv_complex.c @@ -0,0 +1,2323 @@ +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * 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"); + if (!src_p->shared->u.cplx.homogeneous || !dst_p->shared->u.cplx.homogeneous) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "source and destination complex number datatypes must be homogeneous"); + src_atomic = src_p->shared->parent->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for source datatype"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for destination datatype"); + if (dst_p->shared->size > 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(src_p->shared->u.cplx.homogeneous); + assert(dst_p); + assert(dst_p->shared->type == H5T_COMPLEX); + assert(dst_p->shared->u.cplx.homogeneous); + assert(conv_ctx); + assert(buf); + + FUNC_ENTER_PACKAGE + + src_atomic = src_p->shared->parent->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + src_part_size = src_p->shared->size / 2; + dst_part_size = dst_p->shared->size / 2; + + /* + * 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.homogeneous) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported form of complex number datatype for conversion"); + 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 806a7261677..7e0d914a97f 100644 --- a/src/H5Tconv_float.c +++ b/src/H5Tconv_float.c @@ -24,6 +24,8 @@ /***********/ #include "H5Tconv.h" #include "H5Tconv_macros.h" +#include "H5Tconv_complex.h" +#include "H5Tconv_integer.h" #include "H5Tconv_float.h" /*------------------------------------------------------------------------- @@ -42,54 +44,34 @@ H5T__conv_f_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { - /* Traversal-related variables */ - H5T_atomic_t src; /*atomic source info */ - H5T_atomic_t dst; /*atomic destination info */ - ssize_t src_delta, dst_delta; /*source & destination stride */ - int direction; /*forward or backward traversal */ - size_t elmtno; /*element number */ - size_t half_size; /*half the type size */ - size_t tsize; /*type size for swapping bytes */ - size_t olap; /*num overlapping elements */ - ssize_t bitno = 0; /*bit number */ - uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ - uint8_t *src_rev = NULL; /*order-reversed source buffer */ - uint8_t dbuf[64] = {0}; /*temp destination buffer */ - uint8_t tmp1, tmp2; /*temp variables for swapping bytes*/ - - /* Conversion-related variables */ - int64_t expo; /*exponent */ - hssize_t expo_max; /*maximum possible dst exponent */ - size_t msize = 0; /*useful size of mantissa in src*/ - size_t mpos; /*offset to useful mant is src */ - uint64_t sign; /*source sign bit value */ - size_t mrsh; /*amount to right shift mantissa*/ - bool carry = false; /*carry after rounding mantissa */ - size_t i; /*miscellaneous counters */ - size_t implied; /*destination implied bits */ - bool denormalized = false; /*is either source or destination denormalized?*/ - H5T_conv_ret_t except_ret; /*return of callback function */ - bool reverse; /*if reverse the order of destination */ - herr_t ret_value = SUCCEED; /*return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE switch (cdata->command) { - case H5T_CONV_INIT: + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + if (NULL == src_p || NULL == dst_p) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; - if (H5T_ORDER_LE != src.order && H5T_ORDER_BE != src.order && H5T_ORDER_VAX != src.order) + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); - if (H5T_ORDER_LE != dst.order && H5T_ORDER_BE != dst.order && H5T_ORDER_VAX != dst.order) + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); - if (dst_p->shared->size > sizeof(dbuf)) + if (dst_p->shared->size > TEMP_FLOAT_CONV_BUFFER_SIZE) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); - if (8 * sizeof(expo) - 1 < src.u.f.esize || 8 * sizeof(expo) - 1 < dst.u.f.esize) + if (8 * sizeof(int64_t) - 1 < src_atomic.u.f.esize || + 8 * sizeof(int64_t) - 1 < dst_atomic.u.f.esize) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); cdata->need_bkg = H5T_BKG_NO; + break; + } case H5T_CONV_FREE: break; @@ -100,524 +82,625 @@ H5T__conv_f_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const if (NULL == conv_ctx) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; - expo_max = ((hssize_t)1 << dst.u.f.esize) - 1; - - /* - * Do we process the values from beginning to end or vice versa? Also, - * how many of the elements have the source and destination areas - * overlapping? - */ - if (src_p->shared->size == dst_p->shared->size || buf_stride) { - sp = dp = (uint8_t *)buf; - direction = 1; - olap = nelmts; - } - else if (src_p->shared->size >= dst_p->shared->size) { - double olap_d = - ceil((double)(dst_p->shared->size) / (double)(src_p->shared->size - dst_p->shared->size)); - olap = (size_t)olap_d; - sp = dp = (uint8_t *)buf; - direction = 1; - } - else { - double olap_d = - ceil((double)(src_p->shared->size) / (double)(dst_p->shared->size - src_p->shared->size)); - olap = (size_t)olap_d; - sp = (uint8_t *)buf + (nelmts - 1) * src_p->shared->size; - dp = (uint8_t *)buf + (nelmts - 1) * dst_p->shared->size; - direction = -1; - } + if (H5T__conv_f_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); - /* - * Direction & size of buffer traversal. - */ - H5_CHECK_OVERFLOW(buf_stride, size_t, ssize_t); - H5_CHECK_OVERFLOW(src_p->shared->size, size_t, ssize_t); - H5_CHECK_OVERFLOW(dst_p->shared->size, size_t, ssize_t); - src_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : src_p->shared->size); - dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst_p->shared->size); - - /* Allocate space for order-reversed source buffer */ - src_rev = (uint8_t *)H5MM_calloc(src_p->shared->size); - - /* The conversion loop */ - for (elmtno = 0; elmtno < nelmts; elmtno++) { - /* Set these variables to default */ - except_ret = H5T_CONV_UNHANDLED; - reverse = true; + 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; + } + + /* + * 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); - } - 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); + 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) { - 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); - - /* Advance source & destination pointers by delta amounts */ - sp += src_delta; - dp += dst_delta; - } + /* + * 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); + } - break; + /* 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); - default: - HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); - } /* end switch */ + /* Advance source & destination pointers by delta amounts */ + sp += src_delta; + dp += dst_delta; + } /* end conversion loop */ done: - if (src_rev) - H5MM_free(src_rev); + H5MM_free(src_rev); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__conv_f_f() */ +} /* end H5T__conv_f_f_loop() */ + +/*------------------------------------------------------------------------- + * Function: H5T__conv_float_find_special + * + * Purpose: Helper function to inspect the bits of a floating-point + * value during data conversions and determine if that value + * is a special value (+/-Inf, +/-0, NaN). + * + * If `sign_out` is non-NULL, it is set to the value of the + * sign bit of the floating-point value. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +H5T_conv_float_specval_t +H5T__conv_float_find_special(const uint8_t *src_buf, const H5T_atomic_t *src_atomic, uint64_t *sign_out) +{ + uint64_t sign; /* sign bit value */ + H5T_conv_float_specval_t ret_value = H5T_CONV_FLOAT_SPECVAL_REGULAR; + + FUNC_ENTER_PACKAGE_NOERR + + assert(src_buf); + assert(src_atomic); + + /* Find the sign bit value of the source. */ + sign = H5T__bit_get_d(src_buf, src_atomic->u.f.sign, (size_t)1); + + /* Is the mantissa all 0 bits? */ + if (H5T__bit_find(src_buf, src_atomic->u.f.mpos, src_atomic->u.f.msize, H5T_BIT_LSB, true) < 0) { + /* Is the exponent all 0 bits? */ + if (H5T__bit_find(src_buf, src_atomic->u.f.epos, src_atomic->u.f.esize, H5T_BIT_LSB, true) < 0) + /* +0 or -0 */ + ret_value = sign ? H5T_CONV_FLOAT_SPECVAL_NEGZERO : H5T_CONV_FLOAT_SPECVAL_POSZERO; + /* Is the exponent all 1 bits? */ + else if (H5T__bit_find(src_buf, src_atomic->u.f.epos, src_atomic->u.f.esize, H5T_BIT_LSB, false) < 0) + /* +Inf or -Inf */ + ret_value = sign ? H5T_CONV_FLOAT_SPECVAL_NEGINF : H5T_CONV_FLOAT_SPECVAL_POSINF; + } + else { + bool exp_all_ones = + (H5T__bit_find(src_buf, src_atomic->u.f.epos, src_atomic->u.f.esize, H5T_BIT_LSB, false) < 0); + + /* For a source value with no implied mantissa bit, if the exponent bits + * are all 1s and only the 1st bit of the mantissa is set to 1, the value + * is infinity. The Intel-Linux "long double" is this case. + */ + if (H5T_NORM_NONE == src_atomic->u.f.norm && exp_all_ones && + H5T__bit_find(src_buf, src_atomic->u.f.mpos, src_atomic->u.f.msize - 1, H5T_BIT_LSB, true) < 0) + ret_value = sign ? H5T_CONV_FLOAT_SPECVAL_NEGINF : H5T_CONV_FLOAT_SPECVAL_POSINF; + else if (exp_all_ones) + ret_value = H5T_CONV_FLOAT_SPECVAL_NAN; + } + + if (sign_out) + *sign_out = sign; + + FUNC_LEAVE_NOAPI(ret_value); +} /* end H5T__conv_float_find_special() */ /*------------------------------------------------------------------------- * Function: H5T__conv_f_i @@ -635,49 +718,33 @@ H5T__conv_f_i(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) { - /* Traversal-related variables */ - H5T_atomic_t src; /*atomic source info */ - H5T_atomic_t dst; /*atomic destination info */ - int direction; /*forward or backward traversal */ - size_t elmtno; /*element number */ - size_t half_size; /*half the type size */ - size_t tsize; /*type size for swapping bytes */ - size_t olap; /*num overlapping elements */ - uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ - uint8_t *src_rev = NULL; /*order-reversed source buffer */ - uint8_t dbuf[64] = {0}; /*temp destination buffer */ - uint8_t tmp1, tmp2; /*temp variables for swapping bytes*/ - - /* Conversion-related variables */ - hssize_t expo; /*source exponent */ - hssize_t sign; /*source sign bit value */ - uint8_t *int_buf = NULL; /*buffer for temporary value */ - size_t buf_size; /*buffer size for temporary value */ - size_t i; /*miscellaneous counters */ - ssize_t msb_pos_s; /*first bit(MSB) in an integer */ - ssize_t new_msb_pos; /*MSB position after shifting mantissa by exponent */ - hssize_t shift_val; /*shift value when shifting mantissa by exponent */ - bool truncated; /*if fraction value is dropped */ - bool reverse; /*if reverse order of destination at the end */ - H5T_conv_ret_t except_ret; /*return of callback function */ - herr_t ret_value = SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; FUNC_ENTER_PACKAGE switch (cdata->command) { - case H5T_CONV_INIT: + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ + if (NULL == src_p || NULL == dst_p) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); - src = src_p->shared->u.atomic; - dst = dst_p->shared->u.atomic; - if (H5T_ORDER_LE != src.order && H5T_ORDER_BE != src.order && H5T_ORDER_VAX != src.order) + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order && + H5T_ORDER_VAX != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); - if (dst_p->shared->size > sizeof(dbuf)) + if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); - if (8 * sizeof(expo) - 1 < src.u.f.esize) + if (8 * sizeof(hssize_t) - 1 < src_atomic.u.f.esize) HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); cdata->need_bkg = H5T_BKG_NO; + break; + } case H5T_CONV_FREE: break; @@ -688,602 +755,628 @@ 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 /*------------------------------------------------------------------------- @@ -1512,6 +1605,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 /*------------------------------------------------------------------------- @@ -1773,6 +1919,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 * @@ -2032,6 +2237,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 * @@ -2296,3 +2560,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 df349d26874..902ad68f5bf 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 9128f777a79..1599f749420 100644 --- a/src/H5Tconv_integer.c +++ b/src/H5Tconv_integer.c @@ -118,7 +118,9 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ dst_delta = (ssize_t)direction * (ssize_t)(buf_stride ? buf_stride : dst->shared->size); /* Allocate space for order-reversed source buffer */ - src_rev = (uint8_t *)H5MM_calloc(src->shared->size); + if (conv_ctx->u.conv.cb_struct.func) + if (NULL == (src_rev = H5MM_calloc(src->shared->size))) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTALLOC, FAIL, "unable to allocate temporary buffer"); /* The conversion loop */ for (elmtno = 0; elmtno < nelmts; elmtno++) { @@ -198,8 +200,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); except_ret = (conv_ctx->u.conv.cb_struct.func)( H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev, d, @@ -234,8 +236,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow - source is negative*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); except_ret = (conv_ctx->u.conv.cb_struct.func)( H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev, d, @@ -262,8 +264,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow - source is positive*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); except_ret = (conv_ctx->u.conv.cb_struct.func)( H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev, d, @@ -295,8 +297,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); except_ret = (conv_ctx->u.conv.cb_struct.func)( H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev, d, @@ -343,8 +345,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); except_ret = (conv_ctx->u.conv.cb_struct.func)( H5T_CONV_EXCEPT_RANGE_LOW, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev, d, @@ -386,8 +388,8 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ /*overflow*/ if (conv_ctx->u.conv.cb_struct .func) { /*If user's exception handler is present, use it*/ - H5T__reverse_order(src_rev, s, src->shared->size, - src->shared->u.atomic.order); /*reverse order first*/ + /* reverse source buffer order first */ + H5T__reverse_order(src_rev, s, src); except_ret = (conv_ctx->u.conv.cb_struct.func)( H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, conv_ctx->u.conv.dst_type_id, src_rev, d, @@ -475,425 +477,529 @@ H5T__conv_i_i(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata, const H5T_ } /* end H5T__conv_i_i() */ /*------------------------------------------------------------------------- - * Function: H5T__conv_i_f + * Function: H5T__conv_i_f_loop * - * Purpose: Convert one integer type to a floating-point type. This is - * the catch-all function for integer-float conversions and - * is probably not particularly fast. + * Purpose: Implements the body of the conversion loop when converting + * integer values to floating-point values (including complex + * number values). Encapsulates common code that is shared + * between the H5T__conv_i_f conversion function and other + * functions where the logic is nearly identical, such as + * H5T__conv_i_complex. * * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ herr_t -H5T__conv_i_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, - size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, - void H5_ATTR_UNUSED *bkg) +H5T__conv_i_f_loop(const H5T_t *src_p, const H5T_t *dst_p, const H5T_conv_ctx_t *conv_ctx, size_t nelmts, + size_t buf_stride, void *buf) { - /* Traversal-related variables */ - H5T_atomic_t src; /*atomic source info */ - H5T_atomic_t dst; /*atomic destination info */ - int direction; /*forward or backward traversal */ - size_t elmtno; /*element number */ - size_t half_size; /*half the type size */ - size_t tsize; /*type size for swapping bytes */ - size_t olap; /*num overlapping elements */ - uint8_t *s, *sp, *d, *dp; /*source and dest traversal ptrs*/ - uint8_t *src_rev = NULL; /*order-reversed source buffer */ - uint8_t dbuf[64] = {0}; /*temp destination buffer */ - uint8_t tmp1, tmp2; /*temp variables for swapping bytes*/ - - /* Conversion-related variables */ - hsize_t expo; /*destination exponent */ - hsize_t expo_max; /*maximal possible exponent value */ - size_t sign; /*source sign bit value */ - bool is_max_neg; /*source is maximal negative value*/ - bool do_round; /*whether there is roundup */ - uint8_t *int_buf = NULL; /*buffer for temporary value */ - size_t buf_size; /*buffer size for temporary value */ - size_t i; /*miscellaneous counters */ - size_t first; /*first bit(MSB) in an integer */ - ssize_t sfirst; /*a signed version of `first' */ - H5T_conv_ret_t except_ret; /*return of callback function */ - bool reverse; /*if reverse the order of destination */ - herr_t ret_value = SUCCEED; /* Return value */ + 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) { + for (size_t i = 0; i < dst_p->shared->size / 2; i++) + H5_SWAP_BYTES(d, i, dst_p->shared->size - (i + 1)); + } + else if (H5T_ORDER_VAX == dst_atomic.order && reverse) { + if (H5T_FLOAT == dst_p->shared->type) { + uint8_t tmp1, tmp2; + size_t tsize = dst_p->shared->size; + assert(0 == tsize % 2); + + for (size_t i = 0; i < tsize; i += 4) { + tmp1 = d[i]; + tmp2 = d[i + 1]; + + d[i] = d[(tsize - 2) - i]; + d[i + 1] = d[(tsize - 1) - i]; + + d[(tsize - 2) - i] = tmp1; + d[(tsize - 1) - i] = tmp2; } + } + else + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "VAX byte ordering is unsupported for complex number type conversions"); + } + + /* + * If we had used a temporary buffer for the destination then we + * should copy the value to the true destination buffer. + */ + if (d == dbuf) /* For complex number values, assume that dbuf was initialized to 0s */ + H5MM_memcpy(dp, d, dst_p->shared->size); + else if (dst_p->shared->type == H5T_COMPLEX) + /* Ensure imaginary part of complex number is zeroed */ + memset(dp + (dst_p->shared->size / 2), 0, dst_p->shared->size / 2); + + /* Advance source & destination pointers by delta amounts */ + sp += src_delta; + dp += dst_delta; + + memset(int_buf, 0, int_buf_size); + } /* end conversion loop */ - /* Handle mantissa part here */ - if (H5T_NORM_IMPLIED == dst.u.f.norm) { - /* Imply first bit */ - H5T__bit_set(int_buf, first, (size_t)1, 0); - } - else if (H5T_NORM_NONE == dst.u.f.norm) { - first++; - } +done: + H5MM_free(src_rev); + H5MM_free(int_buf); - /* Roundup for mantissa */ - if (first > dst.u.f.msize) { - /* If the bit sequence is bigger than the mantissa part, there'll be some - * precision loss. Let user's handler deal with the case if it's present - */ - if (conv_ctx->u.conv.cb_struct.func) { - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_PRECISION, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); - } + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_i_f_loop() */ - if (except_ret == H5T_CONV_HANDLED) { - reverse = false; - goto padding; - } - else if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "can't handle conversion exception"); +/*------------------------------------------------------------------------- + * Function: H5T__conv_i_f + * + * Purpose: Convert one integer type to a floating-point type. This is + * the catch-all function for integer-float conversions and + * is probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_i_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, const H5T_conv_ctx_t *conv_ctx, + size_t nelmts, size_t buf_stride, size_t H5_ATTR_UNUSED bkg_stride, void *buf, + void H5_ATTR_UNUSED *bkg) +{ + herr_t ret_value = SUCCEED; /* Return value */ - /* If user's exception handler does deal with it, we do it by dropping off the - * extra bits at the end and do rounding. If we have .50...0(decimal) after radix - * point, we do roundup when the least significant digit before radix is odd, we do - * rounddown if it's even. - */ + FUNC_ENTER_PACKAGE - /* Check 1st dropoff bit, see if it's set. */ - if (H5T__bit_get_d(int_buf, ((first - dst.u.f.msize) - 1), (size_t)1)) { - /* Check all bits after 1st dropoff bit, see if any of them is set. */ - if (((first - dst.u.f.msize) - 1) > 0 && - H5T__bit_get_d(int_buf, (size_t)0, ((first - dst.u.f.msize) - 1))) - do_round = 1; - else { /* The .50...0 case */ - /* Check if the least significant bit is odd. */ - if (H5T__bit_get_d(int_buf, (first - dst.u.f.msize), (size_t)1)) - do_round = 1; - } - } + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ - /* Right shift to drop off extra bits */ - H5T__bit_shift(int_buf, (ssize_t)(dst.u.f.msize - first), (size_t)0, buf_size * 8); + if (NULL == src_p || NULL == dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order && + H5T_ORDER_VAX != dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unsupported byte order"); + if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination size is too large"); + if (8 * sizeof(hsize_t) - 1 < dst_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; - if (do_round) { - H5T__bit_inc(int_buf, (size_t)0, buf_size * 8); - do_round = 0; + break; + } - /* If integer is like 0x0ff...fff and we need to round up the - * last f, we get 0x100...000. Treat this special case here. - */ - if (H5T__bit_get_d(int_buf, dst.u.f.msize, (size_t)1)) { - if (H5T_NORM_IMPLIED == dst.u.f.norm) { - /* The bit at this 1's position was impled already, so this - * number should be 0x200...000. We need to increment the - * exponent in this case. - */ - expo++; - } - else if (H5T_NORM_NONE == dst.u.f.norm) { - /* Right shift 1 bit to let the carried 1 fit in the mantissa, - * and increment exponent by 1. - */ - H5T__bit_shift(int_buf, (ssize_t)-1, (size_t)0, buf_size * 8); - expo++; - } - } - } - } - else { - /* The bit sequence can fit mantissa part. Left shift to fit in from high-order of - * bit position. */ - H5T__bit_shift(int_buf, (ssize_t)(dst.u.f.msize - first), (size_t)0, dst.u.f.msize); - } + case H5T_CONV_FREE: + break; - /* Check if the exponent is too big */ - expo_max = (hsize_t)(pow(2.0, (double)dst.u.f.esize) - 1); + case H5T_CONV_CONV: + if (NULL == src_p || NULL == dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - if (expo > expo_max) { /*overflows*/ - if (conv_ctx->u.conv.cb_struct - .func) { /*user's exception handler. Reverse back source order*/ - H5T__reverse_order(src_rev, s, src_p->shared->size, - src_p->shared->u.atomic.order); /*reverse order first*/ - except_ret = (conv_ctx->u.conv.cb_struct.func)( - H5T_CONV_EXCEPT_RANGE_HI, conv_ctx->u.conv.src_type_id, - conv_ctx->u.conv.dst_type_id, src_rev, d, conv_ctx->u.conv.cb_struct.user_data); + if (H5T__conv_i_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); - if (except_ret == H5T_CONV_ABORT) - HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, - "can't handle conversion exception"); - else if (except_ret == H5T_CONV_HANDLED) { - reverse = false; - goto padding; - } - } + break; - if (!conv_ctx->u.conv.cb_struct.func || (except_ret == H5T_CONV_UNHANDLED)) { - /*make destination infinity by setting exponent to maximal number and - *mantissa to zero.*/ - expo = expo_max; - memset(int_buf, 0, buf_size); - } - } + default: + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); + } - if (except_ret == H5T_CONV_UNHANDLED) { - /* Set exponent in destination */ - H5T__bit_set_d(d, dst.u.f.epos, dst.u.f.esize, expo); +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5T__conv_i_f() */ - /* Copy mantissa into destination */ - H5T__bit_copy(d, dst.u.f.mpos, int_buf, (size_t)0, - (buf_size * 8) > dst.u.f.msize ? dst.u.f.msize : buf_size * 8); - } +/*------------------------------------------------------------------------- + * Function: H5T__conv_i_complex + * + * Purpose: Convert integer values to complex number values. This is + * the catch-all function for integer -> complex number + * conversions and is probably not particularly fast. + * + * Return: Non-negative on success/Negative on failure + * + *------------------------------------------------------------------------- + */ +herr_t +H5T__conv_i_complex(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata, + const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, + size_t H5_ATTR_UNUSED bkg_stride, void *buf, void H5_ATTR_UNUSED *bkg) +{ + herr_t ret_value = SUCCEED; -padding: - /* - * Set padding areas in destination. - */ - if (dst.offset > 0) { - assert(H5T_PAD_ZERO == dst.lsb_pad || H5T_PAD_ONE == dst.lsb_pad); - H5T__bit_set(d, (size_t)0, dst.offset, (bool)(H5T_PAD_ONE == dst.lsb_pad)); - } - if (dst.offset + dst.prec != 8 * dst_p->shared->size) { - assert(H5T_PAD_ZERO == dst.msb_pad || H5T_PAD_ONE == dst.msb_pad); - H5T__bit_set(d, dst.offset + dst.prec, 8 * dst_p->shared->size - (dst.offset + dst.prec), - (bool)(H5T_PAD_ONE == dst.msb_pad)); - } + FUNC_ENTER_PACKAGE - /* - * Put the destination in the correct byte order. See note at - * beginning of loop. - */ - if (H5T_ORDER_BE == dst.order && reverse) { - half_size = dst_p->shared->size / 2; - for (i = 0; i < half_size; i++) { - uint8_t tmp = d[dst_p->shared->size - (i + 1)]; - d[dst_p->shared->size - (i + 1)] = d[i]; - d[i] = tmp; - } - } - else if (H5T_ORDER_VAX == dst.order && reverse) { - tsize = dst_p->shared->size; - assert(0 == tsize % 2); + switch (cdata->command) { + case H5T_CONV_INIT: { + H5T_atomic_t src_atomic; /* source datatype atomic info */ + H5T_atomic_t dst_atomic; /* destination datatype atomic info */ - for (i = 0; i < tsize; i += 4) { - tmp1 = d[i]; - tmp2 = d[i + 1]; + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (!H5T_IS_ATOMIC(dst_p->shared->parent->shared)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid complex number datatype"); + src_atomic = src_p->shared->u.atomic; + dst_atomic = dst_p->shared->parent->shared->u.atomic; + if (H5T_ORDER_LE != src_atomic.order && H5T_ORDER_BE != src_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for source datatype"); + if (H5T_ORDER_LE != dst_atomic.order && H5T_ORDER_BE != dst_atomic.order) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, + "unsupported byte order for destination datatype"); + if (dst_p->shared->size > TEMP_INT_CONV_BUFFER_SIZE) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "destination datatype size is too large"); + if (8 * sizeof(hsize_t) - 1 < dst_atomic.u.f.esize) + HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "exponent field is too large"); + cdata->need_bkg = H5T_BKG_NO; - d[i] = d[(tsize - 2) - i]; - d[i + 1] = d[(tsize - 1) - i]; + break; + } - d[(tsize - 2) - i] = tmp1; - d[(tsize - 1) - i] = tmp2; - } - } + case H5T_CONV_FREE: + break; - /* - * If we had used a temporary buffer for the destination then we - * should copy the value to the true destination buffer. - */ - if (d == dbuf) - H5MM_memcpy(dp, d, dst_p->shared->size); - if (buf_stride) { - sp += direction * (ssize_t)buf_stride; - dp += direction * (ssize_t)buf_stride; - } - else { - sp += direction * (ssize_t)src_p->shared->size; - dp += direction * (ssize_t)dst_p->shared->size; - } + case H5T_CONV_CONV: + if (!src_p || !dst_p) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a datatype"); + if (NULL == conv_ctx) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid datatype conversion context pointer"); - memset(int_buf, 0, buf_size); - } + if (H5T__conv_i_f_loop(src_p, dst_p, conv_ctx, nelmts, buf_stride, buf) < 0) + HGOTO_ERROR(H5E_DATATYPE, H5E_CANTCONVERT, FAIL, "unable to convert data values"); break; default: HGOTO_ERROR(H5E_DATATYPE, H5E_UNSUPPORTED, FAIL, "unknown conversion command"); - } /* end switch */ + } done: - if (int_buf) - H5MM_xfree(int_buf); - if (src_rev) - H5MM_free(src_rev); - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5T__conv_i_f() */ +} /* end H5T__conv_i_complex() */ /*------------------------------------------------------------------------- * Function: H5T__conv_schar_uchar @@ -1121,6 +1227,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 * @@ -1347,6 +1512,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 * @@ -1573,6 +1797,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 * @@ -1781,26 +2064,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 @@ -2031,6 +2373,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 * @@ -2260,6 +2661,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 * @@ -2489,6 +2949,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 * @@ -2718,6 +3237,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 * @@ -2949,6 +3527,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 * @@ -3179,3 +3818,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 c8eff45a285..a871fc5fbe0 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 c2876670f5e..879a8889f47 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 ab6f5fc2d59..6c73563644e 100644 --- a/src/H5Tconv_vlen.c +++ b/src/H5Tconv_vlen.c @@ -56,7 +56,7 @@ H5FL_BLK_DEFINE_STATIC(vlen_seq); * Function: H5T__conv_vlen_nested_free * * Purpose: Recursively locates and frees any nested VLEN components of - * complex data types (including COMPOUND). + * composite data types (including COMPOUND). * * Return: Non-negative on success/Negative on failure. * @@ -100,6 +100,7 @@ H5T__conv_vlen_nested_free(uint8_t *buf, H5T_t *dt) case H5T_OPAQUE: case H5T_REFERENCE: case H5T_ENUM: + case H5T_COMPLEX: /* These types cannot contain vl data */ break; diff --git a/src/H5Tdbg.c b/src/H5Tdbg.c index b1de7708b8f..b0316f9bd0f 100644 --- a/src/H5Tdbg.c +++ b/src/H5Tdbg.c @@ -182,6 +182,31 @@ H5T_debug(const H5T_t *dt, FILE *stream) s1 = "struct"; break; + case H5T_REFERENCE: + switch (dt->shared->u.atomic.u.r.rtype) { + case H5R_OBJECT1: + s1 = "object reference (old)"; + break; + case H5R_OBJECT2: + s1 = "object reference (new)"; + break; + case H5R_DATASET_REGION1: + s1 = "region reference (old)"; + break; + case H5R_DATASET_REGION2: + s1 = "region reference (new)"; + break; + case H5R_ATTR: + s1 = "attribute reference"; + break; + case H5R_BADTYPE: + case H5R_MAXTYPE: + default: + s1 = "invalid reference"; + break; + } + break; + case H5T_ENUM: s1 = "enum"; break; @@ -193,8 +218,14 @@ H5T_debug(const H5T_t *dt, FILE *stream) s1 = "vlen"; break; - case H5T_REFERENCE: case H5T_ARRAY: + s1 = "array"; + break; + + case H5T_COMPLEX: + s1 = "complex number"; + break; + case H5T_NCLASSES: default: s1 = ""; @@ -342,6 +373,7 @@ H5T_debug(const H5T_t *dt, FILE *stream) case H5T_ENUM: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: /* No additional info */ @@ -407,6 +439,23 @@ H5T_debug(const H5T_t *dt, FILE *stream) else if (H5T_OPAQUE == dt->shared->type) { fprintf(stream, ", tag=\"%s\"", dt->shared->u.opaque.tag); } + else if (H5T_COMPLEX == dt->shared->type) { + fprintf(stream, ", %s", dt->shared->u.cplx.homogeneous ? "homogeneous" : "heterogeneous"); + switch (dt->shared->u.cplx.form) { + case H5T_COMPLEX_RECTANGULAR: + fprintf(stream, ", rectangular form"); + break; + case H5T_COMPLEX_POLAR: + fprintf(stream, ", polar form"); + break; + case H5T_COMPLEX_EXPONENTIAL: + fprintf(stream, ", exponential form"); + break; + default: + fprintf(stream, ", invalid form"); + break; + } + } else { /* Unknown */ fprintf(stream, "unknown class %d\n", (int)(dt->shared->type)); diff --git a/src/H5Tfields.c b/src/H5Tfields.c index 86c9e1eb51b..336d016476d 100644 --- a/src/H5Tfields.c +++ b/src/H5Tfields.c @@ -172,6 +172,7 @@ H5T__get_member_name(H5T_t const *dt, unsigned membno) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "operation not supported for type class"); @@ -231,6 +232,7 @@ H5Tget_member_index(hid_t type_id, const char *name) case H5T_REFERENCE: case H5T_VLEN: case H5T_ARRAY: + case H5T_COMPLEX: case H5T_NCLASSES: default: HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "operation not supported for this type"); diff --git a/src/H5Tfixed.c b/src/H5Tfixed.c index 178a0271fb4..b4495ddc465 100644 --- a/src/H5Tfixed.c +++ b/src/H5Tfixed.c @@ -23,13 +23,12 @@ #include "H5Tpkg.h" /*data-type functions */ /*------------------------------------------------------------------------- - * Function: H5Tget_sign + * Function: H5Tget_sign * - * Purpose: Retrieves the sign type for an integer type. + * Purpose: Retrieves the sign type for an integer type. * - * Return: Success: The sign type. - * - * Failure: H5T_SGN_ERROR (Negative) + * Return: Success: The sign type. + * Failure: H5T_SGN_ERROR (Negative) * *------------------------------------------------------------------------- */ @@ -52,14 +51,13 @@ H5Tget_sign(hid_t type_id) } /*------------------------------------------------------------------------- - * Function: H5T_get_sign + * Function: H5T_get_sign * - * Purpose: Private function for H5Tget_sign. Retrieves the sign type + * Purpose: Private function for H5Tget_sign. Retrieves the sign type * for an integer type. * - * Return: Success: The sign type. - * - * Failure: H5T_SGN_ERROR (Negative) + * Return: Success: The sign type. + * Failure: H5T_SGN_ERROR (Negative) * *------------------------------------------------------------------------- */ @@ -88,11 +86,11 @@ H5T_get_sign(H5T_t const *dt) } /*------------------------------------------------------------------------- - * Function: H5Tset_sign + * Function: H5Tset_sign * - * Purpose: Sets the sign property for an integer. + * Purpose: Sets the sign property for an integer. * - * Return: Non-negative on success/Negative on failure + * Return: Non-negative on success/Negative on failure * *------------------------------------------------------------------------- */ diff --git a/src/H5Tmodule.h b/src/H5Tmodule.h index 35e748bac3f..f98d43564ec 100644 --- a/src/H5Tmodule.h +++ b/src/H5Tmodule.h @@ -70,7 +70,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 * @@ -167,6 +167,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
* @@ -198,7 +200,7 @@ * - * * + * + * + * + * + * + * *
* Description * + * * Properties * @@ -350,6 +352,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 @@ -744,6 +760,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 * * @@ -1004,12 +1044,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. * * * @@ -1043,7 +1122,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). * * * @@ -1074,12 +1154,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 @@ -1087,7 +1167,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 @@ -1114,7 +1194,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 * * * @@ -1472,6 +1552,14 @@ * #H5Tvlen_create * * + * + * + * COMPLEX + * + * + * #H5Tcomplex_create + * + * * * * Once the datatype is created and the datatype properties set, the datatype object can be used. @@ -2404,7 +2492,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 @@ -2687,7 +2776,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). * @@ -2723,7 +2812,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: @@ -2776,14 +2865,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 @@ -2811,7 +2900,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 * * @@ -2823,10 +2912,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 @@ -2849,6 +2938,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. * @@ -2913,13 +3040,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 * \code @@ -2939,7 +3066,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 @@ -3740,11 +3867,12 @@ 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 DDLBNF116. The portion of the + * \ref DDLBNF116 that defines HDF5 datatypes appears below. * The definition of HDF5 datatypes from the HDF5 DDL * \code - * ::= | | | + * ::= | | | | + * * * ::= | |