Files
hdf5/java/test/TestH5T.java
T
jhendersonHDF 90429f5e7d Implement support for complex number datatypes (#4630)
* 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.
2024-10-31 13:54:25 -07:00

584 lines
20 KiB
Java

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* 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 LICENSE 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. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package test;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import hdf.hdf5lib.H5;
import hdf.hdf5lib.HDF5Constants;
import hdf.hdf5lib.exceptions.HDF5Exception;
import hdf.hdf5lib.exceptions.HDF5LibraryException;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
public class TestH5T {
@Rule
public TestName testname = new TestName();
private static final String H5_FILE = "testT.h5";
long H5fid = HDF5Constants.H5I_INVALID_HID;
long H5strdid = HDF5Constants.H5I_INVALID_HID;
private final void _deleteFile(String filename)
{
File file = null;
try {
file = new File(filename);
}
catch (Throwable err) {
}
if (file.exists()) {
try {
file.delete();
}
catch (SecurityException e) {
}
}
}
@Before
public void createH5file() throws NullPointerException, HDF5Exception
{
assertTrue("H5 open ids is 0", H5.getOpenIDCount() == 0);
System.out.print(testname.getMethodName());
H5fid = H5.H5Fcreate(H5_FILE, HDF5Constants.H5F_ACC_TRUNC, HDF5Constants.H5P_DEFAULT,
HDF5Constants.H5P_DEFAULT);
assertTrue("H5.H5Fcreate", H5fid > 0);
H5strdid = H5.H5Tcopy(HDF5Constants.H5T_C_S1);
assertTrue("H5.H5Tcopy", H5strdid > 0);
H5.H5Fflush(H5fid, HDF5Constants.H5F_SCOPE_LOCAL);
}
@After
public void deleteH5file() throws HDF5LibraryException
{
if (H5strdid >= 0)
try {
H5.H5Tclose(H5strdid);
}
catch (Exception ex) {
}
if (H5fid > 0)
try {
H5.H5Fclose(H5fid);
}
catch (Exception ex) {
}
_deleteFile(H5_FILE);
System.out.println();
}
@Test(expected = HDF5LibraryException.class)
public void testH5Tequal_type_error() throws Throwable
{
H5.H5Tequal(HDF5Constants.H5T_INTEGER, H5strdid);
}
@Test
public void testH5Tget_class()
{
try {
int result = H5.H5Tget_class(H5strdid);
assertTrue("H5.H5Tget_class", result > 0);
String class_name = H5.H5Tget_class_name(result);
assertTrue("H5.H5Tget_class", class_name.compareTo("H5T_STRING") == 0);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tget_class: " + err);
}
}
@Test
public void testH5Tget_size()
{
long dt_size = -1;
try {
dt_size = H5.H5Tget_size(H5strdid);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tget_size:H5.H5Tget_size " + err);
}
assertTrue("testH5Tget_size", dt_size > 0);
}
@Test
public void testH5Tset_size()
{
long dt_size = 5;
try {
H5.H5Tset_size(H5strdid, dt_size);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tset_size:H5.H5Tset_size " + err);
}
try {
dt_size = H5.H5Tget_size(H5strdid);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tget_size:H5.H5Tget_size " + err);
}
assertTrue("testH5Tget_size", dt_size == 5);
}
@Test
public void testH5Tarray_create()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
long[] adims = {3, 5};
try {
filetype_id = H5.H5Tarray_create(HDF5Constants.H5T_STD_I64LE, 2, adims);
assertTrue("testH5Tarray_create", filetype_id >= 0);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tarray_create.H5Tarray_create " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@Test
public void testH5Tget_array_ndims()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
int ndims = 0;
long[] adims = {3, 5};
try {
filetype_id = H5.H5Tarray_create(HDF5Constants.H5T_STD_I64LE, 2, adims);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tarray_create.H5Tarray_create " + err);
}
assertTrue("testH5Tget_array_ndims:H5Tarray_create", filetype_id >= 0);
try {
ndims = H5.H5Tget_array_ndims(filetype_id);
assertTrue("testH5Tget_array_ndims", ndims == 2);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tget_array_ndims.H5Tget_array_ndims " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@Test
public void testH5Tget_array_dims()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
int ndims = 0;
long[] adims = {3, 5};
long[] rdims = new long[2];
try {
filetype_id = H5.H5Tarray_create(HDF5Constants.H5T_STD_I64LE, 2, adims);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tarray_create.H5Tarray_create " + err);
}
assertTrue("testH5Tget_array_dims:H5Tarray_create", filetype_id >= 0);
try {
ndims = H5.H5Tget_array_dims(filetype_id, rdims);
assertTrue("testH5Tget_array_dims", ndims == 2);
assertTrue("testH5Tget_array_dims", adims[0] == rdims[0]);
assertTrue("testH5Tget_array_dims", adims[1] == rdims[1]);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tget_array_dims.H5Tget_array_dims " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@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()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
String enum_type = "Enum_type";
byte[] enum_val = new byte[1];
String enum_name = null;
// Create a enumerate datatype
try {
filetype_id = H5.H5Tcreate(HDF5Constants.H5T_ENUM, (long)1);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tenum_functions:H5Tcreate " + err);
}
assertTrue("testH5Tenum_functions:H5Tcreate", filetype_id >= 0);
try {
enum_val[0] = 10;
H5.H5Tenum_insert(filetype_id, "RED", enum_val);
enum_val[0] = 11;
H5.H5Tenum_insert(filetype_id, "GREEN", enum_val);
enum_val[0] = 12;
H5.H5Tenum_insert(filetype_id, "BLUE", enum_val);
enum_val[0] = 13;
H5.H5Tenum_insert(filetype_id, "ORANGE", enum_val);
enum_val[0] = 14;
H5.H5Tenum_insert(filetype_id, "YELLOW", enum_val);
// Query member number and member index by member name, for enumeration type.
assertTrue("Can't get member number", H5.H5Tget_nmembers(filetype_id) == 5);
assertTrue("Can't get correct index number", H5.H5Tget_member_index(filetype_id, "ORANGE") == 3);
// Commit enumeration datatype and close it */
H5.H5Tcommit(H5fid, enum_type, filetype_id, HDF5Constants.H5P_DEFAULT, HDF5Constants.H5P_DEFAULT,
HDF5Constants.H5P_DEFAULT);
H5.H5Tclose(filetype_id);
// Open the dataytpe for query
filetype_id = H5.H5Topen(H5fid, enum_type, HDF5Constants.H5P_DEFAULT);
assertTrue("testH5Tenum_functions:H5Tcreate", filetype_id >= 0);
// Query member number and member index by member name, for enumeration type
assertTrue("Can't get member number", H5.H5Tget_nmembers(filetype_id) == 5);
assertTrue("Can't get correct index number", H5.H5Tget_member_index(filetype_id, "ORANGE") == 3);
// Query member value by member name, for enumeration type
H5.H5Tenum_valueof(filetype_id, "ORANGE", enum_val);
assertTrue("Incorrect value for enum member", enum_val[0] == 13);
// Query member value by member index, for enumeration type
H5.H5Tget_member_value(filetype_id, 2, enum_val);
assertTrue("Incorrect value for enum member", enum_val[0] == 12);
// Query member name by member value, for enumeration type
enum_val[0] = 14;
enum_name = H5.H5Tenum_nameof(filetype_id, enum_val, 16);
assertTrue("Incorrect name for enum member", enum_name.compareTo("YELLOW") == 0);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tenum_functions:query " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@Test
public void testH5Tenum_create_functions()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
byte[] enum_val = new byte[1];
// Create a enumerate datatype
try {
filetype_id = H5.H5Tenum_create(HDF5Constants.H5T_NATIVE_INT);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tenum_create_functions:H5Tcreate " + err);
}
assertTrue("testH5Tenum_create_functions:H5Tcreate", filetype_id >= 0);
try {
enum_val[0] = 10;
H5.H5Tenum_insert(filetype_id, "RED", enum_val);
enum_val[0] = 11;
H5.H5Tenum_insert(filetype_id, "GREEN", enum_val);
enum_val[0] = 12;
H5.H5Tenum_insert(filetype_id, "BLUE", enum_val);
enum_val[0] = 13;
H5.H5Tenum_insert(filetype_id, "ORANGE", enum_val);
enum_val[0] = 14;
H5.H5Tenum_insert(filetype_id, "YELLOW", enum_val);
// Query member number and member index by member name, for enumeration type.
assertTrue("Can't get member number", H5.H5Tget_nmembers(filetype_id) == 5);
assertTrue("Can't get correct index number", H5.H5Tget_member_index(filetype_id, "ORANGE") == 3);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tenum_create_functions:H5Tget_nmembers " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@Test
public void testH5Topaque_functions()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
String opaque_name = null;
// Create a opaque datatype
try {
filetype_id = H5.H5Tcreate(HDF5Constants.H5T_OPAQUE, (long)4);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Topaque_functions:H5Tcreate " + err);
}
assertTrue("testH5Topaque_functions:H5Tcreate", filetype_id >= 0);
try {
H5.H5Tset_tag(filetype_id, "opaque type");
opaque_name = H5.H5Tget_tag(filetype_id);
assertTrue("Incorrect tag for opaque type", opaque_name.compareTo("opaque type") == 0);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Topaque_functions:H5Tset_get_tag " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@Test
public void testH5Tvlen_create()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
try {
filetype_id = H5.H5Tvlen_create(HDF5Constants.H5T_C_S1);
assertTrue("testH5Tvlen_create", filetype_id >= 0);
// Check if datatype is VL type
int vlclass = H5.H5Tget_class(filetype_id);
assertTrue("testH5Tvlen_create:H5Tget_class", vlclass == HDF5Constants.H5T_VLEN);
assertFalse("testH5Tis_variable_str:H5Tget_class", vlclass == HDF5Constants.H5T_STRING);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tvlen_create.H5Tvlen_create " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@Test
public void testH5Tis_variable_str()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
try {
filetype_id = H5.H5Tcopy(HDF5Constants.H5T_C_S1);
assertTrue("testH5Tis_variable_str.H5Tcopy: ", filetype_id >= 0);
// Convert to variable-length string
H5.H5Tset_size(filetype_id, HDF5Constants.H5T_VARIABLE);
// Check if datatype is VL string
int vlclass = H5.H5Tget_class(filetype_id);
assertTrue("testH5Tis_variable_str:H5Tget_class", vlclass == HDF5Constants.H5T_STRING);
assertFalse("testH5Tvlen_create:H5Tget_class", vlclass == HDF5Constants.H5T_VLEN);
assertTrue("testH5Tis_variable_str:H5Tis_variable_str", H5.H5Tis_variable_str(filetype_id));
// Verify that the class detects as a string
assertTrue("testH5Tis_variable_str:H5Tdetect_class",
H5.H5Tdetect_class(filetype_id, HDF5Constants.H5T_STRING));
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tis_variable_str " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
@Test
public void testH5Tcompound_functions()
{
long filetype_id = HDF5Constants.H5I_INVALID_HID;
// Create a compound datatype
try {
filetype_id = H5.H5Tcreate(HDF5Constants.H5T_COMPOUND, (long)16);
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tcompound_functions:H5Tcreate " + err);
}
assertTrue("testH5Tcompound_functions:H5Tcreate", filetype_id >= 0);
try {
H5.H5Tinsert(filetype_id, "Lon", 0, HDF5Constants.H5T_NATIVE_DOUBLE);
H5.H5Tinsert(filetype_id, "Lat", 8, HDF5Constants.H5T_NATIVE_DOUBLE);
// Query member number and member index by member name, for enumeration type.
assertTrue("Can't get member number", H5.H5Tget_nmembers(filetype_id) == 2);
assertTrue("Can't get correct index number", H5.H5Tget_member_index(filetype_id, "Lat") == 1);
// We started to support this function for compound type in 1.8.6 release.
int order = H5.H5Tget_order(filetype_id);
assertFalse("Can't get order for compound type.", order == HDF5Constants.H5T_ORDER_ERROR);
assertTrue("Wrong order for this type.",
(order == HDF5Constants.H5T_ORDER_LE) || (order == HDF5Constants.H5T_ORDER_BE));
// Make certain that the correct classes can be detected
assertTrue("Can't get correct class",
H5.H5Tdetect_class(filetype_id, HDF5Constants.H5T_COMPOUND));
assertTrue("Can't get correct class", H5.H5Tdetect_class(filetype_id, HDF5Constants.H5T_FLOAT));
// Make certain that an incorrect class is not detected
assertFalse("Can get incorrect class", H5.H5Tdetect_class(filetype_id, HDF5Constants.H5T_TIME));
// Query member name by member index
String index_name = H5.H5Tget_member_name(filetype_id, 0);
assertTrue("Incorrect name for member index", index_name.compareTo("Lon") == 0);
// Query member offset by member no
long index_offset = H5.H5Tget_member_offset(filetype_id, 1);
assertTrue("Incorrect offset for member no", index_offset == 8);
// Query member type by member index
long index_type = H5.H5Tget_member_type(filetype_id, 0);
assertTrue("Incorrect type for member index",
H5.H5Tequal(HDF5Constants.H5T_NATIVE_DOUBLE, index_type));
if (index_type >= 0)
try {
H5.H5Tclose(index_type);
}
catch (Exception ex) {
}
}
catch (Throwable err) {
err.printStackTrace();
fail("testH5Tcompound_functions:query " + err);
}
finally {
if (filetype_id >= 0)
try {
H5.H5Tclose(filetype_id);
}
catch (Exception ex) {
}
}
}
}