summaryrefslogtreecommitdiffstats
path: root/src/H5Shyper.c
diff options
context:
space:
mode:
authorQuincey Koziol <koziol@hdfgroup.org>2003-06-04 15:45:11 (GMT)
committerQuincey Koziol <koziol@hdfgroup.org>2003-06-04 15:45:11 (GMT)
commit4d8f148d0953939baed118399fffe6db05b3a98e (patch)
treec2b8f599d940da1f922be72eb2f482e5984d95f6 /src/H5Shyper.c
parent2a7cf2ea942db24f2c759d43533c0e4df018efe6 (diff)
downloadhdf5-4d8f148d0953939baed118399fffe6db05b3a98e.zip
hdf5-4d8f148d0953939baed118399fffe6db05b3a98e.tar.gz
hdf5-4d8f148d0953939baed118399fffe6db05b3a98e.tar.bz2
[svn-r6957] Purpose:
Code cleanup & performance improvements Description: Optimize hyperslabs that are built to detect situations where "regular" hyperslabs can be recovered from span tree descriptions. Also, improve "same shape" routine to correctly work with all the different combinations of selections. Platforms tested: FreeBSD 4.8 (sleipnir) w/C++ FreeBSD 4.8 (sleipnir) w/parallel h5committested
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r--src/H5Shyper.c601
1 files changed, 557 insertions, 44 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c
index e62dc4f..06cb6ae 100644
--- a/src/H5Shyper.c
+++ b/src/H5Shyper.c
@@ -28,8 +28,10 @@
#include "H5Spkg.h" /* Dataspace functions */
#include "H5Vprivate.h" /* Vector functions */
-/* Interface initialization */
+/* Pablo mask */
#define PABLO_MASK H5Shyper_mask
+
+/* Interface initialization */
#define INTERFACE_INIT NULL
static int interface_initialize_g = 0;
@@ -45,6 +47,13 @@ static herr_t H5S_hyper_span_precompute (H5S_hyper_span_info_t *spans, size_t el
#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 herr_t H5S_hyper_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords);
+static herr_t H5S_hyper_iter_block(const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end);
+static hsize_t H5S_hyper_iter_nelmts(const H5S_sel_iter_t *iter);
+static htri_t H5S_hyper_iter_has_next_block(const H5S_sel_iter_t *sel_iter);
+static herr_t H5S_hyper_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem);
+static herr_t H5S_hyper_iter_next_block(H5S_sel_iter_t *sel_iter);
+static herr_t H5S_hyper_iter_release(H5S_sel_iter_t *sel_iter);
/* Declare a free list to manage the H5S_hyper_span_t struct */
H5FL_DEFINE_STATIC(H5S_hyper_span_t);
@@ -111,6 +120,11 @@ H5S_hyper_print_spans(const struct H5S_hyper_span_info_t *span_lst)
* Programmer: Quincey Koziol
* Saturday, February 24, 2001
*
+ * Notes: If the 'elmt_size' parameter is set to zero, the regular
+ * hyperslab selection iterator will not be 'flattened'. This
+ * is used by the H5S_select_shape_same() code to avoid changing
+ * the rank and appearance of the selection.
+ *
* Modifications:
*
*-------------------------------------------------------------------------
@@ -162,13 +176,18 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size)
/* Initialize the number of contiguous dimensions to be the same as the dataspace's rank */
cont_dim=rank;
- /* Check for a "contiguous" block */
- for(u=rank-1; u>0; u--) {
- if(tdiminfo[u].count==1 && tdiminfo[u].block==mem_size[u])
- cont_dim=u;
- else
- break;
- } /* end for */
+ /* Don't flatten adjacent elements into contiguous block if the
+ * element size is 0. This is for the H5S_select_shape_same() code.
+ */
+ if(elmt_size>0) {
+ /* Check for a "contiguous" block */
+ for(u=rank-1; u>0; u--) {
+ if(tdiminfo[u].count==1 && tdiminfo[u].block==mem_size[u])
+ cont_dim=u;
+ else
+ break;
+ } /* end for */
+ } /* end if */
/* Check if the regular selection can be "flattened" */
if(cont_dim<rank) {
@@ -289,8 +308,11 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size)
/* Initialize methods for selection iterator */
iter->iter_coords=H5S_hyper_iter_coords;
+ iter->iter_block=H5S_hyper_iter_block;
iter->iter_nelmts=H5S_hyper_iter_nelmts;
+ iter->iter_has_next_block=H5S_hyper_iter_has_next_block;
iter->iter_next=H5S_hyper_iter_next;
+ iter->iter_next_block=H5S_hyper_iter_next_block;
iter->iter_release=H5S_hyper_iter_release;
done:
@@ -313,12 +335,10 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords)
{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5S_hyper_iter_coords, FAIL);
+ FUNC_ENTER_NOINIT(H5S_hyper_iter_coords);
/* Check args */
assert (iter);
@@ -348,12 +368,66 @@ H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords)
else
HDmemcpy(coords,iter->u.hyp.off,sizeof(hssize_t)*iter->rank);
-done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(SUCCEED);
} /* H5S_hyper_iter_coords() */
/*-------------------------------------------------------------------------
+ * Function: H5S_hyper_iter_block
+ *
+ * Purpose: Retrieve the current block of iterator for current
+ * selection
+ *
+ * Return: non-negative on success, negative on failure
+ *
+ * Programmer: Quincey Koziol
+ * Monday, June 2, 2003
+ *
+ * Notes: This routine assumes that the iterator is always located at
+ * the beginning of a block.
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5S_hyper_iter_block (const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end)
+{
+ unsigned u; /* Local index variable */
+
+ FUNC_ENTER_NOINIT(H5S_hyper_iter_block);
+
+ /* Check args */
+ assert (iter);
+ assert (start);
+ assert (end);
+
+ /* Copy the offset of the current point */
+
+ /* Check for a single "regular" hyperslab */
+ if(iter->u.hyp.diminfo!=NULL) {
+ /* Copy the current iterator offset as the start */
+ HDmemcpy(start,iter->u.hyp.off,sizeof(hssize_t)*iter->rank);
+
+ /* Compute the end of the block */
+ for(u=0; u<iter->rank; u++)
+ end[u]=(start[u]+iter->u.hyp.diminfo[u].block)-1;
+ } /* end if */
+ else {
+ /* Copy the start of the block */
+ for(u=0; u<iter->rank; u++)
+ start[u]=iter->u.hyp.span[u]->low;
+
+ /* Copy the end of the block */
+ for(u=0; u<iter->rank; u++)
+ end[u]=iter->u.hyp.span[u]->high;
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* H5S_hyper_iter_block() */
+
+
+/*-------------------------------------------------------------------------
* Function: H5S_hyper_iter_nelmts
*
* Purpose: Return number of elements left to process in iterator
@@ -367,22 +441,73 @@ done:
*
*-------------------------------------------------------------------------
*/
-hsize_t
+static hsize_t
H5S_hyper_iter_nelmts (const H5S_sel_iter_t *iter)
{
- hsize_t ret_value; /* Return value */
+ FUNC_ENTER_NOINIT(H5S_hyper_iter_nelmts);
+
+ /* Check args */
+ assert (iter);
+
+ FUNC_LEAVE_NOAPI(iter->elmt_left);
+} /* H5S_hyper_iter_nelmts() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_iter_has_next_block
+ PURPOSE
+ Check if there is another block left in the current iterator
+ USAGE
+ htri_t H5S_hyper_iter_has_next_block(iter)
+ const H5S_sel_iter_t *iter; IN: Pointer to selection iterator
+ RETURNS
+ Non-negative (TRUE/FALSE) on success/Negative on failure
+ DESCRIPTION
+ Check if there is another block available in the selection iterator.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static htri_t
+H5S_hyper_iter_has_next_block(const H5S_sel_iter_t *iter)
+{
+ unsigned u; /* Local index variable */
+ herr_t ret_value=FALSE; /* Return value */
- FUNC_ENTER_NOAPI(H5S_hyper_iter_nelmts, 0);
+ FUNC_ENTER_NOINIT(H5S_hyper_iter_has_next_block);
/* Check args */
assert (iter);
- /* Set return value */
- ret_value=iter->elmt_left;
+ /* Check for a single "regular" hyperslab */
+ if(iter->u.hyp.diminfo!=NULL) {
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
+ const hssize_t *toff; /* Temporary offset in selection */
+
+ /* Check if the offset of the iterator is at the last location in all dimensions */
+ tdiminfo=iter->u.hyp.diminfo;
+ toff=iter->u.hyp.off;
+ for(u=0; u<iter->rank; u++) {
+ /* If there is only one block, continue */
+ if(tdiminfo[u].count==1)
+ continue;
+ H5_CHECK_OVERFLOW(tdiminfo[u].start+((tdiminfo[u].count-1)*tdiminfo[u].stride),hsize_t,hssize_t);
+ if(toff[u]!=(hssize_t)(tdiminfo[u].start+((tdiminfo[u].count-1)*tdiminfo[u].stride)))
+ HGOTO_DONE(TRUE);
+ } /* end for */
+ } /* end if */
+ else {
+ /* Check for any levels of the tree with more sequences in them */
+ for(u=0; u<iter->rank; u++)
+ if(iter->u.hyp.span[u]->next!=NULL)
+ HGOTO_DONE(TRUE);
+ } /* end else */
done:
FUNC_LEAVE_NOAPI(ret_value);
-} /* H5S_hyper_iter_nelmts() */
+} /* H5S_hyper_iter_has_next_block() */
/*-------------------------------------------------------------------------
@@ -403,7 +528,7 @@ done:
*
*-------------------------------------------------------------------------
*/
-herr_t
+static herr_t
H5S_hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
{
unsigned ndims; /* Number of dimensions of dataset */
@@ -602,6 +727,191 @@ H5S_hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
} /* H5S_hyper_iter_next() */
+/*-------------------------------------------------------------------------
+ * Function: H5S_hyper_iter_next_block
+ *
+ * Purpose: Moves a hyperslab iterator to the beginning of the next sequence
+ * of elements to read. Handles walking off the end in all dimensions.
+ *
+ * Return: Success: non-negative
+ * Failure: negative
+ *
+ * Programmer: Quincey Koziol
+ * Tuesday, June 3, 2003
+ *
+ * Modifications:
+ *
+ *-------------------------------------------------------------------------
+ */
+static herr_t
+H5S_hyper_iter_next_block(H5S_sel_iter_t *iter)
+{
+ unsigned ndims; /* Number of dimensions of dataset */
+ int fast_dim; /* Rank of the fastest changing dimension for the dataspace */
+ unsigned u; /* Counters */
+
+ FUNC_ENTER_NOINIT(H5S_hyper_iter_next_block);
+
+ /* Check for the special case of just one H5Sselect_hyperslab call made */
+ /* (i.e. a regular hyperslab selection */
+ if(iter->u.hyp.diminfo!=NULL) {
+ const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */
+ hsize_t iter_offset[H5O_LAYOUT_NDIMS];
+ hsize_t iter_count[H5O_LAYOUT_NDIMS];
+ int temp_dim; /* Temporary rank holder */
+
+ /* Check if this is a "flattened" regular hyperslab selection */
+ if(iter->u.hyp.iter_rank!=0 && iter->u.hyp.iter_rank<iter->rank) {
+ /* Set the aliases for the dimension rank */
+ ndims=iter->u.hyp.iter_rank;
+ } /* end if */
+ else {
+ /* Set the aliases for the dimension rank */
+ ndims=iter->rank;
+ } /* end else */
+
+ /* Set the fastest dimension rank */
+ fast_dim=ndims-1;
+
+ /* Set the local copy of the diminfo pointer */
+ tdiminfo=iter->u.hyp.diminfo;
+
+ /* Calculate the offset and block count for each dimension */
+ for(u=0; u<ndims; u++) {
+ if(tdiminfo[u].stride==1) {
+ iter_offset[u]=iter->u.hyp.off[u]-tdiminfo[u].start;
+ iter_count[u]=0;
+ } /* end if */
+ else {
+ iter_offset[u]=(iter->u.hyp.off[u]-tdiminfo[u].start)%tdiminfo[u].stride;
+ iter_count[u]=(iter->u.hyp.off[u]-tdiminfo[u].start)/tdiminfo[u].stride;
+ } /* end else */
+ } /* end for */
+
+ /* Advance one block */
+ temp_dim=fast_dim; /* Start with the fastest changing dimension */
+ while(temp_dim>=0) {
+ if(temp_dim==fast_dim) {
+ /* Move iterator over current block */
+ iter_offset[temp_dim]+=tdiminfo[temp_dim].block;
+ } /* end if */
+ else {
+ /* Move to the next row in the current dimension */
+ iter_offset[temp_dim]++;
+ } /* end else */
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(iter_offset[temp_dim]<tdiminfo[temp_dim].block)
+ break;
+ else {
+ /* Move to the next block in the current dimension */
+ iter_offset[temp_dim]=0;
+ iter_count[temp_dim]++;
+
+ /* If this block is still in the range of blocks to output for the dimension, break out of loop */
+ if(iter_count[temp_dim]<tdiminfo[temp_dim].count)
+ break;
+ else
+ iter_count[temp_dim]=0; /* reset back to the beginning of the line */
+ } /* end else */
+
+ /* Decrement dimension count */
+ temp_dim--;
+ } /* end while */
+
+ /* Translate current iter_offset and iter_count into iterator position */
+ for(u=0; u<ndims; u++)
+ iter->u.hyp.off[u]=tdiminfo[u].start+(tdiminfo[u].stride*iter_count[u])+iter_offset[u];
+ } /* end if */
+ /* Must be an irregular hyperslab selection */
+ else {
+ H5S_hyper_span_t *curr_span; /* Current hyperslab span node */
+ H5S_hyper_span_t **ispan; /* Iterator's hyperslab span nodes */
+ hssize_t *abs_arr; /* Absolute hyperslab span position */
+ int curr_dim; /* Temporary rank holder */
+
+ /* Set the rank of the fastest changing dimension */
+ ndims=iter->rank;
+ fast_dim=(ndims-1);
+
+ /* Get the pointers to the current span info and span nodes */
+ abs_arr=iter->u.hyp.off;
+ ispan=iter->u.hyp.span;
+
+ /* Loop through, advancing the span information, until all the nelements are accounted for */
+ curr_dim=fast_dim; /* Start at the fastest dim */
+
+ /* Work back up through the dimensions */
+ while(curr_dim>=0) {
+ /* Reset the current span */
+ curr_span=ispan[curr_dim];
+
+ /* Increment absolute position */
+ if(curr_dim==fast_dim) {
+ /* Move the iterator over rest of element in span */
+ abs_arr[curr_dim]=curr_span->high+1;
+ } /* end if */
+ else {
+ /* Move to the next row in the current dimension */
+ abs_arr[curr_dim]++;
+ } /* end else */
+
+ /* Check if we are still within the span */
+ if(abs_arr[curr_dim]<=curr_span->high) {
+ break;
+ } /* end if */
+ /* If we walked off that span, advance to the next span */
+ else {
+ /* Advance span in this dimension */
+ curr_span=curr_span->next;
+
+ /* Check if we have a valid span in this dimension still */
+ if(curr_span!=NULL) {
+ /* Reset the span in the current dimension */
+ ispan[curr_dim]=curr_span;
+
+ /* Reset absolute position */
+ abs_arr[curr_dim]=curr_span->low;
+
+ break;
+ } /* end if */
+ else {
+ /* If we finished the span list in this dimension, decrement the dimension worked on and loop again */
+ curr_dim--;
+ } /* end else */
+ } /* end else */
+ } /* end while */
+
+ /* Check if we are finished with the spans in the tree */
+ if(curr_dim>=0) {
+ /* Walk back down the iterator positions, reseting them */
+ while(curr_dim<fast_dim) {
+ assert(curr_span);
+ assert(curr_span->down);
+ assert(curr_span->down->head);
+
+ /* Increment current dimension */
+ curr_dim++;
+
+ /* Set the new span_info & span for this dimension */
+ ispan[curr_dim]=curr_span->down->head;
+
+ /* Advance span down the tree */
+ curr_span=curr_span->down->head;
+
+ /* Reset the absolute offset for the dim */
+ abs_arr[curr_dim]=curr_span->low;
+ } /* end while */
+
+ /* Verify that the curr_span points to the fastest dim */
+ assert(curr_span==ispan[fast_dim]);
+ } /* end if */
+ } /* end else */
+
+ FUNC_LEAVE_NOAPI(SUCCEED);
+} /* H5S_hyper_iter_next() */
+
+
/*--------------------------------------------------------------------------
NAME
H5S_hyper_iter_release
@@ -619,12 +929,10 @@ H5S_hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem)
EXAMPLES
REVISION LOG
--------------------------------------------------------------------------*/
-herr_t
+static herr_t
H5S_hyper_iter_release (H5S_sel_iter_t *iter)
{
- herr_t ret_value=SUCCEED; /* Return value */
-
- FUNC_ENTER_NOAPI(H5S_hyper_iter_release, FAIL);
+ FUNC_ENTER_NOINIT(H5S_hyper_iter_release);
/* Check args */
assert (iter);
@@ -655,8 +963,7 @@ H5S_hyper_iter_release (H5S_sel_iter_t *iter)
if(iter->u.hyp.span!=NULL)
H5FL_ARR_FREE(H5S_hyper_span_t,iter->u.hyp.span);
-done:
- FUNC_LEAVE_NOAPI(ret_value);
+ FUNC_LEAVE_NOAPI(SUCCEED);
} /* H5S_hyper_iter_release() */
@@ -769,7 +1076,7 @@ H5S_hyper_span_precompute_helper (H5S_hyper_span_info_t *spans, size_t elmt_size
H5S_hyper_span_t *span; /* Hyperslab span */
herr_t ret_value=SUCCEED; /* Return value */
- FUNC_ENTER_NOINIT(H5S_hyper_span_precompute);
+ FUNC_ENTER_NOINIT(H5S_hyper_span_precompute_helper);
assert(spans);
@@ -2294,7 +2601,7 @@ done:
REVISION LOG
--------------------------------------------------------------------------*/
static herr_t
-H5S_hyper_bounds_helper (const H5S_hyper_span_info_t *spans, const hssize_t *offset, hsize_t rank, hsize_t *start, hsize_t *end)
+H5S_hyper_bounds_helper (const H5S_hyper_span_info_t *spans, const hssize_t *offset, hsize_t rank, hssize_t *start, hssize_t *end)
{
H5S_hyper_span_t *curr; /* Hyperslab information nodes */
herr_t ret_value=SUCCEED; /* Return value */
@@ -2311,9 +2618,9 @@ H5S_hyper_bounds_helper (const H5S_hyper_span_info_t *spans, const hssize_t *off
curr=spans->head;
while(curr!=NULL) {
/* Check if the current span extends the bounding box */
- if((hsize_t)(curr->low+offset[rank])<start[rank])
+ if((curr->low+offset[rank])<start[rank])
start[rank]=curr->low+offset[rank];
- if((hsize_t)(curr->high+offset[rank])>end[rank])
+ if((curr->high+offset[rank])>end[rank])
end[rank]=curr->high+offset[rank];
/* Recurse if this node has down spans */
@@ -2359,7 +2666,7 @@ H5S_hyper_bounds_helper (const H5S_hyper_span_info_t *spans, const hssize_t *off
REVISION LOG
--------------------------------------------------------------------------*/
herr_t
-H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
+H5S_hyper_bounds(const H5S_t *space, hssize_t *start, hssize_t *end)
{
int rank; /* Dataspace rank */
int i; /* index variable */
@@ -2374,8 +2681,8 @@ H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end)
/* Set the start and end arrays up */
rank=space->extent.u.simple.rank;
for(i=0; i<rank; i++) {
- start[i]=HSIZET_MAX;
- end[i]=0;
+ start[i]=HSSIZET_MAX;
+ end[i]=HSSIZET_MIN;
} /* end for */
/* Check for a "regular" hyperslab selection */
@@ -3414,9 +3721,6 @@ H5S_hyper_adjust_helper (H5S_hyper_span_info_t *spans, const hssize_t *offset)
/* Iterate over the spans in tree */
while(span!=NULL) {
-#ifdef QAK
-HDfprintf(stderr,"%s: span={%Hd, %Hd}, *offset=%Hd\n",FUNC,span->low,span->high,*offset);
-#endif /* QAK */
/* Adjust span offset */
span->low-=*offset;
assert(span->low>=0);
@@ -4732,6 +5036,139 @@ done:
FUNC_LEAVE_NOAPI(ret_value);
} /* H5S_hyper_make_spans() */
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_can_rebuild
+ PURPOSE
+ Check if optimized hyperslab information can be recovered
+ USAGE
+ htri_t H5S_hyper_can_rebuild(space)
+ const H5S_t *space; IN: Dataspace to check
+ RETURNS
+ TRUE/FALSE on success, <0 on failure
+ DESCRIPTION
+ Examine the span tree for a hyperslab selection and determine if it
+ can be used to rebuild the start/stride/count/block information for
+ the selection.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ To be able to recover the optimized information, the span tree must conform
+ to span tree able to be generated from a single H5S_SELECT_SET operation.
+
+ This routine doesn't currently detect strided block situations.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static htri_t
+H5S_hyper_can_rebuild (const H5S_t *space)
+{
+ H5S_hyper_span_t *span; /* Current hyperslab span */
+ htri_t ret_value=TRUE; /* Return value */
+
+ FUNC_ENTER_NOINIT(H5S_hyper_can_rebuild);
+
+ /* Check args */
+ assert (space);
+ assert (space->select.sel_info.hslab.span_lst);
+
+ /* For each level of the span tree check that there is only one span at
+ * that level.
+ */
+ span=space->select.sel_info.hslab.span_lst->head;
+ while(span!=NULL) {
+ if(span->next!=NULL)
+ HGOTO_DONE(FALSE);
+ if(span->down)
+ span=span->down->head;
+ else
+ break;
+ } /* end while */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5S_hyper_can_rebuild() */
+
+
+/*--------------------------------------------------------------------------
+ NAME
+ H5S_hyper_rebuild
+ PURPOSE
+ Recover optimized hyperslab information from span tree
+ USAGE
+ herr_t H5S_hyper_rebuild(space)
+ H5S_t *space; IN: Dataspace to rebuild optimized selection within
+ RETURNS
+ Non-negative on success/Negative on failure
+ DESCRIPTION
+ Use the span tree information to recover the optimized form of a hyperslab
+ selection.
+ GLOBAL VARIABLES
+ COMMENTS, BUGS, ASSUMPTIONS
+ The recovered optimized information will be similar to that generated from
+ a single H5S_SELECT_SET operation.
+ EXAMPLES
+ REVISION LOG
+--------------------------------------------------------------------------*/
+static herr_t
+H5S_hyper_rebuild (H5S_t *space)
+{
+ H5S_hyper_dim_t *diminfo; /* Per-dimension info for the selection */
+ H5S_hyper_dim_t *app_diminfo; /* "Application view" per-dimension for the selection */
+ H5S_hyper_span_t *span; /* Current hyperslab span */
+ unsigned curr_dim; /* Current dimension being worked on */
+ herr_t ret_value=SUCCEED; /* Return value */
+
+ FUNC_ENTER_NOINIT(H5S_hyper_rebuild);
+
+ /* Check args */
+ assert (space);
+ assert (space->select.sel_info.hslab.span_lst);
+
+ /* Get head of span list */
+ span=space->select.sel_info.hslab.span_lst->head;
+
+ /* Protect against empty tree */
+ if(span!=NULL) {
+ /* Allocate space for the optimized hyperslab information */
+ if((diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector");
+
+ /* Allocate space for the optimized hyperslab information */
+ if((app_diminfo = H5FL_ARR_MALLOC(H5S_hyper_dim_t,space->extent.u.simple.rank))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate per-dimension vector");
+
+ /* Iterate down the span tree */
+ curr_dim=0;
+ while(span!=NULL) {
+ /* Sanity check */
+ assert(curr_dim<space->extent.u.simple.rank);
+
+ /* Recover the optimized dimension information */
+ app_diminfo[curr_dim].start = diminfo[curr_dim].start = span->low;
+ app_diminfo[curr_dim].stride = diminfo[curr_dim].stride = 1;
+ app_diminfo[curr_dim].count = diminfo[curr_dim].count = 1;
+ app_diminfo[curr_dim].block = diminfo[curr_dim].block = (span->high-span->low)+1;
+ assert(diminfo[curr_dim].block>0);
+
+ /* Walk down the span tree */
+ if(span->down) {
+ span=span->down->head;
+ curr_dim++;
+ } /* end if */
+ else
+ break;
+ } /* end while */
+
+ /* Set the dataspace's pointers to the new optimized information */
+ space->select.sel_info.hslab.diminfo = diminfo;
+ space->select.sel_info.hslab.app_diminfo = app_diminfo;
+ } /* end if */
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value);
+} /* H5S_hyper_rebuild() */
+
#ifndef NEW_HYPERSLAB_API
/*-------------------------------------------------------------------------
@@ -4758,12 +5195,13 @@ H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op,
hsize_t stride[H5O_LAYOUT_NDIMS]; /* Optimized stride information */
hsize_t count[H5O_LAYOUT_NDIMS]; /* Optimized count information */
hsize_t block[H5O_LAYOUT_NDIMS]; /* Optimized block information */
- H5S_hyper_span_info_t *new_spans; /* Span tree for new hyperslab */
+ H5S_hyper_span_info_t *new_spans=NULL; /* Span tree for new hyperslab */
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 */
hssize_t nelem; /* Number of elements in hyperslab span tree */
unsigned u; /* Counters */
+ htri_t status; /* Status from internal calls */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOINIT(H5S_generate_hyperslab);
@@ -4921,6 +5359,7 @@ H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op,
default:
HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation");
} /* end switch */
+
/* Free the hyperslab trees generated from the clipping algorithm */
if(a_not_b)
H5S_hyper_free_span_info(a_not_b);
@@ -4928,13 +5367,49 @@ H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op,
H5S_hyper_free_span_info(a_and_b);
if(b_not_a)
H5S_hyper_free_span_info(b_not_a);
+
+ /* Check if the resulting hyperslab span tree is empty */
+ if(space->select.sel_info.hslab.span_lst==NULL) {
+ H5S_hyper_span_info_t *spans; /* Empty hyperslab span tree */
+
+ /* Sanity check */
+ assert(space->select.num_elem==0);
+
+ /* Allocate a span info node */
+ if((spans = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "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 */
+ else {
+ /* Check if the resulting hyperslab span tree can be used to re-build
+ * "optimized" start/stride/count/block information.
+ */
+ status=H5S_hyper_can_rebuild(space);
+ if(status<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't check for rebuilding hyperslab info");
+ if(status>0)
+ if(H5S_hyper_rebuild(space)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info");
+ } /* end else */
} /* end else */
+done:
/* Free the new spans */
- if(H5S_hyper_free_span_info(new_spans)<0)
- HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans");
+ if(new_spans!=NULL)
+ if(H5S_hyper_free_span_info(new_spans)<0)
+ HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans");
-done:
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5S_generate_hyperslab() */
@@ -5136,7 +5611,7 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op,
/* Sanity check */
assert(space->select.type==H5S_SEL_HYPERSLABS);
- /* Is this the first 'or' operation? */
+ /* Is this the first operation? */
if(space->select.sel_info.hslab.diminfo != NULL) {
/* Remove the 'diminfo' information, since we're adding to it */
H5FL_ARR_FREE(H5S_hyper_dim_t,space->select.sel_info.hslab.diminfo);
@@ -5256,6 +5731,7 @@ H5S_operate_hyperslab (H5S_t *result, H5S_hyper_span_info_t *spans1, H5S_seloper
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 */
hssize_t nelem; /* Number of elements in hyperslab span tree */
+ htri_t status; /* Status from internal calls */
herr_t ret_value=SUCCEED; /* Return value */
FUNC_ENTER_NOINIT(H5S_operate_hyperslab);
@@ -5385,6 +5861,41 @@ H5S_operate_hyperslab (H5S_t *result, H5S_hyper_span_info_t *spans1, H5S_seloper
H5S_hyper_free_span_info(a_and_b);
if(b_not_a)
H5S_hyper_free_span_info(b_not_a);
+
+ /* Check if the resulting hyperslab span tree is empty */
+ if(space->select.sel_info.hslab.span_lst==NULL) {
+ H5S_hyper_span_info_t *spans; /* Empty hyperslab span tree */
+
+ /* Sanity check */
+ assert(space->select.num_elem==0);
+
+ /* Allocate a span info node */
+ if((spans = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL)
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "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 */
+ else {
+ /* Check if the resulting hyperslab span tree can be used to re-build
+ * "optimized" start/stride/count/block information.
+ */
+ status=H5S_hyper_can_rebuild(result);
+ if(status<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't check for rebuilding hyperslab info");
+ if(status>0)
+ if(H5S_hyper_rebuild(result)<0)
+ HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info");
+ } /* end else */
} /* end else */
/* Set selection type */
@@ -5478,9 +5989,11 @@ H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op,
done:
/* Free temporary data structures */
if(tmp_spans!=NULL)
- H5S_hyper_free_span_info(tmp_spans);
+ if(H5S_hyper_free_span_info(tmp_spans)<0)
+ HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans");
if(new_spans!=NULL)
- H5S_hyper_free_span_info(new_spans);
+ if(H5S_hyper_free_span_info(new_spans)<0)
+ HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans");
FUNC_LEAVE_NOAPI(ret_value);
} /* end H5S_generate_hyperslab() */