summaryrefslogtreecommitdiffstats
path: root/src/H5Sselect.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Sselect.c')
-rw-r--r--src/H5Sselect.c205
1 files changed, 94 insertions, 111 deletions
diff --git a/src/H5Sselect.c b/src/H5Sselect.c
index 24586de..d4ca1c7 100644
--- a/src/H5Sselect.c
+++ b/src/H5Sselect.c
@@ -32,7 +32,6 @@
#include "H5Eprivate.h" /* Error handling */
#include "H5FLprivate.h" /* Free Lists */
#include "H5Iprivate.h" /* IDs */
-#include "H5MMprivate.h" /* Memory management */
#include "H5Spkg.h" /* Dataspaces */
#include "H5VMprivate.h" /* Vector and array functions */
@@ -998,7 +997,9 @@ H5S_select_is_regular(const H5S_t *space)
herr_t
H5S_select_adjust_u(H5S_t *space, const hsize_t *offset)
{
- herr_t ret_value = FAIL; /* Return value */
+ hbool_t non_zero_offset = FALSE; /* Whether any offset is non-zero */
+ unsigned u; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
FUNC_ENTER_NOAPI_NOINIT_NOERR
@@ -1006,7 +1007,16 @@ H5S_select_adjust_u(H5S_t *space, const hsize_t *offset)
HDassert(space);
HDassert(offset);
- ret_value = (*space->select.type->adjust_u)(space, offset);
+ /* Check for an all-zero offset vector */
+ for(u = 0; u < space->extent.rank; u++)
+ if(0 != offset[u]) {
+ non_zero_offset = TRUE;
+ break;
+ } /* end if */
+
+ /* Only perform operation if the offset is non-zero */
+ if(non_zero_offset)
+ ret_value = (*space->select.type->adjust_u)(space, offset);
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_select_adjust_u() */
@@ -1098,11 +1108,12 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset)
PURPOSE
Initializes iteration information for a selection.
USAGE
- herr_t H5S_select_iter_init(sel_iter, space, elmt_size)
+ herr_t H5S_select_iter_init(sel_iter, space, elmt_size, flags)
H5S_sel_iter_t *sel_iter; OUT: Selection iterator to initialize.
H5S_t *space; IN: Dataspace object containing selection to
iterate over
size_t elmt_size; IN: Size of elements in the selection
+ unsigned flags; IN: Flags to control iteration behavior
RETURNS
Non-negative on success, negative on failure.
DESCRIPTION
@@ -1110,7 +1121,8 @@ H5S_select_project_simple(const H5S_t *space, H5S_t *new_space, hsize_t *offset)
in the dataspace's selection.
--------------------------------------------------------------------------*/
herr_t
-H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_size)
+H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space,
+ size_t elmt_size, unsigned flags)
{
herr_t ret_value = FAIL; /* Return value */
@@ -1125,17 +1137,23 @@ H5S_select_iter_init(H5S_sel_iter_t *sel_iter, const H5S_t *space, size_t elmt_s
/* Save the dataspace's rank */
sel_iter->rank = space->extent.rank;
- /* Point to the dataspace dimensions, if there are any */
- if(sel_iter->rank > 0)
- sel_iter->dims = space->extent.size;
- else
- sel_iter->dims = NULL;
+ /* If dims > 0, copy the dataspace dimensions & selection offset */
+ if(sel_iter->rank > 0) {
+ HDmemcpy(sel_iter->dims, space->extent.size, sizeof(hsize_t) * space->extent.rank);
+ HDmemcpy(sel_iter->sel_off, space->select.offset, sizeof(hsize_t) * space->extent.rank);
+ } /* end if */
/* Save the element size */
sel_iter->elmt_size = elmt_size;
+ /* Initialize the number of elements to iterate over */
+ sel_iter->elmt_left = space->select.num_elem;
+
+ /* Set the flags for the iterator */
+ sel_iter->flags = flags;
+
/* Call initialization routine for selection type */
- ret_value = (*space->select.type->iter_init)(sel_iter, space);
+ ret_value = (*space->select.type->iter_init)(space, sel_iter);
HDassert(sel_iter->type);
FUNC_LEAVE_NOAPI(ret_value)
@@ -1389,7 +1407,7 @@ H5S_select_iter_next_block(H5S_sel_iter_t *iter)
/*-------------------------------------------------------------------------
- * Function: H5S_select_get_seq_list
+ * Function: H5S_select_iter_get_seq_list
*
* Purpose: Retrieves the next sequence of offset/length pairs for an
* iterator on a dataspace
@@ -1406,24 +1424,23 @@ H5S_select_iter_next_block(H5S_sel_iter_t *iter)
*-------------------------------------------------------------------------
*/
herr_t
-H5S_select_get_seq_list(const H5S_t *space, unsigned flags,
- H5S_sel_iter_t *iter, size_t maxseq, size_t maxbytes,
- size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len)
+H5S_select_iter_get_seq_list(H5S_sel_iter_t *iter, size_t maxseq, size_t maxelmts,
+ size_t *nseq, size_t *nelmts, hsize_t *off, size_t *len)
{
herr_t ret_value = FAIL; /* Return value */
FUNC_ENTER_NOAPI_NOINIT
/* Sanity check */
- HDassert(space);
+ HDassert(iter);
/* Call the selection type's get_seq_list function */
- if((ret_value = (*space->select.type->get_seq_list)(space, flags, iter, maxseq, maxbytes, nseq, nbytes, off, len)) < 0)
+ if((ret_value = (*iter->type->iter_get_seq_list)(iter, maxseq, maxelmts, nseq, nelmts, off, len)) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get selection sequence list")
done:
FUNC_LEAVE_NOAPI(ret_value)
-} /* end H5S_select_get_seq_list() */
+} /* end H5S_select_iter_get_seq_list() */
/*--------------------------------------------------------------------------
@@ -1524,7 +1541,7 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
/* Initialize iterator */
- if(H5S_select_iter_init(iter, space, elmt_size) < 0)
+ if(H5S_select_iter_init(iter, space, elmt_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
iter_init = TRUE; /* Selection iteration info has been initialized */
@@ -1558,7 +1575,7 @@ H5S_select_iterate(void *buf, const H5T_t *type, const H5S_t *space,
size_t curr_seq; /* Current sequence being worked on */
/* Get the sequences of bytes */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Loop, while sequences left to process */
@@ -1729,7 +1746,6 @@ H5S_get_select_type(const H5S_t *space)
This is primarily used for reading the entire selection in one swoop.
GLOBAL VARIABLES
COMMENTS, BUGS, ASSUMPTIONS
- Assumes that there is only a single "block" for hyperslab selections.
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
@@ -1759,6 +1775,10 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
const H5S_t *space_b; /* Dataspace with smaller rank */
unsigned space_a_rank; /* Number of dimensions of dataspace A */
unsigned space_b_rank; /* Number of dimensions of dataspace B */
+ int space_a_dim; /* Current dimension in dataspace A */
+ int space_b_dim; /* Current dimension in dataspace B */
+ H5S_sel_type sel_a_type; /* Selection type for dataspace A */
+ H5S_sel_type sel_b_type; /* Selection type for dataspace B */
/* Need to be able to handle spaces of different rank:
*
@@ -1776,106 +1796,77 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
*/
if(space1->extent.rank >= space2->extent.rank) {
space_a = space1;
- space_a_rank = space_a->extent.rank;
-
space_b = space2;
- space_b_rank = space_b->extent.rank;
} /* end if */
else {
space_a = space2;
- space_a_rank = space_a->extent.rank;
-
space_b = space1;
- space_b_rank = space_b->extent.rank;
} /* end else */
+ space_a_rank = space_a->extent.rank;
+ space_b_rank = space_b->extent.rank;
HDassert(space_a_rank >= space_b_rank);
HDassert(space_b_rank > 0);
- /* Check for "easy" cases before getting into generalized block iteration code */
- if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_ALL) && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_ALL)) {
- hsize_t dims1[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #1 */
- hsize_t dims2[H5O_LAYOUT_NDIMS]; /* End point of selection block in dataspace #2 */
- int space_a_dim; /* Current dimension in dataspace A */
- int space_b_dim; /* Current dimension in dataspace B */
+ /* Get selection type for both dataspaces */
+ sel_a_type = H5S_GET_SELECT_TYPE(space_a);
+ sel_b_type = H5S_GET_SELECT_TYPE(space_b);
- if(H5S_get_simple_extent_dims(space_a, dims1, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
- if(H5S_get_simple_extent_dims(space_b, dims2, NULL) < 0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "unable to get dimensionality")
+ /* If selections aren't "none", compare their bounds */
+ if(sel_a_type != H5S_SEL_NONE && sel_b_type != H5S_SEL_NONE) {
+ hsize_t low_a[H5S_MAX_RANK]; /* Low bound of selection in dataspace a */
+ hsize_t low_b[H5S_MAX_RANK]; /* Low bound of selection in dataspace b */
+ hsize_t high_a[H5S_MAX_RANK]; /* High bound of selection in dataspace a */
+ hsize_t high_b[H5S_MAX_RANK]; /* High bound of selection in dataspace b */
- space_a_dim = (int)space_a_rank - 1;
- space_b_dim = (int)space_b_rank - 1;
-
- /* recall that space_a_rank >= space_b_rank.
- *
- * In the following while loop, we test to see if space_a and space_b
- * have identical size in all dimensions they have in common.
- */
- while(space_b_dim >= 0) {
- if(dims1[space_a_dim] != dims2[space_b_dim])
- HGOTO_DONE(FALSE)
-
- space_a_dim--;
- space_b_dim--;
- } /* end while */
-
- /* Since we are selecting the entire space, we must also verify that space_a
- * has size 1 in all dimensions that it does not share with space_b.
- */
- while(space_a_dim >= 0) {
- if(dims1[space_a_dim] != 1)
- HGOTO_DONE(FALSE)
-
- space_a_dim--;
- } /* end while */
- } /* end if */
- else if((H5S_GET_SELECT_TYPE(space1) == H5S_SEL_NONE) || (H5S_GET_SELECT_TYPE(space2) == H5S_SEL_NONE)) {
- /* (Both must be, at this point, if one is) */
- HGOTO_DONE(TRUE)
- } /* end if */
- else if((H5S_GET_SELECT_TYPE(space_a) == H5S_SEL_HYPERSLABS && space_a->select.sel_info.hslab->diminfo_valid)
- && (H5S_GET_SELECT_TYPE(space_b) == H5S_SEL_HYPERSLABS && space_b->select.sel_info.hslab->diminfo_valid)) {
- int space_a_dim; /* Current dimension in dataspace A */
- int space_b_dim; /* Current dimension in dataspace B */
+ /* Get low & high bounds for both dataspaces */
+ if(H5S_SELECT_BOUNDS(space_a, low_a, high_a) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds for first dataspace")
+ if(H5S_SELECT_BOUNDS(space_b, low_b, high_b) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds for second dataspace")
+ /* Check that the range between the low & high bounds are the same */
space_a_dim = (int)space_a_rank - 1;
space_b_dim = (int)space_b_rank - 1;
-
- /* check that the shapes are the same in the common dimensions, and that
- * block == 1 in all dimensions that appear only in space_a.
- */
while(space_b_dim >= 0) {
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].stride !=
- space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].stride)
- HGOTO_DONE(FALSE)
-
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].count !=
- space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].count)
- HGOTO_DONE(FALSE)
+ /* Sanity check */
+ HDassert(low_a[space_a_dim] <= high_a[space_a_dim]);
+ HDassert(low_a[space_b_dim] <= high_a[space_b_dim]);
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block !=
- space_b->select.sel_info.hslab->opt_diminfo[space_b_dim].block)
+ /* Verify that the ranges are the same */
+ if((high_a[space_a_dim] - low_a[space_a_dim])
+ != (high_b[space_b_dim] - low_b[space_b_dim]))
HGOTO_DONE(FALSE)
+ /* Go to next dimension */
space_a_dim--;
space_b_dim--;
} /* end while */
+ /* Check that the rest of the ranges in space a are "flat" */
while(space_a_dim >= 0) {
- if(space_a->select.sel_info.hslab->opt_diminfo[space_a_dim].block != 1)
+ /* Sanity check */
+ HDassert(low_a[space_a_dim] <= high_a[space_a_dim]);
+
+ /* This range should be flat to be the same in a lower dimension */
+ if(low_a[space_a_dim] != high_a[space_a_dim])
HGOTO_DONE(FALSE)
space_a_dim--;
} /* end while */
} /* end if */
- /* Iterate through all the blocks in the selection */
+
+ /* If the dataspaces have the same selection type, use the selection's
+ * shape_same operator.
+ */
+ if(sel_a_type == sel_b_type)
+ ret_value = (*space_a->select.type->shape_same)(space_a, space_b);
+ /* Otherwise, iterate through all the blocks in the selection */
else {
hsize_t start_a[H5S_MAX_RANK]; /* Start point of selection block in dataspace a */
hsize_t start_b[H5S_MAX_RANK]; /* Start point of selection block in dataspace b */
hsize_t end_a[H5S_MAX_RANK]; /* End point of selection block in dataspace a */
hsize_t end_b[H5S_MAX_RANK]; /* End point of selection block in dataspace b */
- hsize_t off_a[H5S_MAX_RANK]; /* Offset of selection a blocks */
- hsize_t off_b[H5S_MAX_RANK]; /* Offset of selection b blocks */
+ hssize_t offset[H5S_MAX_RANK]; /* Offset of selection b blocks relative to selection a blocks */
hbool_t first_block = TRUE; /* Flag to indicate the first block */
/* Allocate the selection iterators */
@@ -1889,17 +1880,15 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
* that the selection iterator shouldn't be "flattened", since we
* aren't actually going to be doing I/O with the iterators.
*/
- if(H5S_select_iter_init(iter_a, space_a, (size_t)0) < 0)
+ if(H5S_select_iter_init(iter_a, space_a, (size_t)0, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator a")
iter_a_init = TRUE;
- if(H5S_select_iter_init(iter_b, space_b, (size_t)0) < 0)
+ if(H5S_select_iter_init(iter_b, space_b, (size_t)0, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator b")
iter_b_init = TRUE;
/* Iterate over all the blocks in each selection */
while(1) {
- int space_a_dim; /* Current dimension in dataspace A */
- int space_b_dim; /* Current dimension in dataspace B */
htri_t status_a, status_b; /* Status from next block checks */
/* Get the current block for each selection iterator */
@@ -1924,8 +1913,7 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
HGOTO_DONE(FALSE)
/* Set the relative locations of the selections */
- off_a[space_a_dim] = start_a[space_a_dim];
- off_b[space_b_dim] = start_b[space_b_dim];
+ offset[space_a_dim] = (hssize_t)start_b[space_b_dim] - (hssize_t)start_a[space_a_dim];
space_a_dim--;
space_b_dim--;
@@ -1935,12 +1923,9 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
* in space_a is not equal to 1, get out.
*/
while(space_a_dim >= 0) {
- if((end_a[space_a_dim] - start_a[space_a_dim]) != 0)
+ if(start_a[space_a_dim] != end_a[space_a_dim])
HGOTO_DONE(FALSE)
- /* Set the relative locations of the selections */
- off_a[space_a_dim] = start_a[space_a_dim];
-
space_a_dim--;
} /* end while */
@@ -1952,8 +1937,7 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
/* For dimensions that space_a and space_b have in common: */
while(space_b_dim >= 0) {
/* Check if the blocks are in the same relative location */
- if((start_a[space_a_dim] - off_a[space_a_dim]) !=
- (start_b[space_b_dim] - off_b[space_b_dim]))
+ if((hsize_t)((hssize_t)start_a[space_a_dim] + offset[space_a_dim]) != start_b[space_b_dim])
HGOTO_DONE(FALSE)
/* If the block sizes from each selection doesn't match, get out */
@@ -1968,7 +1952,7 @@ H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2)
/* For dimensions that appear only in space_a: */
while(space_a_dim >= 0) {
/* If the block size isn't 1, get out */
- if((end_a[space_a_dim] - start_a[space_a_dim]) != 0)
+ if(start_a[space_a_dim] != end_a[space_a_dim])
HGOTO_DONE(FALSE)
space_a_dim--;
@@ -2329,7 +2313,7 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate selection iterator")
/* Initialize iterator */
- if(H5S_select_iter_init(iter, space, fill_size) < 0)
+ if(H5S_select_iter_init(iter, space, fill_size, 0) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
iter_init = TRUE; /* Selection iteration info has been initialized */
@@ -2353,7 +2337,7 @@ H5S_select_fill(const void *fill, size_t fill_size, const H5S_t *space, void *_b
size_t nelem; /* Number of elements used in sequences */
/* Get the sequences of bytes */
- if(H5S_SELECT_GET_SEQ_LIST(space, 0, iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
+ if(H5S_SELECT_ITER_GET_SEQ_LIST(iter, (size_t)H5D_IO_VECTOR_SIZE, max_elem, &nseq, &nelem, off, len) < 0)
HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
/* Loop over sequences */
@@ -2528,12 +2512,13 @@ H5S_select_subtract(H5S_t *space, H5S_t *subtract_space)
if(H5S_select_none(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
} /* end if */
+ /* If either selection is a point selection, fail currently */
+ else if((subtract_space->select.type->type == H5S_SEL_POINTS) ||
+ (space->select.type->type == H5S_SEL_POINTS)) {
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
+ } /* end if */
else {
- /* Check for point selection in subtract_space, convert to hyperslab */
- if(subtract_space->select.type->type == H5S_SEL_POINTS)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
-
- /* Check for point or all selection in space, convert to hyperslab */
+ /* Check for all selection in space, convert to hyperslab */
if(space->select.type->type == H5S_SEL_ALL) {
/* Convert current "all" selection to "real" hyperslab selection */
/* Then allow operation to proceed */
@@ -2555,14 +2540,12 @@ H5S_select_subtract(H5S_t *space, H5S_t *subtract_space)
if(H5S_select_hyperslab(space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection")
} /* end if */
- else if(space->select.type->type == H5S_SEL_POINTS)
- HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "point selections not currently supported")
HDassert(space->select.type->type == H5S_SEL_HYPERSLABS);
HDassert(subtract_space->select.type->type == H5S_SEL_HYPERSLABS);
/* Both spaces are now hyperslabs, perform the operation */
- if(H5S__hyper_subtract(space, subtract_space) < 0)
+ if(H5S__modify_select(space, H5S_SELECT_NOTB, subtract_space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't subtract hyperslab")
} /* end else */
} /* end if */