While debugging a workaround for H5Sselect_hyperslab
we noticed that H5Scombine_select
can’t be used with certain special selections, e.g. H5S_SEL_NONE
and H5S_SEL_ALL
. Note that the intersection of two hyperslabs might not be considered a hyperslab selection. For example when using H5S_SELECT_AND
with two non-overlapping selections (the result is H5S_SEL_NONE
). We’re wondering if there’s a more rebust way of combining two selections than H5Scombine_select
? Even a partial solution that works only for all combination of H5S_SEL_{NONE,HYPERSLAB,ALL}
and all combination of H5S_SEL_{NONE,POINT,ALL}
would be very helpful.
Here’s a reproducer:
// file: select_none-v2.cpp
#include <hdf5.h>
#include <iostream>
#include <array>
hid_t select_none(hsize_t * dims) {
auto space_id = H5Screate_simple(2, dims, nullptr);
H5Sselect_none(space_id);
return space_id;
}
void select_hyperslab(hid_t space_id, H5S_seloper_t op, std::array<hsize_t, 2> offset, std::array<hsize_t, 2> count) {
H5Sselect_hyperslab(space_id, op, offset.data(), nullptr, count.data(), nullptr);
}
int main() {
size_t n = 100000000, m = 20;
hsize_t dims[] = {n, m};
auto left_space_id = select_none(dims);
select_hyperslab(left_space_id, H5S_SELECT_OR, {0, 0}, {1, 4});
select_hyperslab(left_space_id, H5S_SELECT_AND, {3, 0}, {1, 4});
if(H5Sget_select_type(left_space_id) == H5S_SEL_NONE) {
std::cout << "left_space_id is H5S_SEL_NONE. \n" << std::endl;
}
auto right_space_id = select_none(dims);
select_hyperslab(right_space_id, H5S_SELECT_OR, {1, 0}, {1, 4});
auto space_id = H5Scombine_select(left_space_id, H5S_SELECT_OR, right_space_id);
H5Sclose(left_space_id);
H5Sclose(right_space_id);
H5Sclose(space_id);
return 0;
}
which we compile and run as follows:
$ g++ select_none-v2.cpp -o select_none-v2 -l hdf5 && ./select_none-v2
left_space_id is H5S_SEL_NONE.
HDF5-DIAG: Error detected in HDF5 (1.14.4-3) thread 0:
#000: H5Shyper.c line 10774 in H5Scombine_select(): dataspaces don't have hyperslab selections
major: Invalid arguments to routine
minor: Bad value
HDF5-DIAG: Error detected in HDF5 (1.14.4-3) thread 0:
#000: H5S.c line 438 in H5Sclose(): not a dataspace
major: Invalid arguments to routine
minor: Inappropriate type
Why is this an issue for us?
This is becomes tedious when trying to write generic code that combines two selections. For example in library code, we’re given two selections and an operation to join them and no additional information. We need to check if either of the two selections is empty and implement special cases, if they are. Then we also need to avoid H5S_SEL_ALL
. Then we need to consider that the result of combining H5S_SEL_ALL
with a “hyperslab” needs to be hand-coded for each operation (OR, AND, XOR, NOTA, etc).
I’d like to repeat that the intersection or union of hyperslabs is not always a hyperslab. Therefore, even if we know that we’d dealing with a sequence of operations on “hyperslabs” we can’t avoid the logic for checking the corner cases. As a result very precise testing (or luck) is required to avoid writing code that is mostly correct, but breaks for specific input.