summaryrefslogtreecommitdiffstats
path: root/src/H5Shyper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r--src/H5Shyper.c1570
1 files changed, 1510 insertions, 60 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 10bcdd6..28cabf0 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -45,6 +45,10 @@ static herr_t H5S_hyper_generate_spans(H5S_t *space);
#ifdef NEW_HYPERSLAB_API
static herr_t H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2);
#endif /*NEW_HYPERSLAB_API*/
+static void H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride,
+ hsize_t *count, hsize_t *block, hsize_t clip_size);
+static hsize_t H5S__hyper_get_clip_extent_real(const H5S_t *clip_space,
+ hsize_t num_slices, hbool_t incl_trail);
/* Selection callbacks */
static herr_t H5S_hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
@@ -55,9 +59,13 @@ static herr_t H5S_hyper_release(H5S_t *space);
static htri_t H5S_hyper_is_valid(const H5S_t *space);
static hssize_t H5S_hyper_serial_size(const H5S_t *space);
static herr_t H5S_hyper_serialize(const H5S_t *space, uint8_t **p);
-static herr_t H5S_hyper_deserialize(H5S_t *space, const uint8_t **p);
+static herr_t H5S_hyper_deserialize(H5S_t *space, uint32_t version, uint8_t flags,
+ const uint8_t **p);
static herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end);
static herr_t H5S_hyper_offset(const H5S_t *space, hsize_t *offset);
+static int H5S__hyper_unlim_dim(const H5S_t *space);
+static herr_t H5S_hyper_num_elem_non_unlim(const H5S_t *space,
+ hsize_t *num_elem_non_unlim);
static htri_t H5S_hyper_is_contiguous(const H5S_t *space);
static htri_t H5S_hyper_is_single(const H5S_t *space);
static htri_t H5S_hyper_is_regular(const H5S_t *space);
@@ -94,6 +102,8 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{
H5S_hyper_deserialize,
H5S_hyper_bounds,
H5S_hyper_offset,
+ H5S__hyper_unlim_dim,
+ H5S_hyper_num_elem_non_unlim,
H5S_hyper_is_contiguous,
H5S_hyper_is_single,
H5S_hyper_is_regular,
@@ -248,6 +258,7 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space)
/* Check args */
HDassert(space && H5S_SEL_HYPERSLABS == H5S_GET_SELECT_TYPE(space));
HDassert(iter);
+ HDassert(space->select.sel_info.hslab->unlim_dim < 0);
/* Initialize the number of points to iterate over */
iter->elmt_left = space->select.num_elem;
@@ -1644,6 +1655,8 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection)
dst_hslab->app_diminfo[u]=src_hslab->app_diminfo[u];
} /* end for */
} /* end if */
+ dst_hslab->unlim_dim = src_hslab->unlim_dim;
+ dst_hslab->num_elem_non_unlim = src_hslab->num_elem_non_unlim;
dst->select.sel_info.hslab->span_lst=src->select.sel_info.hslab->span_lst;
/* Check if there is hyperslab span information to copy */
@@ -1759,6 +1772,10 @@ H5S_hyper_is_valid (const H5S_t *space)
HDassert(space);
+ /* Check for unlimited selection */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_DONE(FALSE)
+
/* Check for a "regular" hyperslab selection */
if(space->select.sel_info.hslab->diminfo_valid) {
const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab->opt_diminfo; /* local alias for diminfo */
@@ -1863,6 +1880,7 @@ H5S_get_select_hyper_nblocks(H5S_t *space)
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(space);
+ HDassert(space->select.sel_info.hslab->unlim_dim < 0);
/* Check for a "regular" hyperslab selection */
if(space->select.sel_info.hslab->diminfo_valid) {
@@ -1910,6 +1928,8 @@ H5Sget_select_hyper_nblocks(hid_t spaceid)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_HYPERSLABS)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection")
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot get number of blocks for unlimited selection")
ret_value = (hssize_t)H5S_get_select_hyper_nblocks(space);
@@ -1948,24 +1968,41 @@ H5S_hyper_serial_size(const H5S_t *space)
HDassert(space);
- /* Basic number of bytes required to serialize hyperslab selection:
- * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
- * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)> = 24 bytes
- */
- ret_value = 24;
+ /* Check for version (right now, an unlimited dimension is the only thing
+ * that would bump the version) */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ /* Version 2 */
+ /* Size required is always:
+ * <type (4 bytes)> + <version (4 bytes)> + <flags (1 byte)> +
+ * <length (4 bytes)> + <rank (4 bytes)> +
+ * (4 (start/stride/count/block) * <rank> * <value (8 bytes)>) =
+ * 17 + (4 * rank * 8) bytes
+ */
+ ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)space->extent.rank
+ * (hssize_t)8);
+ else {
+ /* Version 1 */
+ /* Basic number of bytes required to serialize hyperslab selection:
+ * <type (4 bytes)> + <version (4 bytes)> + <padding (4 bytes)> +
+ * <length (4 bytes)> + <rank (4 bytes)> + <# of blocks (4 bytes)>
+ * = 24 bytes
+ */
+ ret_value = 24;
- /* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
- /* Check each dimension */
- for(block_count = 1, u = 0; u < space->extent.rank; u++)
- block_count *= space->select.sel_info.hslab->opt_diminfo[u].count;
- } /* end if */
- else
- /* Spin through hyperslab spans, adding 8 * rank bytes for each block */
- block_count = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
+ /* Check for a "regular" hyperslab selection */
+ if(space->select.sel_info.hslab->diminfo_valid) {
+ /* Check each dimension */
+ for(block_count = 1, u = 0; u < space->extent.rank; u++)
+ block_count *= space->select.sel_info.hslab->opt_diminfo[u].count;
+ } /* end if */
+ else
+ /* Spin through hyperslab spans, adding 8 * rank bytes for each
+ * block */
+ block_count = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
- H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, hssize_t);
- ret_value += (hssize_t)(8 * block_count * space->extent.rank);
+ H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, hssize_t);
+ ret_value += (hssize_t)(8 * block_count * space->extent.rank);
+ } /* end else */
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_serial_size() */
@@ -2020,8 +2057,7 @@ H5S_hyper_serialize_helper(const H5S_hyper_span_info_t *spans,
end[rank]=curr->high;
/* Recurse down to the next dimension */
- *p = pp;
- H5S_hyper_serialize_helper(curr->down, start, end, rank + 1, p);
+ H5S_hyper_serialize_helper(curr->down, start, end, rank + 1, &pp);
} /* end if */
else {
/* Encode all the previous dimensions starting & ending points */
@@ -2079,12 +2115,14 @@ H5S_hyper_serialize(const H5S_t *space, uint8_t **p)
const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
uint8_t *pp = (*p); /* Local pointer for decoding */
hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
- hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */
+ hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */
hsize_t start[H5O_LAYOUT_NDIMS]; /* Location of start of hyperslab */
hsize_t end[H5O_LAYOUT_NDIMS]; /* Location of end of hyperslab */
- hsize_t temp_off; /* Offset in a given dimension */
+ hsize_t temp_off; /* Offset in a given dimension */
uint8_t *lenp; /* pointer to length location for later storage */
uint32_t len = 0; /* number of bytes used */
+ uint32_t version; /* Version number */
+ uint8_t flags = 0; /* Flags for message */
hsize_t block_count; /* block counter for regular hyperslabs */
unsigned fast_dim; /* Rank of the fastest changing dimension for the dataspace */
unsigned ndims; /* Rank of the dataspace */
@@ -2092,15 +2130,25 @@ H5S_hyper_serialize(const H5S_t *space, uint8_t **p)
FUNC_ENTER_NOAPI_NOINIT_NOERR
- /* Check args */
HDassert(space);
HDassert(p);
HDassert(pp);
+ /* Calculate version */
+ if(space->select.sel_info.hslab->unlim_dim >= 0) {
+ version = 2;
+ flags |= H5S_SELECT_FLAG_UNLIM;
+ } /* end if */
+ else
+ version = 1;
+
/* Store the preamble information */
UINT32ENCODE(pp, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
- UINT32ENCODE(pp, (uint32_t)1); /* Store the version number */
- UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
+ UINT32ENCODE(pp, version); /* Store the version number */
+ if(version >= 2)
+ *(pp)++ = flags; /* Store the flags */
+ else
+ UINT32ENCODE(pp, (uint32_t)0); /* Store the un-used padding */
lenp = pp; /* keep the pointer to the length location for later */
pp += 4; /* skip over space for length */
@@ -2108,8 +2156,23 @@ H5S_hyper_serialize(const H5S_t *space, uint8_t **p)
UINT32ENCODE(pp, (uint32_t)space->extent.rank);
len += 4;
+ /* If there is an unlimited dimension, only encode opt_unlim_diminfo */
+ if(flags & H5S_SELECT_FLAG_UNLIM) {
+ unsigned i;
+
+ HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
+
+ /* Iterate over dimensions */
+ for(i = 0; i < space->extent.rank; i++) {
+ /* Encode start/stride/block/count */
+ UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].start);
+ UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].stride);
+ UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].count);
+ UINT64ENCODE(pp, space->select.sel_info.hslab->opt_diminfo[i].block);
+ } /* end for */
+ } /* end if */
/* Check for a "regular" hyperslab selection */
- if(space->select.sel_info.hslab->diminfo_valid) {
+ else if(space->select.sel_info.hslab->diminfo_valid) {
unsigned u; /* Local counting variable */
/* Set some convienence values */
@@ -2209,8 +2272,7 @@ H5S_hyper_serialize(const H5S_t *space, uint8_t **p)
len += (uint32_t)(8 * space->extent.rank * block_count);
/* Encode each hyperslab in selection */
- *p = pp;
- H5S_hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, p);
+ H5S_hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, &pp);
} /* end else */
/* Encode length */
@@ -2232,6 +2294,8 @@ H5S_hyper_serialize(const H5S_t *space, uint8_t **p)
herr_t H5S_hyper_deserialize(space, p)
H5S_t *space; IN/OUT: Dataspace pointer to place
selection into
+ uint32_t version IN: Selection version
+ uint8_t flags IN: Selection flags
uint8 **p; OUT: Pointer to buffer holding serialized
selection. Will be advanced to end of
serialized selection.
@@ -2246,10 +2310,11 @@ H5S_hyper_serialize(const H5S_t *space, uint8_t **p)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_hyper_deserialize(H5S_t *space, const uint8_t **p)
+H5S_hyper_deserialize(H5S_t *space, uint32_t H5_ATTR_UNUSED version, uint8_t flags,
+ const uint8_t **p)
{
- const uint8_t *pp = (*p); /* Local pointer for decoding */
unsigned rank; /* rank of points */
+ const uint8_t *pp = (*p); /* Local pointer for decoding */
size_t num_elem=0; /* number of elements in selection */
hsize_t start[H5O_LAYOUT_NDIMS]; /* hyperslab start information */
hsize_t end[H5O_LAYOUT_NDIMS]; /* hyperslab end information */
@@ -2274,32 +2339,54 @@ H5S_hyper_deserialize(H5S_t *space, const uint8_t **p)
/* Deserialize slabs to select */
/* (The header and rank have already beed decoded) */
rank = space->extent.rank; /* Retrieve rank from space */
- UINT32DECODE(pp,num_elem); /* decode the number of points */
- /* Set the count & stride for all blocks */
- for(tcount=count,tstride=stride,j=0; j<rank; j++,tstride++,tcount++) {
- *tcount=1;
- *tstride=1;
- } /* end for */
+ /* If there is an unlimited dimension, only encode opt_unlim_diminfo */
+ if(flags & H5S_SELECT_FLAG_UNLIM) {
+ HDassert(H5S_UNLIMITED == HSIZE_UNDEF);
+ HDassert(version >= 2);
+
+ /* Iterate over dimensions */
+ for(i = 0; i < space->extent.rank; i++) {
+ /* Decode start/stride/block/count */
+ UINT64DECODE(pp, start[i]);
+ UINT64DECODE(pp, stride[i]);
+ UINT64DECODE(pp, count[i]);
+ UINT64DECODE(pp, block[i]);
+ } /* end for */
- /* Retrieve the coordinates from the buffer */
- for(i=0; i<num_elem; i++) {
- /* Decode the starting points */
- for(tstart=start,j=0; j<rank; j++,tstart++)
- UINT32DECODE(pp, *tstart);
+ /* Select the hyperslab to the current selection */
+ if((ret_value = H5S_select_hyperslab(space, H5S_SELECT_SET, start, stride, count, block)) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ } /* end if */
+ else {
+ /* decode the number of points */
+ UINT32DECODE(pp,num_elem);
- /* Decode the ending points */
- for(tend=end,j=0; j<rank; j++,tend++)
- UINT32DECODE(pp, *tend);
+ /* Set the count & stride for all blocks */
+ for(tcount = count, tstride = stride, j = 0; j < rank; j++, tstride++, tcount++) {
+ *tcount=1;
+ *tstride=1;
+ } /* end for */
- /* Change the ending points into blocks */
- for(tblock=block,tstart=start,tend=end,j=0; j<rank; j++,tstart++,tend++,tblock++)
- *tblock=(*tend-*tstart)+1;
+ /* Retrieve the coordinates from the buffer */
+ for(i = 0; i < num_elem; i++) {
+ /* Decode the starting points */
+ for(tstart=start,j=0; j<rank; j++,tstart++)
+ UINT32DECODE(pp, *tstart);
- /* Select or add the hyperslab to the current selection */
- if((ret_value=H5S_select_hyperslab(space,(i==0 ? H5S_SELECT_SET : H5S_SELECT_OR),start,stride,count,block))<0)
- HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
- } /* end for */
+ /* Decode the ending points */
+ for(tend = end, j = 0; j < rank; j++, tend++)
+ UINT32DECODE(pp, *tend);
+
+ /* Change the ending points into blocks */
+ for(tblock=block,tstart=start,tend=end,j=0; j<rank; j++,tstart++,tend++,tblock++)
+ *tblock=(*tend-*tstart)+1;
+
+ /* Select or add the hyperslab to the current selection */
+ if((ret_value=H5S_select_hyperslab(space,(i==0 ? H5S_SELECT_SET : H5S_SELECT_OR),start,stride,count,block))<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
+ } /* end for */
+ } /* end else */
/* Update decoding pointer */
*p = pp;
@@ -2452,6 +2539,7 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc
HDassert(space);
HDassert(buf);
+ HDassert(space->select.sel_info.hslab->unlim_dim < 0);
/* Check for a "regular" hyperslab selection */
if(space->select.sel_info.hslab->diminfo_valid) {
@@ -2475,11 +2563,19 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc
*/
diminfo = space->select.sel_info.hslab->opt_diminfo;
else
- /*
- * Use the "application dimension information" to pass back to the user
- * the blocks they set, not the optimized, internal information.
- */
- diminfo = space->select.sel_info.hslab->app_diminfo;
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ /*
+ * There is an unlimited dimension so we must use opt_diminfo as
+ * it has been "clipped" to the current extent.
+ */
+ diminfo = space->select.sel_info.hslab->opt_diminfo;
+ else
+ /*
+ * Use the "application dimension information" to pass back to
+ * the user the blocks they set, not the optimized, internal
+ * information.
+ */
+ diminfo = space->select.sel_info.hslab->app_diminfo;
/* Build the tables of count sizes as well as the initial offset */
for(u = 0; u < ndims; u++) {
@@ -2616,6 +2712,8 @@ H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock,
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space")
if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_HYPERSLABS)
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection")
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot get blocklist for unlimited selection")
/* Go get the correct number of blocks */
if(numblocks > 0)
@@ -2758,7 +2856,10 @@ H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
start[i] = diminfo[i].start + (hsize_t)space->select.offset[i];
/* Compute the largest location in this dimension */
- end[i] = diminfo[i].start + diminfo[i].stride * (diminfo[i].count - 1) + (diminfo[i].block - 1) + (hsize_t)space->select.offset[i];
+ if((int)i == space->select.sel_info.hslab->unlim_dim)
+ end[i] = H5S_UNLIMITED;
+ else
+ end[i] = diminfo[i].start + diminfo[i].stride * (diminfo[i].count - 1) + (diminfo[i].block - 1) + (hsize_t)space->select.offset[i];
} /* end for */
} /* end if */
else {
@@ -2881,6 +2982,75 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5S__hyper_unlim_dim
+ PURPOSE
+ Return unlimited dimension of selection, or -1 if none
+ USAGE
+ int H5S__hyper_unlim_dim(space)
+ H5S_t *space; IN: Dataspace pointer to check
+ RETURNS
+ Unlimited dimension of selection, or -1 if none (never fails).
+ DESCRIPTION
+ Returns the index of the unlimited dimension of the selection, or -1
+ if the selection has no unlimited dimension.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static int
+H5S__hyper_unlim_dim(const H5S_t *space)
+{
+ FUNC_ENTER_STATIC_NOERR
+
+ FUNC_LEAVE_NOAPI(space->select.sel_info.hslab->unlim_dim);
+} /* end H5S__hyper_unlim_dim() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_num_elem_non_unlim
+ PURPOSE
+ Return number of elements in the non-unlimited dimensions
+ USAGE
+ herr_t H5S_hyper_num_elem_non_unlim(space,num_elem_non_unlim)
+ H5S_t *space; IN: Dataspace pointer to check
+ hsize_t *num_elem_non_unlim; OUT: Number of elements in the non-unlimited dimensions
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ Returns the number of elements in a slice through the non-unlimited
+ dimensions of the selection. Fails if the selection has no unlimited
+ dimension.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_hyper_num_elem_non_unlim(const H5S_t *space, hsize_t *num_elem_non_unlim)
+{
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Sanity check */
+ HDassert(space);
+ HDassert(num_elem_non_unlim);
+
+ /* Get number of elements in the non-unlimited dimensions */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ *num_elem_non_unlim = space->select.sel_info.hslab->num_elem_non_unlim;
+ else
+ HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL, "selection has no unlimited dimension")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_num_elem_non_unlim() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_hyper_is_contiguous
PURPOSE
Check if a hyperslab selection is contiguous within the dataspace extent.
@@ -3592,6 +3762,9 @@ H5S_hyper_add_span_element(H5S_t *space, unsigned rank, hsize_t *coords)
/* Reset "regular" hyperslab flag */
space->select.sel_info.hslab->diminfo_valid = FALSE;
+ /* Set unlim_dim */
+ space->select.sel_info.hslab->unlim_dim = -1;
+
/* Set # of elements in selection */
space->select.num_elem = 1;
} /* end if */
@@ -4301,6 +4474,9 @@ H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off
if(NULL == (new_space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
+ /* Set unlim_dim */
+ new_space->select.sel_info.hslab->unlim_dim = -1;
+
/* Check for a "regular" hyperslab selection */
if(base_space->select.sel_info.hslab->diminfo_valid) {
unsigned base_space_dim; /* Current dimension in the base dataspace */
@@ -6047,6 +6223,15 @@ H5S_hyper_generate_spans(H5S_t *space)
/* Get the diminfo */
for(u=0; u<space->extent.rank; u++) {
+ /* Check for unlimited dimension and return error */
+ /* These should be able to be converted to assertions once everything
+ * that calls this function checks for unlimited selections first
+ * (especially the new hyperslab API) -NAF */
+ if(space->select.sel_info.hslab->opt_diminfo[u].count == H5S_UNLIMITED)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited count")
+ if(space->select.sel_info.hslab->opt_diminfo[u].block == H5S_UNLIMITED)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "can't generate spans with unlimited block")
+
tmp_start[u]=space->select.sel_info.hslab->opt_diminfo[u].start;
tmp_stride[u]=space->select.sel_info.hslab->opt_diminfo[u].stride;
tmp_count[u]=space->select.sel_info.hslab->opt_diminfo[u].count;
@@ -6334,6 +6519,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
const hsize_t *opt_count; /* Optimized count information */
const hsize_t *opt_block; /* Optimized block information */
unsigned u; /* Counters */
+ int unlim_dim = -1; /* Unlimited dimension in selection, of -1 if none */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -6352,6 +6538,18 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
if(block==NULL)
block = _ones;
+ /* Check for unlimited dimension */
+ for(u = 0; u<space->extent.rank; u++)
+ if((count[u] == H5S_UNLIMITED) || (block[u] == H5S_UNLIMITED)) {
+ if(unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ else {
+ if(count[u] == block[u] /* == H5S_UNLIMITED */)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
+ unlim_dim = (int)u;
+ } /* end else */
+ } /* end if */
+
/*
* Check new selection.
*/
@@ -6400,7 +6598,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
opt_block = int_block;
for(u=0; u<space->extent.rank; u++) {
/* contiguous hyperslabs have the block size equal to the stride */
- if(stride[u]==block[u]) {
+ if((stride[u] == block[u]) && (count[u] != H5S_UNLIMITED)) {
int_count[u]=1;
int_stride[u]=1;
if(block[u]==1)
@@ -6412,7 +6610,8 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
if(count[u]==1)
int_stride[u]=1;
else {
- HDassert(stride[u] > block[u]);
+ HDassert((stride[u] > block[u]) || ((stride[u] == block[u])
+ && (count[u] == H5S_UNLIMITED)));
int_stride[u]=stride[u];
} /* end else */
int_count[u]=count[u];
@@ -6421,6 +6620,32 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
} /* end for */
} /* end else */
+ /* Check for operating on unlimited selection */
+ if((H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS)
+ && (space->select.sel_info.hslab->unlim_dim >= 0)
+ && (op != H5S_SELECT_SET))
+ {
+ /* Check for invalid operation */
+ if(unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
+ if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTA)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation on unlimited selection")
+ HDassert(space->select.sel_info.hslab->diminfo_valid);
+
+ /* Clip unlimited selection to include new selection */
+ if(H5S_hyper_clip_unlim(space,
+ start[space->select.sel_info.hslab->unlim_dim]
+ + ((opt_count[space->select.sel_info.hslab->unlim_dim]
+ - (hsize_t)1)
+ * opt_stride[space->select.sel_info.hslab->unlim_dim])
+ + opt_block[space->select.sel_info.hslab->unlim_dim]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection")
+
+ /* If an empty space was returned it must be "none" */
+ HDassert((space->select.num_elem > (hsize_t)0)
+ || (space->select.type->type == H5S_SEL_NONE));
+ } /* end if */
+
/* Fixup operation for non-hyperslab selections */
switch(H5S_GET_SELECT_TYPE(space)) {
case H5S_SEL_NONE: /* No elements selected in dataspace */
@@ -6540,16 +6765,64 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
space->select.num_elem *= (opt_count[u] * opt_block[u]);
} /* end for */
+ /* Save unlim_dim */
+ space->select.sel_info.hslab->unlim_dim = unlim_dim;
+
/* Indicate that the dimension information is valid */
space->select.sel_info.hslab->diminfo_valid = TRUE;
/* Indicate that there's no slab information */
space->select.sel_info.hslab->span_lst = NULL;
+
+ /* Handle unlimited selections */
+ if(unlim_dim >= 0) {
+ /* Calculate num_elem_non_unlim */
+ space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++)
+ if((int)u != unlim_dim)
+ space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
+
+ /* Set num_elem */
+ if(space->select.num_elem != (hsize_t)0)
+ space->select.num_elem = H5S_UNLIMITED;
+ } /* end if */
} /* end if */
else if(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA) {
/* Sanity check */
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
+ /* Handle unlimited selections */
+ if(unlim_dim >= 0) {
+ hsize_t bounds_start[H5S_MAX_RANK];
+ hsize_t bounds_end[H5S_MAX_RANK];
+ hsize_t tmp_count = opt_count[unlim_dim];
+ hsize_t tmp_block = opt_block[unlim_dim];
+
+ /* Check for invalid operation */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
+ if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTB)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation with unlimited selection")
+
+ /* Get bounds of existing selection */
+ if(H5S_hyper_bounds(space, bounds_start, bounds_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
+
+ /* Patch count and block to remove unlimited and include the
+ * existing selection */
+ H5S__hyper_get_clip_diminfo(start[unlim_dim], opt_stride[unlim_dim], &tmp_count, &tmp_block, bounds_end[unlim_dim] + (hsize_t)1);
+ HDassert((tmp_count == 1) || (opt_count != _ones));
+ HDassert((tmp_block == 1) || (opt_block != _ones));
+ if(opt_count != _ones) {
+ HDassert(opt_count == int_count);
+ int_count[unlim_dim] = tmp_count;
+ } /* end if */
+ if(opt_block != _ones) {
+ HDassert(opt_block == int_block);
+ int_block[unlim_dim] = tmp_block;
+ } /* end if */
+ } /* end if */
+
/* Check if there's no hyperslab span information currently */
if(NULL == space->select.sel_info.hslab->span_lst)
if(H5S_hyper_generate_spans(space) < 0)
@@ -6896,6 +7169,9 @@ H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op,
/* Allocate space for the hyperslab selection information */
if((space->select.sel_info.hslab=H5FL_MALLOC(H5S_hyper_sel_t))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
+
+ /* Set unlim_dim */
+ space->select.sel_info.hslab->unlim_dim = -1;
} /* end if */
/* Combine tmp_space (really space) & new_space, with the result in space */
@@ -6943,6 +7219,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
const hsize_t *opt_count; /* Optimized count information */
const hsize_t *opt_block; /* Optimized block information */
unsigned u; /* Counters */
+ int unlim_dim = -1; /* Unlimited dimension in selection, of -1 if none */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOAPI(FAIL)
@@ -6961,6 +7238,18 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
if(block==NULL)
block = _ones;
+ /* Check for unlimited dimension */
+ for(u = 0; u<space->extent.rank; u++)
+ if((count[u] == H5S_UNLIMITED) || (block[u] == H5S_UNLIMITED)) {
+ if(unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ else {
+ if(count[u] == block[u] /* == H5S_UNLIMITED */)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
+ unlim_dim = (int)u;
+ } /* end else */
+ } /* end if */
+
/*
* Check new selection.
*/
@@ -7005,7 +7294,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
opt_block = int_block;
for(u=0; u<space->extent.rank; u++) {
/* contiguous hyperslabs have the block size equal to the stride */
- if(stride[u]==block[u]) {
+ if((stride[u] == block[u]) && (count[u] != H5S_UNLIMITED)) {
int_count[u]=1;
int_stride[u]=1;
if(block[u]==1)
@@ -7017,7 +7306,8 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
if(count[u]==1)
int_stride[u]=1;
else {
- HDassert(stride[u] > block[u]);
+ HDassert((stride[u] > block[u]) || ((stride[u] == block[u])
+ && (count[u] == H5S_UNLIMITED)));
int_stride[u]=stride[u];
} /* end else */
int_count[u]=count[u];
@@ -7026,6 +7316,32 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
} /* end for */
} /* end else */
+ /* Check for operating on unlimited selection */
+ if((H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS)
+ && (space->select.sel_info.hslab->unlim_dim >= 0)
+ && (op != H5S_SELECT_SET))
+ {
+ /* Check for invalid operation */
+ if(unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
+ if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTA)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation on unlimited selection")
+ HDassert(space->select.sel_info.hslab->diminfo_valid);
+
+ /* Clip unlimited selection to include new selection */
+ if(H5S_hyper_clip_unlim(space,
+ start[space->select.sel_info.hslab->unlim_dim]
+ + ((opt_count[space->select.sel_info.hslab->unlim_dim]
+ - (hsize_t)1)
+ * opt_stride[space->select.sel_info.hslab->unlim_dim])
+ + opt_block[space->select.sel_info.hslab->unlim_dim]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection")
+
+ /* If an empty space was returned it must be "none" */
+ HDassert((space->select.num_elem > (hsize_t)0)
+ || (space->select.type->type == H5S_SEL_NONE));
+ } /* end if */
+
/* Fixup operation for non-hyperslab selections */
switch(H5S_GET_SELECT_TYPE(space)) {
case H5S_SEL_NONE: /* No elements selected in dataspace */
@@ -7136,16 +7452,64 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
space->select.num_elem*=(opt_count[u]*opt_block[u]);
} /* end for */
+ /* Save unlim_dim */
+ space->select.sel_info.hslab->unlim_dim = unlim_dim;
+
/* Indicate that the dimension information is valid */
space->select.sel_info.hslab->diminfo_valid = TRUE;
/* Indicate that there's no slab information */
space->select.sel_info.hslab->span_lst = NULL;
+
+ /* Handle unlimited selections */
+ if(unlim_dim >= 0) {
+ /* Calculate num_elem_non_unlim */
+ space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++)
+ if((int)u != unlim_dim)
+ space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
+
+ /* Set num_elem */
+ if(space->select.num_elem != (hsize_t)0)
+ space->select.num_elem = H5S_UNLIMITED;
+ } /* end if */
} /* end if */
else if(op>=H5S_SELECT_OR && op<=H5S_SELECT_NOTA) {
/* Sanity check */
HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS);
+ /* Handle unlimited selections */
+ if(unlim_dim >= 0) {
+ hsize_t bounds_start[H5S_MAX_RANK];
+ hsize_t bounds_end[H5S_MAX_RANK];
+ hsize_t tmp_count = opt_count[unlim_dim];
+ hsize_t tmp_block = opt_block[unlim_dim];
+
+ /* Check for invalid operation */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot modify unlimited selection with another unlimited selection")
+ if(!((op == H5S_SELECT_AND) || (op == H5S_SELECT_NOTB)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "unsupported operation with unlimited selection")
+
+ /* Get bounds of existing selection */
+ if(H5S_hyper_bounds(space, bounds_start, bounds_end) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't get selection bounds")
+
+ /* Patch count and block to remove unlimited and include the
+ * existing selection */
+ H5S__hyper_get_clip_diminfo(start[unlim_dim], opt_stride[unlim_dim], &tmp_count, &tmp_block, bounds_end[unlim_dim] + (hsize_t)1);
+ HDassert((tmp_count == 1) || (opt_count != _ones));
+ HDassert((tmp_block == 1) || (opt_block != _ones));
+ if(opt_count != _ones) {
+ HDassert(opt_count == int_count);
+ int_count[unlim_dim] = tmp_count;
+ } /* end if */
+ if(opt_block != _ones) {
+ HDassert(opt_block == int_block);
+ int_block[unlim_dim] = tmp_block;
+ } /* end if */
+ } /* end if */
+
/* Check if there's no hyperslab span information currently */
if(NULL == space->select.sel_info.hslab->span_lst)
if(H5S_hyper_generate_spans(space) < 0)
@@ -7351,6 +7715,9 @@ H5S_combine_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
if((new_space->select.sel_info.hslab=H5FL_CALLOC(H5S_hyper_sel_t))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab info")
+ /* Set unlim_dim */
+ new_space->select.sel_info.hslab->unlim_dim = -1;
+
/* Combine space1 & space2, with the result in new_space */
if(H5S_operate_hyperslab(new_space,space1->select.sel_info.hslab->span_lst,op,space2->select.sel_info.hslab->span_lst,FALSE,&span2_owned)<0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information")
@@ -7480,6 +7847,9 @@ H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2)
if((space1->select.sel_info.hslab=H5FL_CALLOC(H5S_hyper_sel_t))==NULL)
HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
+ /* Set unlim_dim */
+ space1->select.sel_info.hslab->unlim_dim = -1;
+
/* Combine tmp_spans (from space1) & spans from space2, with the result in space1 */
if(H5S_operate_hyperslab(space1,tmp_spans,op,space2->select.sel_info.hslab->span_lst,FALSE,&span2_owned)<0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
@@ -8752,6 +9122,7 @@ H5S_hyper_get_seq_list(const H5S_t *space, unsigned H5_ATTR_UNUSED flags, H5S_se
HDassert(nelem);
HDassert(off);
HDassert(len);
+ HDassert(space->select.sel_info.hslab->unlim_dim < 0);
/* Check for the special case of just one H5Sselect_hyperslab call made */
if(space->select.sel_info.hslab->diminfo_valid) {
@@ -8881,6 +9252,1085 @@ H5S_hyper_get_seq_list(const H5S_t *space, unsigned H5_ATTR_UNUSED flags, H5S_se
/*--------------------------------------------------------------------------
NAME
+ H5S__hyper_project_intersection
+ PURPOSE
+ Projects the intersection of of the selections of src_space and
+ src_intersect_space within the selection of src_space as a selection
+ within the selection of dst_space
+ USAGE
+ herr_t H5S__hyper_project_intersection(src_space,dst_space,src_intersect_space,proj_space)
+ H5S_t *src_space; IN: Selection that is mapped to dst_space, and intersected with src_intersect_space
+ H5S_t *dst_space; IN: Selection that is mapped to src_space, and which contains the result
+ H5S_t *src_intersect_space; IN: Selection whose intersection with src_space is projected to dst_space to obtain the result
+ H5S_t *proj_space; OUT: Will contain the result (intersection of src_intersect_space and src_space projected from src_space to dst_space) after the operation
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Projects the intersection of of the selections of src_space and
+ src_intersect_space within the selection of src_space as a selection
+ within the selection of dst_space. The result is placed in the
+ selection of proj_space. Note src_space, dst_space, and
+ src_intersect_space do not need to use hyperslab selections, but they
+ cannot use point selections. The result is always a hyperslab
+ selection.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S__hyper_project_intersection(const H5S_t *src_space, const H5S_t *dst_space,
+ const H5S_t *src_intersect_space, H5S_t *proj_space)
+{
+ hsize_t ss_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_space */
+ size_t ss_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_space */
+ size_t ss_nseq; /* Number of sequences for src_space */
+ size_t ss_nelem; /* Number of elements for src_space */
+ size_t ss_i = (size_t)0; /* Index into offset/length arrays for src_space */
+ hbool_t advance_ss = FALSE; /* Whether to advance ss_i on the next iteration */
+ H5S_sel_iter_t ss_iter; /* Selection iterator for src_space */
+ hbool_t ss_iter_init = FALSE; /* Whether ss_iter is initialized */
+ hsize_t ss_sel_off = (hsize_t)0; /* Offset within src_space selection */
+ hsize_t ds_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for dst_space */
+ size_t ds_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for dst_space */
+ size_t ds_nseq; /* Number of sequences for dst_space */
+ size_t ds_nelem; /* Number of elements for dst_space */
+ size_t ds_i = (size_t)0; /* Index into offset/length arrays for dst_space */
+ H5S_sel_iter_t ds_iter; /* Selection iterator for dst_space */
+ hbool_t ds_iter_init = FALSE; /* Whether ds_iter is initialized */
+ hsize_t ds_sel_off = (hsize_t)0; /* Offset within dst_space selection */
+ hsize_t sis_off[H5S_PROJECT_INTERSECT_NSEQS]; /* Offset array for src_intersect_space */
+ size_t sis_len[H5S_PROJECT_INTERSECT_NSEQS]; /* Length array for src_intersect_space */
+ size_t sis_nseq; /* Number of sequences for src_intersect_space */
+ size_t sis_nelem; /* Number of elements for src_intersect_space */
+ size_t sis_i = (size_t)0; /* Index into offset/length arrays for src_intersect_space */
+ hbool_t advance_sis = FALSE; /* Whether to advance sis_i on the next iteration */
+ H5S_sel_iter_t sis_iter; /* Selection iterator for src_intersect_space */
+ hbool_t sis_iter_init = FALSE; /* Whether sis_iter is initialized */
+ hsize_t int_sel_off; /* Offset within intersected selections (ss/sis and ds/ps) */
+ size_t int_len; /* Length of segment in intersected selections */
+ hsize_t proj_off; /* Segment offset in proj_space */
+ size_t proj_len; /* Segment length in proj_space */
+ size_t proj_len_rem; /* Remaining length in proj_space for segment */
+ hsize_t proj_down_dims[H5S_MAX_RANK]; /* "Down" dimensions in proj_space */
+ H5S_hyper_span_info_t *curr_span_tree[H5S_MAX_RANK]; /* Current span tree being built (in each dimension) */
+ H5S_hyper_span_t *prev_span[H5S_MAX_RANK]; /* Previous span in tree (in each dimension) */
+ hsize_t curr_span_up_dim[H5S_MAX_RANK]; /* "Up" dimensions for current span */
+ unsigned proj_rank; /* Rank of proj_space */
+ hsize_t low; /* Low value of span */
+ hsize_t high; /* High value of span */
+ size_t span_len; /* Length of span */
+ size_t nelem; /* Number of elements returned for get_seq_list op */
+ unsigned i; /* Local index variable */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_PACKAGE
+
+ /* Check parameters */
+ HDassert(src_space);
+ HDassert(dst_space);
+ HDassert(src_intersect_space);
+ HDassert(proj_space);
+
+ /* Assert that src_space and src_intersect_space have same extent and there
+ * are no point selections */
+ HDassert(H5S_GET_EXTENT_NDIMS(src_space)
+ == H5S_GET_EXTENT_NDIMS(src_intersect_space));
+ HDassert(!HDmemcmp(src_space->extent.size, src_intersect_space->extent.size,
+ (size_t)H5S_GET_EXTENT_NDIMS(src_space)
+ * sizeof(src_space->extent.size[0])));
+ HDassert(H5S_GET_SELECT_TYPE(src_space) != H5S_SEL_POINTS);
+ HDassert(H5S_GET_SELECT_TYPE(dst_space) != H5S_SEL_POINTS);
+ HDassert(H5S_GET_SELECT_TYPE(src_intersect_space) != H5S_SEL_POINTS);
+
+ /* Initialize prev_space, curr_span_tree, and curr_span_up_dim */
+ for(i = 0; i < H5S_MAX_RANK; i++) {
+ curr_span_tree[i] = NULL;
+ prev_span[i] = NULL;
+ curr_span_up_dim[i] = (hsize_t)0;
+ } /* end for */
+
+ /* Save rank of projected space */
+ proj_rank = proj_space->extent.rank;
+ HDassert(proj_rank > 0);
+
+ /* Get numbers of elements */
+ ss_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_space);
+ ds_nelem = (size_t)H5S_GET_SELECT_NPOINTS(dst_space);
+ sis_nelem = (size_t)H5S_GET_SELECT_NPOINTS(src_intersect_space);
+ HDassert(ss_nelem == ds_nelem);
+
+ /* Calculate proj_down_dims (note loop relies on unsigned i wrapping around)
+ */
+ if(H5VM_array_down(proj_rank, proj_space->extent.size, proj_down_dims) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't compute 'down' chunk size value")
+
+ /* Remove current selection from proj_space */
+ if(H5S_SELECT_RELEASE(proj_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
+
+ /* If any selections are empty, skip to the end so "none" is selected */
+ if((ss_nelem == 0) || (ds_nelem == 0) || (sis_nelem == 0))
+ goto loop_end;
+
+ /* Allocate space for the hyperslab selection information (note this sets
+ * diminfo_valid to FALSE, diminfo arrays to 0, and span list to NULL) */
+ if((proj_space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab info")
+
+ /* Set selection type */
+ proj_space->select.type = H5S_sel_hyper;
+
+ /* Set unlim_dim */
+ proj_space->select.sel_info.hslab->unlim_dim = -1;
+
+ /* Initialize source space iterator */
+ if(H5S_select_iter_init(&ss_iter, src_space, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ ss_iter_init = TRUE;
+
+ /* Get sequence list for source space */
+ if(H5S_SELECT_GET_SEQ_LIST(src_space, 0u, &ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+ ss_nelem -= nelem;
+ HDassert(ss_nseq > 0);
+
+ /* Initialize destination space iterator */
+ if(H5S_select_iter_init(&ds_iter, dst_space, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ ds_iter_init = TRUE;
+
+ /* Get sequence list for destination space */
+ if(H5S_SELECT_GET_SEQ_LIST(dst_space, 0u, &ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ ds_nelem -= nelem;
+ HDassert(ds_nseq > 0);
+
+ /* Initialize source intersect space iterator */
+ if(H5S_select_iter_init(&sis_iter, src_intersect_space, (size_t)1) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize selection iterator")
+ sis_iter_init = TRUE;
+
+ /* Get sequence list for source intersect space */
+ if(H5S_SELECT_GET_SEQ_LIST(src_intersect_space, 0u, &sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+ sis_nelem -= nelem;
+ HDassert(sis_nseq > 0);
+
+ /* Loop until we run out of sequences in either the source or source
+ * intersect space */
+ while(1) {
+ while(advance_ss || (ss_off[ss_i] + ss_len[ss_i] <= sis_off[sis_i])) {
+ /* Either we finished the current source sequence or the
+ * sequences do not intersect. Advance source space. */
+ ss_sel_off += (hsize_t)ss_len[ss_i];
+ if(++ss_i == ss_nseq) {
+ if(ss_nelem > 0) {
+ /* Try to grab more sequences from src_space */
+ if(H5S_SELECT_GET_SEQ_LIST(src_space, 0u, &ss_iter, H5S_PROJECT_INTERSECT_NSEQS, ss_nelem, &ss_nseq, &nelem, ss_off, ss_len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+ HDassert(ss_len[0] > 0);
+
+ /* Update ss_nelem */
+ HDassert(nelem > 0);
+ HDassert(nelem <= ss_nelem);
+ ss_nelem -= nelem;
+
+ /* Reset source space index */
+ ss_i = 0;
+ } /* end if */
+ else
+ /* There are no more sequences in src_space, so we can exit
+ * the loop. Use goto instead of break so we exit the outer
+ * loop. */
+ goto loop_end;
+ } /* end if */
+
+ /* Reset advance_ss */
+ advance_ss = FALSE;
+ } /* end if */
+ if(advance_sis
+ || (sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i])) {
+ do {
+ /* Either we finished the current source intersect sequence or
+ * the sequences do not intersect. Advance source intersect
+ * space. */
+ if(++sis_i == sis_nseq) {
+ if(sis_nelem > 0) {
+ /* Try to grab more sequences from src_intersect_space
+ */
+ if(H5S_SELECT_GET_SEQ_LIST(src_intersect_space, 0u, &sis_iter, H5S_PROJECT_INTERSECT_NSEQS, sis_nelem, &sis_nseq, &nelem, sis_off, sis_len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+ HDassert(sis_len[0] > 0);
+
+ /* Update ss_nelem */
+ HDassert(nelem > 0);
+ HDassert(nelem <= sis_nelem);
+ sis_nelem -= nelem;
+
+ /* Reset source space index */
+ sis_i = 0;
+ } /* end if */
+ else
+ /* There are no more sequences in src_intersect_space,
+ * so we can exit the loop. Use goto instead of break
+ * so we exit the outer loop. */
+ goto loop_end;
+ } /* end if */
+ } while(sis_off[sis_i] + sis_len[sis_i] <= ss_off[ss_i]);
+
+ /* Reset advance_sis */
+ advance_sis = FALSE;
+ } /* end if */
+ else {
+ /* Sequences intersect, add intersection to projected space */
+ /* Calculate intersection sequence in terms of offset within source
+ * selection and advance any sequences we complete */
+ if(ss_off[ss_i] >= sis_off[sis_i])
+ int_sel_off = ss_sel_off;
+ else
+ int_sel_off = sis_off[sis_i] - ss_off[ss_i] + ss_sel_off;
+ if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) <= (sis_off[sis_i]
+ + (hsize_t)sis_len[sis_i])) {
+ int_len = (size_t)((hsize_t)ss_len[ss_i] + ss_sel_off - int_sel_off);
+ advance_ss = TRUE;
+ } /* end if */
+ else
+ int_len = (size_t)(sis_off[sis_i] + (hsize_t)sis_len[sis_i] - ss_off[ss_i] + ss_sel_off - int_sel_off);
+ if((ss_off[ss_i] + (hsize_t)ss_len[ss_i]) >= (sis_off[sis_i]
+ + (hsize_t)sis_len[sis_i]))
+ advance_sis = TRUE;
+
+ /* Project intersection sequence to destination selection */
+ while(int_len > (size_t)0) {
+ while(ds_sel_off + (hsize_t)ds_len[ds_i] <= int_sel_off) {
+ /* Intersection is not projected to this destination
+ * sequence, advance destination space */
+ ds_sel_off += (hsize_t)ds_len[ds_i];
+ if(++ds_i == ds_nseq) {
+ HDassert(ds_nelem > 0);
+
+ /* Try to grab more sequences from dst_space */
+ if(H5S_SELECT_GET_SEQ_LIST(dst_space, 0u, &ds_iter, H5S_PROJECT_INTERSECT_NSEQS, ds_nelem, &ds_nseq, &nelem, ds_off, ds_len) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL, "sequence length generation failed")
+ HDassert(ds_len[0] > 0);
+
+ /* Update ss_nelem */
+ HDassert(nelem > 0);
+ HDassert(nelem <= ds_nelem);
+ ds_nelem -= nelem;
+
+ /* Reset source space index */
+ ds_i = 0;
+ } /* end if */
+ } /* end while */
+
+ /* Add sequence to projected space */
+ HDassert(ds_sel_off <= int_sel_off);
+ proj_off = ds_off[ds_i] + int_sel_off - ds_sel_off;
+ proj_len = proj_len_rem = (size_t)MIN(int_len,
+ (size_t)(ds_sel_off + (hsize_t)ds_len[ds_i]
+ - int_sel_off));
+
+ /* Add to span tree */
+ while(proj_len_rem > (size_t)0) {
+ /* Check for more than one full row (in every dim) and
+ * append multiple spans at once? -NAF */
+ /* Append spans in higher dimensions if we're going ouside
+ * the plane of the span currently being built (i.e. it's
+ * finished being built) */
+ for(i = proj_rank - 1; ((i > 0)
+ && ((proj_off / proj_down_dims[i - 1])
+ != curr_span_up_dim[i - 1])); i--) {
+ if(curr_span_tree[i]) {
+ HDassert(prev_span[i]);
+
+ /* Append complete lower dimension span tree to
+ * current dimension */
+ low = curr_span_up_dim[i - 1] % proj_space->extent.size[i - 1];
+ if(H5S_hyper_append_span(&prev_span[i - 1], &curr_span_tree[i - 1], low, low, curr_span_tree[i], NULL) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+
+ /* Reset lower dimension's span tree and previous
+ * span since we just committed it and will start
+ * over with a new one */
+ if(H5S_hyper_free_span_info(curr_span_tree[i]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't free span info")
+ curr_span_tree[i] = NULL;
+ prev_span[i] = NULL;
+ } /* end if */
+
+ /* Update curr_span_up_dim */
+ curr_span_up_dim[i - 1] = proj_off / proj_down_dims[i - 1];
+ } /* end for */
+
+ /* Compute bounds for new span in lowest dimension */
+ low = proj_off % proj_space->extent.size[proj_rank - 1];
+ span_len = MIN(proj_len_rem,
+ (size_t)(proj_space->extent.size[proj_rank - 1]
+ - low));
+ HDassert(proj_len_rem >= span_len);
+ high = low + (hsize_t)span_len - (hsize_t)1;
+
+ /* Append span in lowest dimension */
+ if(H5S_hyper_append_span(&prev_span[proj_rank - 1], &curr_span_tree[proj_rank - 1], low, high, NULL, NULL) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+
+ /* Update remaining offset and length */
+ proj_off += (hsize_t)span_len;
+ proj_len_rem -= span_len;
+ } /* end while */
+
+ /* Update intersection sequence */
+ int_sel_off += (hsize_t)proj_len;
+ int_len -= proj_len;
+ } /* end while */
+ } /* end else */
+ } /* end while */
+
+loop_end:
+ /* Add remaining spans to span tree */
+ for(i = proj_rank - 1; i > 0; i--)
+ if(curr_span_tree[i]) {
+ HDassert(prev_span[i]);
+
+ /* Append remaining span tree to higher dimension */
+ low = curr_span_up_dim[i - 1] % proj_space->extent.size[i - 1];
+ if(H5S_hyper_append_span(&prev_span[i - 1], &curr_span_tree[i - 1], low, low, curr_span_tree[i], NULL) < 0)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTAPPEND, FAIL, "can't allocate hyperslab span")
+
+ /* Reset span tree */
+ if(H5S_hyper_free_span_info(curr_span_tree[i]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't free span info")
+ curr_span_tree[i] = NULL;
+ } /* end if */
+
+ /* Add span tree to proj_space */
+ if(curr_span_tree[0]) {
+ proj_space->select.sel_info.hslab->span_lst = curr_span_tree[0];
+ curr_span_tree[0] = NULL;
+
+ /* Set the number of elements in current selection */
+ proj_space->select.num_elem = H5S_hyper_spans_nelem(proj_space->select.sel_info.hslab->span_lst);
+
+ /* Attempt to rebuild "optimized" start/stride/count/block information.
+ * from resulting hyperslab span tree */
+ if(H5S_hyper_rebuild(proj_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info")
+ } /* end if */
+ else
+ /* If we did not add anything to proj_space, select none instead */
+ if(H5S_select_none(proj_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
+
+done:
+ /* Release source selection iterator */
+ if(ss_iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&ss_iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
+
+ /* Release destination selection iterator */
+ if(ds_iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&ds_iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
+
+ /* Release source intersect selection iterator */
+ if(sis_iter_init)
+ if(H5S_SELECT_ITER_RELEASE(&sis_iter) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release selection iterator")
+
+ /* Cleanup on error */
+ if(ret_value < 0) {
+ /* Remove current selection from proj_space */
+ if(H5S_SELECT_RELEASE(proj_space) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
+
+ /* Free span trees */
+ for(i = 0; i < proj_rank; i++)
+ if(curr_span_tree[i]) {
+ if(H5S_hyper_free_span_info(curr_span_tree[i]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "can't free span info")
+ curr_span_tree[i] = NULL;
+ } /* end if */
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_project_intersection() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_subtract
+ PURPOSE
+ Subtract one hyperslab selection from another
+ USAGE
+ herr_t H5S__hyper_subtract(space,subtract_space)
+ H5S_t *space; IN/OUT: Selection to be operated on
+ H5S_t *subtract_space; IN: Selection that will be subtracted from space
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Removes any and all portions of space that are also present in
+ subtract_space. In essence, performs an A_NOT_B operation with the
+ two selections.
+
+ Note this function basically duplicates a subset of the functionality
+ of H5S_select_select(). It should probably be removed when that
+ function is enabled.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S__hyper_subtract(H5S_t *space, H5S_t *subtract_space)
+{
+ H5S_hyper_span_info_t *a_not_b = NULL; /* Span tree for hyperslab spans in old span tree and not in new span tree */
+ H5S_hyper_span_info_t *a_and_b = NULL; /* Span tree for hyperslab spans in both old and new span trees */
+ H5S_hyper_span_info_t *b_not_a = NULL; /* Span tree for hyperslab spans in new span tree and not in old span tree */
+ herr_t ret_value = SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ /* Check args */
+ HDassert(space);
+ HDassert(subtract_space);
+
+ /* Check that the space selections both have span trees */
+ if(space->select.sel_info.hslab->span_lst == NULL)
+ if(H5S_hyper_generate_spans(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
+ if(subtract_space->select.sel_info.hslab->span_lst == NULL)
+ if(H5S_hyper_generate_spans(subtract_space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
+
+ /* Generate lists of spans which overlap and don't overlap */
+ if(H5S_hyper_clip_spans(space->select.sel_info.hslab->span_lst, subtract_space->select.sel_info.hslab->span_lst, &a_not_b, &a_and_b, &b_not_a)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information")
+
+ /* Reset the other dataspace selection information */
+ if(H5S_SELECT_RELEASE(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection")
+
+ /* Allocate space for the hyperslab selection information */
+ if((space->select.sel_info.hslab = H5FL_CALLOC(H5S_hyper_sel_t)) == NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
+
+ /* Set unlim_dim */
+ space->select.sel_info.hslab->unlim_dim = -1;
+
+ /* Check for anything returned in a_not_b */
+ if(a_not_b) {
+ /* Update spans in space */
+ space->select.sel_info.hslab->span_lst = a_not_b;
+ a_not_b = NULL;
+
+ /* Update number of elements */
+ space->select.num_elem = H5S_hyper_spans_nelem(space->select.sel_info.hslab->span_lst);
+
+ /* Attempt to rebuild "optimized" start/stride/count/block information.
+ * from resulting hyperslab span tree */
+ if(H5S_hyper_rebuild(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info")
+ } /* end if */
+ else {
+ H5S_hyper_span_info_t *spans; /* Empty hyperslab span tree */
+
+ /* Set number of elements */
+ space->select.num_elem = 0;
+
+ /* Allocate a span info node */
+ if(NULL == (spans = H5FL_MALLOC(H5S_hyper_span_info_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, FAIL, "can't allocate hyperslab span")
+
+ /* Set the reference count */
+ spans->count = 1;
+
+ /* Reset the scratch pad space */
+ spans->scratch = 0;
+
+ /* Set to empty tree */
+ spans->head = NULL;
+
+ /* Set pointer to empty span tree */
+ space->select.sel_info.hslab->span_lst = spans;
+ } /* end if */
+
+done:
+ /* Free span trees */
+ if(a_and_b)
+ H5S_hyper_free_span_info(a_and_b);
+ if(b_not_a)
+ H5S_hyper_free_span_info(b_not_a);
+ if(a_not_b) {
+ HDassert(ret_value < 0);
+ H5S_hyper_free_span_info(b_not_a);
+ } /* end if */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_subtract() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_get_clip_diminfo
+ PURPOSE
+ Calculates the count and block required to clip the specified
+ unlimited dimension to include clip_size. The returned selection may
+ extent beyond clip_size.
+ USAGE
+ void H5S__hyper_get_clip_diminfo(start,stride,count,block,clip_size)
+ hsize_t start; IN: Start of hyperslab in unlimited dimension
+ hsize_t stride; IN: Stride of hyperslab in unlimited dimension
+ hsize_t *count; IN/OUT: Count of hyperslab in unlimited dimension
+ hsize_t *block; IN/OUT: Block of hyperslab in unlimited dimension
+ hsize_t clip_size; IN: Extent that hyperslab will be clipped to
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ This function recalculates the internal description of the hyperslab
+ to make the unlimited dimension extend to the specified extent.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+void
+H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count,
+ hsize_t *block, hsize_t clip_size)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Check for selection outside clip size */
+ if(start >= clip_size) {
+ if(*block == H5S_UNLIMITED)
+ *block = 0;
+ else
+ *count = 0;
+ } /* end if */
+ /* Check for single block in unlimited dimension */
+ else if((*block == H5S_UNLIMITED) || (*block == stride)) {
+ /* Calculate actual block size for this clip size */
+ *block = clip_size - start;
+ *count = (hsize_t)1;
+ } /* end if */
+ else {
+ HDassert(*count == H5S_UNLIMITED);
+
+ /* Calculate initial count (last block may be partial) */
+ *count = (clip_size - start + stride - (hsize_t)1) / stride;
+ HDassert(*count > (hsize_t)0);
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI_VOID
+} /* end H5S_hyper_get_clip_diminfo() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_clip_unlim
+ PURPOSE
+ Clips the unlimited dimension of the hyperslab selection to the
+ specified size
+ USAGE
+ void H5S_hyper_clip_unlim(space,clip_size)
+ H5S_t *space, IN/OUT: Unlimited space to clip
+ hsize_t clip_size; IN: Extent that hyperslab will be clipped to
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ This function changes the unlimited selection into a limited selection
+ with the extent of the formerly unlimited dimension specified by
+ * clip_size.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this function does not take the offset into account.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_hyper_clip_unlim(H5S_t *space, hsize_t clip_size)
+{
+ H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
+ hsize_t orig_count; /* Original count in unlimited dimension */
+ int orig_unlim_dim; /* Original unliminted dimension */
+ H5S_hyper_dim_t *diminfo; /* Convenience pointer to opt_diminfo in unlimited dimension */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check parameters */
+ HDassert(space);
+ hslab = space->select.sel_info.hslab;
+ HDassert(hslab);
+ HDassert(hslab->unlim_dim >= 0);
+ HDassert(!hslab->span_lst);
+
+ /* Save original unlimited dimension */
+ orig_unlim_dim = hslab->unlim_dim;
+
+ diminfo = &hslab->opt_diminfo[orig_unlim_dim];
+
+ /* Save original count in unlimited dimension */
+ orig_count = diminfo->count;
+
+ /* Get initial diminfo */
+ H5S__hyper_get_clip_diminfo(diminfo->start, diminfo->stride, &diminfo->count, &diminfo->block, clip_size);
+
+ /* Selection is no longer unlimited */
+ space->select.sel_info.hslab->unlim_dim = -1;
+
+ /* Check for nothing returned */
+ if((diminfo->block == 0) || (diminfo->count == 0)) {
+ /* Convert to "none" selection */
+ if(H5S_select_none(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection")
+ } /* end if */
+ /* Check for single block in unlimited dimension */
+ else if(orig_count == (hsize_t)1) {
+ /* Calculate number of elements */
+ space->select.num_elem = diminfo->block * hslab->num_elem_non_unlim;
+
+ /* Mark that opt_diminfo is valid */
+ hslab->diminfo_valid = TRUE;
+ } /* end if */
+ else {
+ /* Calculate number of elements */
+ space->select.num_elem = diminfo->count * diminfo->block
+ * hslab->num_elem_non_unlim;
+
+ /* Check if last block is partial. If superset is set, just keep the
+ * last block complete to speed computation. */
+ HDassert(clip_size > diminfo->start);
+ if(((diminfo->stride * (diminfo->count - (hsize_t)1)) + diminfo->block)
+ > (clip_size - diminfo->start)) {
+ hsize_t start[H5S_MAX_RANK];
+ hsize_t block[H5S_MAX_RANK];
+ unsigned i;
+
+ /* Last block is partial, need to construct compound selection */
+ /* Fill start with zeros */
+ HDmemset(start, 0, sizeof(start));
+
+ /* Set block to clip_size in unlimited dimension, H5S_MAX_SIZE in
+ * others so only unlimited dimension is clipped */
+ for(i = 0; i < space->extent.rank; i++)
+ if((int)i == orig_unlim_dim)
+ block[i] = clip_size;
+ else
+ block[i] = H5S_MAX_SIZE;
+
+ /* Generate span tree in selection */
+ if(!hslab->span_lst)
+ if(H5S_hyper_generate_spans(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to generate span tree")
+
+ /* Indicate that the regular dimensions are no longer valid */
+ hslab->diminfo_valid = FALSE;
+
+ /* "And" selection with calculated block to perform clip operation
+ */
+ if(H5S_generate_hyperslab(space, H5S_SELECT_AND, start, _ones, _ones, block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
+ } /* end if */
+ else
+ /* Last block is complete, simply mark that opt_diminfo is valid */
+ hslab->diminfo_valid = TRUE;
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_clip_unlim() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S__hyper_get_clip_extent_real
+ PURPOSE
+ Gets the extent a space should be clipped to in order to contain the
+ specified number of slices in the unlimited dimension
+ USAGE
+ hsize_t H5S__hyper_get_clip_extent_real(clip_space,num_slices,incl_trail)
+ const H5S_t *clip_space, IN: Space that clip size will be calculated based on
+ hsize_t num_slizes, IN: Number of slices clip_space should contain when clipped
+ hbool_t incl_trail; IN: Whether to include trailing unselected space
+ RETURNS
+ Clip extent to match num_slices (never fails)
+ DESCRIPTION
+ Calculates and returns the extent that clip_space should be clipped to
+ (via H5S_hyper_clip_unlim) in order for it to contain num_slices
+ slices in the unlimited dimension. If the clipped selection would end
+ immediately before a section of unselected space (i.e. at the end of a
+ block), then if incl_trail is TRUE, the returned clip extent is
+ selected to include that trailing "blank" space, otherwise it is
+ selected to end at the end before the blank space.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this assumes the offset has been normalized.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static hsize_t
+H5S__hyper_get_clip_extent_real(const H5S_t *clip_space, hsize_t num_slices,
+ hbool_t incl_trail)
+{
+ const H5S_hyper_dim_t *diminfo; /* Convenience pointer to opt_unlim_diminfo in unlimited dimension */
+ hsize_t count;
+ hsize_t rem_slices;
+ hsize_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_STATIC_NOERR
+
+ /* Check parameters */
+ HDassert(clip_space);
+ HDassert(clip_space->select.sel_info.hslab);
+ HDassert(clip_space->select.sel_info.hslab->unlim_dim >= 0);
+
+ diminfo = &clip_space->select.sel_info.hslab->opt_diminfo[clip_space->select.sel_info.hslab->unlim_dim];
+
+ if(num_slices == 0)
+ ret_value = incl_trail ? diminfo->start : 0;
+ else if((diminfo->block == H5S_UNLIMITED)
+ || (diminfo->block == diminfo->stride))
+ /* Unlimited block, just set the extent large enough for the block size
+ * to match num_slices */
+ ret_value = diminfo->start + num_slices;
+ else {
+ /* Unlimited count, need to match extent so a block (possibly) gets cut
+ * off so the number of slices matches num_slices */
+ HDassert(diminfo->count == H5S_UNLIMITED);
+
+ /* Calculate number of complete blocks in clip_space */
+ count = num_slices / diminfo->block;
+
+ /* Calculate slices remaining */
+ rem_slices = num_slices - (count * diminfo->block);
+
+ if(rem_slices > 0)
+ /* Must end extent in middle of partial block (or beginning of empty
+ * block if include_trailing_space and rem_slices == 0) */
+ ret_value = diminfo->start + (count * diminfo->stride) + rem_slices;
+ else {
+ if(incl_trail)
+ /* End extent just before first missing block */
+ ret_value = diminfo->start + (count * diminfo->stride);
+ else
+ /* End extent at end of last block */
+ ret_value = diminfo->start + ((count - (hsize_t)1)
+ * diminfo->stride) + diminfo->block;
+ } /* end else */
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S__hyper_get_clip_extent_real() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_get_clip_extent
+ PURPOSE
+ Gets the extent a space should be clipped to in order to contain the
+ same number of elements as another space
+ USAGE
+ hsize_t H5S__hyper_get_clip_extent(clip_space,match_space,incl_trail)
+ const H5S_t *clip_space, IN: Space that clip size will be calculated based on
+ const H5S_t *match_space, IN: Space containing the same number of elements as clip_space should after clipping
+ hbool_t incl_trail; IN: Whether to include trailing unselected space
+ RETURNS
+ Calculated clip extent (never fails)
+ DESCRIPTION
+ Calculates and returns the extent that clip_space should be clipped to
+ (via H5S_hyper_clip_unlim) in order for it to contain the same number
+ of elements as match_space. If the clipped selection would end
+ immediately before a section of unselected space (i.e. at the end of a
+ block), then if incl_trail is TRUE, the returned clip extent is
+ selected to include that trailing "blank" space, otherwise it is
+ selected to end at the end before the blank space.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this assumes the offset has been normalized.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hsize_t
+H5S_hyper_get_clip_extent(const H5S_t *clip_space, const H5S_t *match_space,
+ hbool_t incl_trail)
+{
+ hsize_t num_slices; /* Number of slices in unlimited dimension */
+ hsize_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI(0)
+
+ /* Check parameters */
+ HDassert(clip_space);
+ HDassert(match_space);
+ HDassert(clip_space->select.sel_info.hslab->unlim_dim >= 0);
+
+ /* Check for "none" match space */
+ if(match_space->select.type->type == H5S_SEL_NONE)
+ num_slices = (hsize_t)0;
+ else {
+ HDassert(match_space->select.type->type == H5S_SEL_HYPERSLABS);
+ HDassert(match_space->select.sel_info.hslab);
+
+ /* Calculate number of slices */
+ num_slices = match_space->select.num_elem
+ / clip_space->select.sel_info.hslab->num_elem_non_unlim;
+ HDassert((match_space->select.num_elem
+ % clip_space->select.sel_info.hslab->num_elem_non_unlim) == 0);
+ } /* end else */
+
+ /* Call "real" get_clip_extent function */
+ ret_value = H5S__hyper_get_clip_extent_real(clip_space, num_slices, incl_trail);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_get_clip_extent() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_get_clip_extent_match
+ PURPOSE
+ Gets the extent a space should be clipped to in order to contain the
+ same number of elements as another unlimited space that has been
+ clipped to a different extent
+ USAGE
+ hsize_t H5S__hyper_get_clip_extent_match(clip_space,match_space,match_clip_size,incl_trail)
+ const H5S_t *clip_space, IN: Space that clip size will be calculated based on
+ const H5S_t *match_space, IN: Space that, after being clipped to match_clip_size, contains the same number of elements as clip_space should after clipping
+ hsize_t match_clip_size, IN: Extent match_space would be clipped to to match the number of elements in clip_space
+ hbool_t incl_trail; IN: Whether to include trailing unselected space
+ RETURNS
+ Calculated clip extent (never fails)
+ DESCRIPTION
+ Calculates and returns the extent that clip_space should be clipped to
+ (via H5S_hyper_clip_unlim) in order for it to contain the same number
+ of elements as match_space would have after being clipped to
+ match_clip_size. If the clipped selection would end immediately
+ before a section of unselected space (i.e. at the end of a block),
+ then if incl_trail is TRUE, the returned clip extent is selected to
+ include that trailing "blank" space, otherwise it is selected to end
+ at the end before the blank space.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this assumes the offset has been normalized.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hsize_t
+H5S_hyper_get_clip_extent_match(const H5S_t *clip_space,
+ const H5S_t *match_space, hsize_t match_clip_size, hbool_t incl_trail)
+{
+ const H5S_hyper_dim_t *match_diminfo; /* Convenience pointer to opt_unlim_diminfo in unlimited dimension in match_space */
+ hsize_t count; /* Temporary count */
+ hsize_t block; /* Temporary block */
+ hsize_t num_slices; /* Number of slices in unlimited dimension */
+ hsize_t ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI(0)
+
+ /* Check parameters */
+ HDassert(clip_space);
+ HDassert(match_space);
+ HDassert(clip_space->select.sel_info.hslab);
+ HDassert(match_space->select.sel_info.hslab);
+ HDassert(clip_space->select.sel_info.hslab->unlim_dim >= 0);
+ HDassert(match_space->select.sel_info.hslab->unlim_dim >= 0);
+ HDassert(clip_space->select.sel_info.hslab->num_elem_non_unlim
+ == match_space->select.sel_info.hslab->num_elem_non_unlim);
+
+ match_diminfo = &match_space->select.sel_info.hslab->opt_diminfo[match_space->select.sel_info.hslab->unlim_dim];
+
+ /* Get initial count and block */
+ count = match_diminfo->count;
+ block = match_diminfo->block;
+ H5S__hyper_get_clip_diminfo(match_diminfo->start, match_diminfo->stride, &count, &block, match_clip_size);
+
+ /* Calculate number of slices */
+ /* Check for nothing returned */
+ if((block == 0) || (count == 0))
+ num_slices = (hsize_t)0;
+ /* Check for single block in unlimited dimension */
+ else if(count == (hsize_t)1)
+ num_slices = block;
+ else {
+ /* Calculate initial num_slices */
+ num_slices = block * count;
+
+ /* Check for partial last block */
+ HDassert(match_clip_size >= match_diminfo->start);
+ if(((match_diminfo->stride * (count - (hsize_t)1)) + block)
+ > (match_clip_size - match_diminfo->start)) {
+ /* Subtract slices missing from last block */
+ HDassert((((match_diminfo->stride * (count - (hsize_t)1)) + block)
+ - (match_clip_size - match_diminfo->start)) < num_slices);
+ num_slices -= ((match_diminfo->stride * (count - (hsize_t)1))
+ + block) - (match_clip_size - match_diminfo->start);
+ } /* end if */
+ } /* end else */
+
+ /* Call "real" get_clip_extent function */
+ ret_value = H5S__hyper_get_clip_extent_real(clip_space, num_slices, incl_trail);
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_get_clip_extent_match() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_get_unlim_block
+ PURPOSE
+ Get the nth block in the unlimited dimension
+ USAGE
+ H5S_t *H5S_hyper_get_unlim_block(space,block_index)
+ const H5S_t *space, IN: Space with unlimited selection
+ hsize_t block_index, IN: Index of block to return in unlimited dimension
+ hbool_t incl_trail; IN: Whether to include trailing unselected space
+ RETURNS
+ New space on success/NULL on failure.
+ DESCRIPTION
+ Returns a space containing only the block_indexth block in the
+ unlimited dimension on space. All blocks in all other dimensions are
+ preserved.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this assumes the offset has been normalized.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+H5S_t *
+H5S_hyper_get_unlim_block(const H5S_t *space, hsize_t block_index)
+{
+ H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
+ H5S_t *space_out = NULL;
+ hsize_t start[H5S_MAX_RANK];
+ hsize_t stride[H5S_MAX_RANK];
+ hsize_t count[H5S_MAX_RANK];
+ hsize_t block[H5S_MAX_RANK];
+ unsigned i;
+ H5S_t *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ /* Check parameters */
+ HDassert(space);
+ hslab = space->select.sel_info.hslab;
+ HDassert(hslab);
+ HDassert(hslab->unlim_dim >= 0);
+ HDassert(hslab->opt_diminfo[hslab->unlim_dim].count == H5S_UNLIMITED);
+
+ /* Set start to select block_indexth block in unlimited dimension and set
+ * count to 1 in that dimension to only select that block. Copy all other
+ * diminfo parameters. */
+ for(i = 0; i < space->extent.rank; i++) {
+ if((int)i == hslab->unlim_dim){
+ start[i] = hslab->opt_diminfo[i].start + (block_index
+ * hslab->opt_diminfo[i].stride);
+ count[i] = (hsize_t)1;
+ } /* end if */
+ else {
+ start[i] = hslab->opt_diminfo[i].start;
+ count[i] = hslab->opt_diminfo[i].count;
+ } /* end else */
+ stride[i] = hslab->opt_diminfo[i].stride;
+ block[i] = hslab->opt_diminfo[i].block;
+ } /* end for */
+
+ /* Create output space, copy extent */
+ if(NULL == (space_out = H5S_create(H5S_SIMPLE)))
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "unable to create output dataspace")
+ if(H5S_extent_copy_real(&space_out->extent, &space->extent, TRUE) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "unable to copy destination space extent")
+
+ /* Select block as defined by start/stride/count/block computed above */
+ if(H5S_select_hyperslab(space_out, H5S_SELECT_SET, start, stride, count, block) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't select hyperslab")
+
+ /* Set return value */
+ ret_value = space_out;
+
+done:
+ /* Free space on error */
+ if(!ret_value)
+ if(space_out && H5S_close(space_out) < 0)
+ HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release dataspace")
+
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_get_unlim_block */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_get_first_inc_block
+ PURPOSE
+ Get the index of the first incomplete block in the specified extent
+ USAGE
+ hsize_t H5S_hyper_get_first_inc_block(space,clip_size,partial)
+ const H5S_t *space, IN: Space with unlimited selection
+ hsize_t clip_size, IN: Extent space would be clipped to
+ hbool_t *partial; OUT: Whether the ret_valueth block (first incomplete block) is partial
+ RETURNS
+ Index of first incomplete block in clip_size (never fails).
+ DESCRIPTION
+ Calculates and returns the index (as would be passed to
+ H5S_hyper_get_unlim_block()) of the first block in the unlimited
+ dimension of space which would be incomplete or missing when space is
+ clipped to clip_size. partial is set to TRUE if the first incomplete
+ block is partial, and FALSE if the first incomplete block is missing.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this assumes the offset has been normalized.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+hsize_t
+H5S_hyper_get_first_inc_block(const H5S_t *space, hsize_t clip_size,
+ hbool_t *partial)
+{
+ H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
+ H5S_hyper_dim_t *diminfo; /* Convenience pointer to opt_diminfo in unlimited dimension */
+ hsize_t ret_value = 0;
+
+ FUNC_ENTER_NOAPI(0)
+
+ /* Check parameters */
+ HDassert(space);
+ hslab = space->select.sel_info.hslab;
+ HDassert(hslab);
+ HDassert(hslab->unlim_dim >= 0);
+ HDassert(hslab->opt_diminfo[hslab->unlim_dim].count == H5S_UNLIMITED);
+
+ diminfo = &hslab->opt_diminfo[hslab->unlim_dim];
+
+ /* Check for selection outside of clip_size */
+ if(diminfo->start >= clip_size) {
+ ret_value = 0;
+ if(partial)
+ partial = FALSE;
+ } /* end if */
+ else {
+ /* Calculate index of first incomplete block */
+ ret_value = (clip_size - diminfo->start + diminfo->stride
+ - diminfo->block) / diminfo->stride;
+
+ if(partial) {
+ /* Check for partial block */
+ if((diminfo->stride * ret_value) < (clip_size - diminfo->start))
+ *partial = TRUE;
+ else
+ *partial = FALSE;
+ } /* end if */
+ } /* end else */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_get_first_inc_block */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5Sis_regular_hyperslab
PURPOSE
Determine if a hyperslab selection is regular