summaryrefslogtreecommitdiffstats
path: root/src/H5Shyper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r--src/H5Shyper.c1459
1 files changed, 1376 insertions, 83 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index 51b5ab6..6cc78a9 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -45,6 +45,8 @@ 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, hssize_t offset, hsize_t clip_size);
/* Selection callbacks */
static herr_t H5S_hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection);
@@ -53,11 +55,14 @@ static herr_t H5S_hyper_get_seq_list(const H5S_t *space, unsigned flags,
size_t *nseq, size_t *nbytes, hsize_t *off, size_t *len);
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 hssize_t H5S_hyper_serial_size(const H5F_t *f, const H5S_t *space);
+static herr_t H5S_hyper_serialize(const H5F_t *f, const H5S_t *space,
+ uint8_t **p);
+static herr_t H5S_hyper_deserialize(const H5F_t *f, 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 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 +99,7 @@ const H5S_select_class_t H5S_sel_hyper[1] = {{
H5S_hyper_deserialize,
H5S_hyper_bounds,
H5S_hyper_offset,
+ H5S_hyper_unlim_dim,
H5S_hyper_is_contiguous,
H5S_hyper_is_single,
H5S_hyper_is_regular,
@@ -1644,6 +1650,17 @@ 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;
+ if(src_hslab->unlim_dim >= 0) {
+ size_t u; /* Local index variable */
+
+ for(u = 0; u < src->extent.rank; u++) {
+ dst_hslab->opt_unlim_diminfo[u] = src_hslab->opt_unlim_diminfo[u];
+ dst_hslab->app_diminfo[u] = src_hslab->app_diminfo[u];
+ } /* end for */
+ } /* end for */
+ dst_hslab->unlim_dim_clip_size = src_hslab->unlim_dim_clip_size;
+ 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 */
@@ -1658,6 +1675,13 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection)
dst->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(src->select.sel_info.hslab->span_lst);
} /* end if */
+ /* If there is an unlimited dimension, we must update the selection */
+ /* Disabled to make chunk I/O work. This is a quick hack - no sense in a
+ * proper fix since we are planning to change how unlimited selections work
+ * anyways. VDSINC */
+ /*if(H5S_hyper_clip_to_extent(dst) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "can't update hyperslab")*/
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5S_hyper_copy() */
@@ -1866,15 +1890,26 @@ H5S_get_select_hyper_nblocks(H5S_t *space)
/* Check for a "regular" hyperslab selection */
if(space->select.sel_info.hslab->diminfo_valid) {
+ const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
unsigned u; /* Local index variable */
+ /* Set diminfo based on whether this is an unlimited selection */
+ if(space->select.sel_info.hslab->unlim_dim >= 0)
+ diminfo = space->select.sel_info.hslab->opt_diminfo;
+ else
+ diminfo = space->select.sel_info.hslab->app_diminfo;
+
/* Check each dimension */
- for(ret_value = 1, u = 0; u < space->extent.rank; u++)
- ret_value *= space->select.sel_info.hslab->app_diminfo[u].count;
+ for(ret_value = 1, u = 0; u < space->extent.rank; u++) {
+ if(diminfo[u].block == (hsize_t)0)
+ HGOTO_DONE((hsize_t)0)
+ ret_value *= diminfo[u].count;
+ } /* end for */
} /* end if */
else
ret_value = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst);
+done:
FUNC_LEAVE_NOAPI(ret_value)
} /* H5S_get_select_hyper_nblocks() */
@@ -1925,8 +1960,9 @@ done:
Determine the number of bytes needed to store the serialized hyperslab
selection information.
USAGE
- hssize_t H5S_hyper_serial_size(space)
- H5S_t *space; IN: Dataspace pointer to query
+ hssize_t H5S_hyper_serial_size(f, space)
+ H5F_t *f IN: File pointer
+ H5S_t *space; IN: Dataspace pointer to query
RETURNS
The number of bytes required on success, negative on an error.
DESCRIPTION
@@ -1938,7 +1974,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static hssize_t
-H5S_hyper_serial_size(const H5S_t *space)
+H5S_hyper_serial_size(const H5F_t *f, const H5S_t *space)
{
unsigned u; /* Counter */
hsize_t block_count; /* block counter for regular hyperslabs */
@@ -1948,24 +1984,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 * <rank> * <start/stride/count/block (sizeof_size bytes)>) =
+ * 17 + (4 * sizeof_size) bytes
+ */
+ ret_value = (hssize_t)17 + ((hssize_t)4 * (hssize_t)space->extent.rank
+ * (hssize_t)H5F_SIZEOF_SIZE(f));
+ 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() */
@@ -1994,7 +2047,8 @@ H5S_hyper_serial_size(const H5S_t *space)
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_hyper_serialize_helper (const H5S_hyper_span_info_t *spans, hsize_t *start, hsize_t *end, hsize_t rank, uint8_t **p)
+H5S_hyper_serialize_helper (const H5S_hyper_span_info_t *spans,
+ hsize_t *start, hsize_t *end, hsize_t rank, uint8_t **p)
{
H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */
hsize_t u; /* Index variable */
@@ -2056,6 +2110,7 @@ done:
Serialize the current selection into a user-provided buffer.
USAGE
herr_t H5S_hyper_serialize(space, p)
+ H5F_t *f IN: File pointer
const H5S_t *space; IN: Dataspace with selection to serialize
uint8_t **p; OUT: Pointer to buffer to put serialized
selection. Will be advanced to end of
@@ -2071,7 +2126,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
+H5S_hyper_serialize(const H5F_t *f, const H5S_t *space, uint8_t **p)
{
const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */
hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */
@@ -2081,6 +2136,8 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
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 */
@@ -2090,10 +2147,21 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
HDassert(space);
+ /* 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(*p, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
- UINT32ENCODE(*p, (uint32_t)1); /* Store the version number */
- UINT32ENCODE(*p, (uint32_t)0); /* Store the un-used padding */
+ UINT32ENCODE(*p, (uint32_t)H5S_GET_SELECT_TYPE(space)); /* Store the type of selection */
+ UINT32ENCODE(*p, version); /* Store the version number */
+ if(version >= 2)
+ *(*p)++ = flags; /* Store the flags */
+ else
+ UINT32ENCODE(*p, (uint32_t)0); /* Store the un-used padding */
lenp = *p; /* keep the pointer to the length location for later */
*p += 4; /* skip over space for length */
@@ -2101,8 +2169,23 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
UINT32ENCODE(*p, (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 */
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_diminfo[i].start);
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_diminfo[i].stride);
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_diminfo[i].count);
+ H5F_size_encode(f, p, space->select.sel_info.hslab->opt_unlim_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 */
@@ -2219,8 +2302,11 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t **p)
Deserialize the current selection from a user-provided buffer.
USAGE
herr_t H5S_hyper_deserialize(space, p)
+ H5F_t *f IN: File pointer
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.
@@ -2235,7 +2321,8 @@ 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(const H5F_t *f, H5S_t *space,
+ uint32_t H5_ATTR_UNUSED version, uint8_t flags, const uint8_t **p)
{
unsigned rank; /* rank of points */
size_t num_elem=0; /* number of elements in selection */
@@ -2262,32 +2349,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(*p,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 */
+ H5F_size_decode(f, p, &start[i]);
+ H5F_size_decode(f, p, &stride[i]);
+ H5F_size_decode(f, p, &count[i]);
+ H5F_size_decode(f, p, &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(*p, *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(*p,num_elem);
- /* Decode the ending points */
- for(tend=end,j=0; j<rank; j++,tend++)
- UINT32DECODE(*p, *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(*p, *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(*p, *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 */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -2460,11 +2569,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++) {
@@ -2866,6 +2983,31 @@ done:
/*--------------------------------------------------------------------------
NAME
+ H5S_hyper_unlim_dim
+ PURPOSE
+ Return unlimited dimension of selection, or -1 if none
+ USAGE
+ VDSINC
+ RETURNS
+ Unlimited dimension of selection, or -1 if none (never fails).
+ DESCRIPTION
+ VDSINC
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static int
+H5S_hyper_unlim_dim(const H5S_t *space)
+{
+ FUNC_ENTER_NOAPI_NOERR
+
+ FUNC_LEAVE_NOAPI(space->select.sel_info.hslab->unlim_dim)
+} /* end H5S_hyper_get_unlim_dim() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
H5S_hyper_is_contiguous
PURPOSE
Check if a hyperslab selection is contiguous within the dataspace extent.
@@ -3148,7 +3290,8 @@ H5S_hyper_is_regular(const H5S_t *space)
HDassert(space);
/* Only simple check for regular hyperslabs for now... */
- if(space->select.sel_info.hslab->diminfo_valid)
+ if(space->select.sel_info.hslab->diminfo_valid
+ || (space->select.sel_info.hslab->unlim_dim >= 0))
ret_value=TRUE;
else
ret_value=FALSE;
@@ -3193,13 +3336,15 @@ H5S_hyper_release(H5S_t *space)
space->select.num_elem = 0;
/* Release irregular hyperslab information */
- if(space->select.sel_info.hslab->span_lst != NULL) {
- if(H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst) < 0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
- } /* end if */
+ if(space->select.sel_info.hslab) {
+ if(space->select.sel_info.hslab->span_lst != NULL) {
+ if(H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
+ } /* end if */
- /* Release space for the hyperslab selection information */
- space->select.sel_info.hslab = H5FL_FREE(H5S_hyper_sel_t, space->select.sel_info.hslab);
+ /* Release space for the hyperslab selection information */
+ space->select.sel_info.hslab = H5FL_FREE(H5S_hyper_sel_t, space->select.sel_info.hslab);
+ } /* end if */
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -3574,6 +3719,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 */
@@ -4283,6 +4431,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 */
@@ -6029,6 +6180,12 @@ 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 */
+ 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 (only H5S_SELECT_SET supported)")
+ 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 (only H5S_SELECT_SET supported)")
+
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;
@@ -6316,6 +6473,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)
@@ -6334,6 +6492,22 @@ 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) {
+ HDassert(0 && "Checking code coverage..."); //VDSINC
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ } //VDSINC
+ else {
+ if(count[u] == block[u] /* == H5S_UNLIMITED */) {
+ HDassert(0 && "Checking code coverage..."); //VDSINC
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
+ } //VDSINC
+ unlim_dim = (int)u;
+ } /* end else */
+ } /* end if */
+
/*
* Check new selection.
*/
@@ -6382,7 +6556,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)
@@ -6394,7 +6568,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];
@@ -6522,16 +6697,103 @@ 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;
+
+ /* Initialize unlim_dim_clip_size to HSSIZET_MIN so the selection is
+ * clipped by H5S__hyper_clip_unlim() no matter what the extent is */
+ space->select.sel_info.hslab->unlim_dim_clip_size = HSSIZET_MIN;
+
/* 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) {
+ space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Save start/stride/count/block */
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].start = start[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].stride = opt_stride[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].count = opt_count[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].block = opt_block[u];
+
+ /* Calculate num_elem_non_unlim */
+ if((int)u != unlim_dim)
+ space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
+ } /* end for */
+
+ /* Set opt_diminfo or span tree based on extent */
+ if(H5S_hyper_clip_to_extent(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't set selection based on extent")
+ } /* 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];
+
+ HDassert(0 && "Checking code coverage..."); //VDSINC
+ /* 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, space->select.offset[unlim_dim], 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 */
+ else if(space->select.sel_info.hslab->unlim_dim >= 0) {
+ /* 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")
+
+ /* Convert to limited selection */
+ space->select.sel_info.hslab->unlim_dim = -1;
+
+ /* Currently just use the existing clip size. This is not ideal and
+ * may give surprising results. Note this will work differently
+ * when we switch to the new way of handling unlimited selections
+ * (unlimited selections have no clip size or clipped version). See
+ * below. VDSINC */
+#if 0 //VDSINC
+ /* Clip unlimited selection to include new selection */
+ if(H5S_hyper_clip_unlim(space,
+ (hsize_t)((hssize_t)start[space->select.sel_info.hslab->unlim_dim]
+ + space->select.offset[space->select.sel_info.hslab->unlim_dim]
+ + (((hssize_t)opt_count[space->select.sel_info.hslab->unlim_dim]
+ - (hssize_t)1)
+ * (hssize_t)opt_stride[space->select.sel_info.hslab->unlim_dim])
+ + (hssize_t)opt_block[space->select.sel_info.hslab->unlim_dim])) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection")
+#endif
+ } /* 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)
@@ -6878,6 +7140,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 */
@@ -6925,6 +7190,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)
@@ -6943,6 +7209,22 @@ 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) {
+ HDassert(0 && "Checking code coverage..."); //VDSINC
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "cannot have more than one unlimited dimension in selection")
+ } //VDSINC
+ else {
+ if(count[u] == block[u] /* == H5S_UNLIMITED */) {
+ HDassert(0 && "Checking code coverage..."); //VDSINC
+ HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "count and block cannot both be unlimited")
+ } //VDSINC
+ unlim_dim = (int)u;
+ } /* end else */
+ } /* end if */
+
/*
* Check new selection.
*/
@@ -6987,7 +7269,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)
@@ -6999,7 +7281,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];
@@ -7099,8 +7382,8 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab")
/* 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, NULL, "can't allocate hyperslab info")
+ if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info")
/* Save the diminfo */
space->select.num_elem=1;
@@ -7118,33 +7401,121 @@ 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;
+
+ /* Initialize unlim_dim_clip_size to HSSIZET_MIN so the selection is
+ * clipped by H5S__hyper_clip_to_extent() no matter what the extent is
+ */
+ space->select.sel_info.hslab->unlim_dim_clip_size = HSSIZET_MIN;
+
/* Indicate that the dimension information is valid */
- space->select.sel_info.hslab->diminfo_valid=TRUE;
+ space->select.sel_info.hslab->diminfo_valid = TRUE;
/* Indicate that there's no slab information */
- space->select.sel_info.hslab->span_lst=NULL;
+ space->select.sel_info.hslab->span_lst = NULL;
+
+ /* Handle unlimited selections */
+ if(unlim_dim >= 0) {
+ space->select.sel_info.hslab->num_elem_non_unlim = (hsize_t)1;
+ for(u = 0; u < space->extent.rank; u++) {
+ /* Save start/stride/count/block */
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].start = start[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].stride = opt_stride[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].count = opt_count[u];
+ space->select.sel_info.hslab->opt_unlim_diminfo[u].block = opt_block[u];
+
+ /* Calculate num_elem_non_unlim */
+ if((int)u != unlim_dim)
+ space->select.sel_info.hslab->num_elem_non_unlim *= (opt_count[u] * opt_block[u]);
+ } /* end for */
+
+ /* Set opt_diminfo or span tree based on extent */
+ if(H5S__hyper_clip_to_extent(space) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't set selection based on extent")
+ } /* 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];
+
+ HDassert(0 && "Checking code coverage..."); //VDSINC
+ /* 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, space->select.offset[unlim_dim], 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 */
+ else if(space->select.sel_info.hslab->unlim_dim >= 0) {
+ /* 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")
+
+ /* Convert to limited selection */
+ space->select.sel_info.hslab->unlim_dim = -1;
+
+ /* Currently just use the existing clip size. This is not ideal and
+ * may give surprising results. Note this will work differently
+ * when we switch to the new way of handling unlimited selections
+ * (unlimited selections have no clip size or clipped version). See
+ * below. VDSINC */
+#if 0 //VDSINC
+ /* Clip unlimited selection to include new selection */
+ if(H5S_hyper_clip_unlim(space,
+ (hsize_t)((hssize_t)start[space->select.sel_info.hslab->unlim_dim]
+ + space->select.offset[space->select.sel_info.hslab->unlim_dim]
+ + (((hssize_t)opt_count[space->select.sel_info.hslab->unlim_dim]
+ - (hssize_t)1)
+ * (hssize_t)opt_stride[space->select.sel_info.hslab->unlim_dim])
+ + (hssize_t)opt_block[space->select.sel_info.hslab->unlim_dim])) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection")
+#endif
+ } /* end if */
+
/* Check if there's no hyperslab span information currently */
- if(space->select.sel_info.hslab->span_lst==NULL)
- if(H5S_hyper_generate_spans(space)<0)
+ if(NULL == space->select.sel_info.hslab->span_lst)
+ if(H5S_hyper_generate_spans(space) < 0)
HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree")
+ /* Indicate that the regular dimensions are no longer valid */
+ space->select.sel_info.hslab->diminfo_valid = FALSE;
+
/* Add in the new hyperslab information */
if(H5S_generate_hyperslab (space, op, start, opt_stride, opt_count, opt_block)<0)
HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs")
-
- /* Indicate that the regular dimensions are no longer valid */
- space->select.sel_info.hslab->diminfo_valid=FALSE;
} /* end if */
else
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation")
/* Set selection type */
- space->select.type=H5S_sel_hyper;
+ space->select.type = H5S_sel_hyper;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -7333,6 +7704,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")
@@ -7462,6 +7836,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")
@@ -8794,7 +9171,7 @@ H5S_hyper_get_seq_list(const H5S_t *space, unsigned H5_ATTR_UNUSED flags, H5S_se
/* Make certain that we don't write too many */
actual_elem = MIN3(leftover, (size_t)iter->elmt_left, maxelem);
- /* initialize row sizes for each dimension */
+ /* Initialize row sizes for each dimension */
elem_size = iter->elmt_size;
for(i = (int)fast_dim, acc = elem_size; i >= 0; i--) {
slab[i] = acc;
@@ -8863,6 +9240,913 @@ 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
+ VDSINC
+ 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];
+ size_t ss_len[H5S_PROJECT_INTERSECT_NSEQS];
+ size_t ss_nseq;
+ size_t ss_nelem;
+ size_t ss_i = (size_t)0;
+ hbool_t advance_ss = FALSE;
+ H5S_sel_iter_t ss_iter;
+ hbool_t ss_iter_init = FALSE;
+ hsize_t ss_sel_off = (hsize_t)0;
+ hsize_t ds_off[H5S_PROJECT_INTERSECT_NSEQS];
+ size_t ds_len[H5S_PROJECT_INTERSECT_NSEQS];
+ size_t ds_nseq;
+ size_t ds_nelem;
+ size_t ds_i = (size_t)0;
+ H5S_sel_iter_t ds_iter;
+ hbool_t ds_iter_init = FALSE;
+ hsize_t ds_sel_off = (hsize_t)0;
+ hsize_t sis_off[H5S_PROJECT_INTERSECT_NSEQS];
+ size_t sis_len[H5S_PROJECT_INTERSECT_NSEQS];
+ size_t sis_nseq;
+ size_t sis_nelem;
+ size_t sis_i = (size_t)0;
+ hbool_t advance_sis = FALSE;
+ H5S_sel_iter_t sis_iter;
+ hbool_t sis_iter_init = FALSE;
+ hsize_t int_sel_off;
+ size_t int_len;
+ hsize_t proj_off;
+ size_t proj_len;
+ size_t proj_len_rem;
+ hsize_t proj_down_dims[H5S_MAX_RANK];
+ H5S_hyper_span_info_t *curr_span_tree[H5S_MAX_RANK];
+ H5S_hyper_span_t *prev_span[H5S_MAX_RANK];
+ hsize_t curr_span_up_dim[H5S_MAX_RANK];
+ unsigned proj_rank;
+ hsize_t low;
+ hsize_t high;
+ size_t span_len;
+ size_t nelem;
+ unsigned i;
+ herr_t ret_value = SUCCEED;
+
+ 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? */
+
+ /* 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_CANTSELECT, 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_CANTSELECT, 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_CANTSELECT, 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
+ VDSINC
+ USAGE
+ VDSINC
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ VDSINC
+
+ 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 */
+
+ HDassert(0 && "Checking code coverage..."); //VDSINC
+ /* 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
+ VDSINC
+ 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. if
+ superset is TRUE, then the hyperslab can be clipped to a size equal to
+ or greater than clip_size.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this function takes the offset into account.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static void
+H5S__hyper_get_clip_diminfo(hsize_t start, hsize_t stride, hsize_t *count,
+ hsize_t *block, hssize_t offset, hsize_t clip_size)
+{
+ FUNC_ENTER_PACKAGE_NOERR
+
+ /* Check for selection outside clip size */
+ if((hsize_t)((hssize_t)start + offset) >= 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 = (hsize_t)((hssize_t)clip_size - ((hssize_t)start + offset));
+ *count = (hsize_t)1;
+ } /* end if */
+ else {
+ HDassert(*count == H5S_UNLIMITED);
+ HDassert((hssize_t)clip_size > offset);
+
+ /* Calculate initial count (last block may be partial) */
+ *count = (hsize_t)((hssize_t)clip_size - ((hssize_t)start + offset)
+ + (hssize_t)stride - (hssize_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
+ VDSINC
+ 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. if
+ superset is TRUE, then the hyperslab can be clipped to a size equal to
+ or greater than clip_size. If include_offset is TRUE, then the offset
+ is taken into account.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this function takes 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 */
+
+ 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);
+
+ diminfo = &hslab->opt_diminfo[hslab->unlim_dim];
+
+ /* Check for no need to change size */
+ if(((hssize_t)clip_size - space->select.offset[hslab->unlim_dim])
+ == hslab->unlim_dim_clip_size)
+ HGOTO_DONE(SUCCEED)
+
+ /* Free previous spans, if any */
+ if(hslab->span_lst != NULL) {
+ if(H5S_hyper_free_span_info(hslab->span_lst) < 0)
+ HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans")
+ hslab->span_lst = NULL;
+ } /* end if */
+
+ /* Initialize opt_diminfo with opt_unlim_diminfo */
+ *diminfo = hslab->opt_unlim_diminfo[hslab->unlim_dim];
+
+ /* Get initial diminfo */
+ H5S__hyper_get_clip_diminfo(diminfo->start, diminfo->stride, &diminfo->count, &diminfo->block, space->select.offset[hslab->unlim_dim], clip_size);
+
+ /* Check for nothing returned */
+ if((diminfo->block == 0)
+ || (diminfo->count == 0)) {
+ /* Set num_elem */
+ space->select.num_elem = (hsize_t)0;
+
+ /* Mark that opt_diminfo is valid */
+ hslab->diminfo_valid = TRUE;
+ } /* end if */
+ /* Check for single block in unlimited dimension */
+ else if(hslab->opt_unlim_diminfo[hslab->unlim_dim].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. */
+ if(((diminfo->stride * (diminfo->count - (hsize_t)1)) + diminfo->block)
+ > ((hsize_t)((hssize_t)clip_size - ((hssize_t)diminfo->start
+ + space->select.offset[hslab->unlim_dim])))) {
+ 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 == hslab->unlim_dim)
+ block[i] = (hsize_t)((hssize_t)clip_size
+ - space->select.offset[hslab->unlim_dim]);
+ 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 calculate 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 */
+
+ /* Save clip size */
+ hslab->unlim_dim_clip_size = (hssize_t)clip_size
+ - space->select.offset[hslab->unlim_dim];
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_clip_unlim() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_clip_to_extent
+ PURPOSE
+ Updates the hyperslab selection after a change to the dataspace extent
+ or offset
+ USAGE
+ VDSINC
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ Since unlimited selections are internally described as limited
+ selections with maximal size, these internal selections need to be
+ updated whenever the maximum size changes. This function
+ recaluculates the unlimited dimension (if any) of the hyperslab
+ selection when the extent or offset is changed.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this function takes the offset into account.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_hyper_clip_to_extent(H5S_t *space)
+{
+ H5S_hyper_sel_t *hslab; /* Convenience pointer to hyperslab info */
+ herr_t ret_value = SUCCEED;
+
+ FUNC_ENTER_NOAPI(FAIL)
+
+ /* Check parameters */
+ HDassert(space);
+ hslab = space->select.sel_info.hslab;
+ HDassert(hslab);
+
+ /* Check for unlimited dimension */
+ if(hslab->unlim_dim < 0)
+ HGOTO_DONE(SUCCEED)
+
+ /* Clip unlimited selection to extent */
+ if(H5S_hyper_clip_unlim(space, space->extent.size[hslab->unlim_dim]) < 0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "failed to clip unlimited selection")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5S_hyper_clip_to_extent() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_get_clip_extent
+ PURPOSE
+ VDSINC
+ USAGE
+ VDSINC
+ RETURNS
+ Non-negative on success/Negative on failure.
+ DESCRIPTION
+ VDSINC
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ Note this assumes the offset has been normalized.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+herr_t
+H5S_hyper_get_clip_extent(const H5S_t *clip_space, const H5S_t *match_space,
+ hsize_t *clip_size, hbool_t incl_trail)
+{
+ const H5S_hyper_sel_t *clip_hslab; /* Convenience pointer to hyperslab info */
+ const H5S_hyper_sel_t *match_hslab; /* Convenience pointer to hyperslab info */
+ const H5S_hyper_dim_t *diminfo; /* Convenience pointer to opt_unlim_diminfo in unlimited dimension */
+ hsize_t num_slices;
+ hsize_t count;
+ hsize_t rem_slices;
+
+ FUNC_ENTER_NOAPI_NOERR
+
+ /* Check parameters */
+ HDassert(clip_space);
+ clip_hslab = clip_space->select.sel_info.hslab;
+ HDassert(clip_hslab);
+ HDassert(match_space);
+ match_hslab = match_space->select.sel_info.hslab;
+ HDassert(match_space);
+ HDassert(clip_size);
+ HDassert(clip_hslab->unlim_dim >= 0);
+ HDassert(match_hslab->unlim_dim >= 0);
+ HDassert(clip_hslab->num_elem_non_unlim == match_hslab->num_elem_non_unlim);
+
+ diminfo = &clip_hslab->opt_unlim_diminfo[clip_hslab->unlim_dim];
+
+ /* Calculate number of slices */
+ num_slices = match_space->select.num_elem / match_hslab->num_elem_non_unlim;
+
+ if(num_slices == 0) {
+ //HDassert(incl_trail && "Checking code coverage..."); //VDSINC
+ HDassert(!incl_trail && "Checking code coverage..."); //VDSINC
+ *clip_size = incl_trail ? diminfo->start : 0;
+ } //VDSINC
+ 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 */
+ *clip_size = 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) */
+ *clip_size = diminfo->start + (count * diminfo->stride)
+ + rem_slices;
+ else {
+ if(incl_trail)
+ /* End extent just before first missing block */
+ *clip_size = diminfo->start + (count * diminfo->stride);
+ else
+ /* End extent at end of last block */
+ *clip_size = diminfo->start + ((count - (hsize_t)1)
+ * diminfo->stride) + diminfo->block;
+ } /* end else */
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(SUCCEED)
+} /* end H5S_hyper_get_clip_extent() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_get_unlim_block
+ PURPOSE
+ VDSINC
+ USAGE
+ VDSINC
+ RETURNS
+ New space on success/NULL on failure.
+ DESCRIPTION
+ VDSINC
+ 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_unlim_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_unlim_diminfo[i].start + (block_index
+ * hslab->opt_unlim_diminfo[i].stride);
+ count[i] = (hsize_t)1;
+ } /* end if */
+ else {
+ start[i] = hslab->opt_unlim_diminfo[i].start;
+ count[i] = hslab->opt_unlim_diminfo[i].count;
+ } /* end else */
+ stride[i] = hslab->opt_unlim_diminfo[i].stride;
+ block[i] = hslab->opt_unlim_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")
+
+ /* Set offset to zeros */
+ (void)HDmemset(space_out->select.offset, 0, (size_t)space_out->extent.rank * sizeof(space_out->select.offset[0]));
+ space_out->select.offset_changed = FALSE;
+
+ /* 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
H5Sis_regular_hyperslab
PURPOSE
Determine if a hyperslab selection is regular
@@ -8934,6 +10218,7 @@ H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[], hsize_t stride[],
hsize_t count[], hsize_t block[])
{
H5S_t *space; /* Dataspace to query */
+ H5S_hyper_dim_t *diminfo; /* Pointer to diminfo to return */
unsigned u; /* Local index variable */
herr_t ret_value = SUCCEED; /* Return value */
@@ -8948,19 +10233,27 @@ H5Sget_regular_hyperslab(hid_t spaceid, hsize_t start[], hsize_t stride[],
if(TRUE != H5S_hyper_is_regular(space))
HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a regular hyperslab selection")
+ /* Determine which diminfo to return */
+ if(space->select.sel_info.hslab->diminfo_valid)
+ diminfo = space->select.sel_info.hslab->app_diminfo;
+ else {
+ HDassert(space->select.sel_info.hslab->unlim_dim >= 0);
+ diminfo = space->select.sel_info.hslab->opt_unlim_diminfo;
+ } /* end else */
+
/* Retrieve hyperslab parameters */
if(start)
for(u = 0; u < space->extent.rank; u++)
- start[u] = space->select.sel_info.hslab->app_diminfo[u].start;
+ start[u] = diminfo[u].start;
if(stride)
for(u = 0; u < space->extent.rank; u++)
- stride[u] = space->select.sel_info.hslab->app_diminfo[u].stride;
+ stride[u] = diminfo[u].stride;
if(count)
for(u = 0; u < space->extent.rank; u++)
- count[u] = space->select.sel_info.hslab->app_diminfo[u].count;
+ count[u] = diminfo[u].count;
if(block)
for(u = 0; u < space->extent.rank; u++)
- block[u] = space->select.sel_info.hslab->app_diminfo[u].block;
+ block[u] = diminfo[u].block;
done:
FUNC_LEAVE_API(ret_value)