Skip to content

Commit

Permalink
Implement no-op compat conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
jhendersonHDF committed Jun 28, 2024
1 parent 276d780 commit 00978f2
Show file tree
Hide file tree
Showing 4 changed files with 1,020 additions and 53 deletions.
5 changes: 4 additions & 1 deletion src/H5T.c
Original file line number Diff line number Diff line change
Expand Up @@ -1311,7 +1311,6 @@ H5T_init(void)
status |= H5T__register_int(H5T_PERS_SOFT, "complexbo(opt)", cplx, cplx, H5T__conv_order_opt);
status |= H5T__register_int(H5T_PERS_SOFT, "struct(no-opt)", compound, compound, H5T__conv_struct);
status |= H5T__register_int(H5T_PERS_SOFT, "struct(opt)", compound, compound, H5T__conv_struct_opt);
/* TODO: complex number struct conversions */
status |= H5T__register_int(H5T_PERS_SOFT, "enum", enum_type, enum_type, H5T__conv_enum);
status |= H5T__register_int(H5T_PERS_SOFT, "enum_i", enum_type, fixedpt, H5T__conv_enum_numeric);
status |= H5T__register_int(H5T_PERS_SOFT, "enum_f", enum_type, floatpt, H5T__conv_enum_numeric);
Expand All @@ -1322,6 +1321,10 @@ 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
Expand Down
208 changes: 168 additions & 40 deletions src/H5Tconv_complex.c
Original file line number Diff line number Diff line change
Expand Up @@ -1385,53 +1385,181 @@ H5T__conv_complex_f_matched(const H5T_t *src_p, const H5T_t *dst_p, const H5T_co
} /* end H5T__conv_complex_f_matched() */

/*-------------------------------------------------------------------------
* Function: H5T__conv_complex_struct
*
* Purpose: Convert a complex number type to the equivalent compound
* type representation. A compound type must match one of the
* the following representations exactly to be considered
* equivalent.
*
* H5T_COMPOUND {
* <float_type> "r"; OFFSET 0
* <float_type> "i"; OFFSET SIZEOF("r")
* }
*
* H5T_COMPOUND {
* <float_type> "re"; OFFSET 0
* <float_type> "im"; OFFSET SIZEOF("re")
* }
*
* H5T_COMPOUND {
* <float_type> "real"; OFFSET 0
* <float_type> "imag"; OFFSET SIZEOF("real")
* }
*
* H5T_COMPOUND {
* <float_type> "real"; OFFSET 0
* <float_type> "imaginary"; OFFSET SIZEOF("real")
* }
* 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 {
* <float_type> "r(e)(a)(l)"; OFFSET 0
* <float_type> "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_struct(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata,
const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride, size_t bkg_stride,
void *_buf, void *bkg)
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)
{
(void)src;
(void)dst;
(void)cdata;
(void)conv_ctx;
(void)nelmts;
(void)buf_stride;
(void)bkg_stride;
(void)_buf;
(void)bkg;
return FAIL; /* TODO */
}
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
/*-------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/H5Tconv_complex.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ H5_DLL herr_t H5T__conv_complex_i(const H5T_t *src_p, const H5T_t *dst_p, H5T_cd
H5_DLL herr_t H5T__conv_complex_f(const H5T_t *src_p, const H5T_t *dst_p, H5T_cdata_t *cdata,
const H5T_conv_ctx_t *conv_ctx, size_t nelmts, size_t buf_stride,
size_t bkg_stride, void *buf, void *bkg);
H5_DLL herr_t H5T__conv_complex_struct(const H5T_t *src, const H5T_t *dst, H5T_cdata_t *cdata,
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);

Expand Down
Loading

0 comments on commit 00978f2

Please sign in to comment.