From 4d8f148d0953939baed118399fffe6db05b3a98e Mon Sep 17 00:00:00 2001 From: Quincey Koziol Date: Wed, 4 Jun 2003 10:45:11 -0500 Subject: [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 --- src/H5Sall.c | 158 ++++++++-- src/H5Shyper.c | 601 +++++++++++++++++++++++++++++++++++--- src/H5Snone.c | 147 ++++++++-- src/H5Spkg.h | 33 +-- src/H5Spoint.c | 164 ++++++++--- src/H5Sprivate.h | 13 +- test/tselect.c | 870 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 7 files changed, 1823 insertions(+), 163 deletions(-) diff --git a/src/H5Sall.c b/src/H5Sall.c index 08dc8d3..ea6d6b1 100644 --- a/src/H5Sall.c +++ b/src/H5Sall.c @@ -27,11 +27,22 @@ #include "H5Spkg.h" /* Dataspace functions */ #include "H5Vprivate.h" /* Vector functions */ -/* Interface initialization */ +/* Pablo mask */ #define PABLO_MASK H5Sall_mask + +/* Interface initialization */ #define INTERFACE_INIT NULL static int interface_initialize_g = 0; +/* Static function prototypes */ +static herr_t H5S_all_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); +static herr_t H5S_all_iter_block(const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end); +static hsize_t H5S_all_iter_nelmts(const H5S_sel_iter_t *iter); +static htri_t H5S_all_iter_has_next_block(const H5S_sel_iter_t *iter); +static herr_t H5S_all_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); +static herr_t H5S_all_iter_next_block(H5S_sel_iter_t *sel_iter); +static herr_t H5S_all_iter_release(H5S_sel_iter_t *sel_iter); + /*------------------------------------------------------------------------- * Function: H5S_all_iter_init @@ -66,8 +77,11 @@ H5S_all_iter_init (H5S_sel_iter_t *iter, const H5S_t *space, size_t UNUSED elmt_ /* Initialize methods for selection iterator */ iter->iter_coords=H5S_all_iter_coords; + iter->iter_block=H5S_all_iter_block; iter->iter_nelmts=H5S_all_iter_nelmts; + iter->iter_has_next_block=H5S_all_iter_has_next_block; iter->iter_next=H5S_all_iter_next; + iter->iter_next_block=H5S_all_iter_next_block; iter->iter_release=H5S_all_iter_release; done: @@ -90,12 +104,12 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5S_all_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords) { herr_t ret_value=SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(H5S_all_iter_coords, FAIL); + FUNC_ENTER_NOINIT(H5S_all_iter_coords); /* Check args */ assert (iter); @@ -111,6 +125,46 @@ done: /*------------------------------------------------------------------------- + * Function: H5S_all_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 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_all_iter_block (const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end) +{ + unsigned u; /* Local index variable */ + + FUNC_ENTER_NOINIT(H5S_all_iter_block); + + /* Check args */ + assert (iter); + assert (start); + assert (end); + + /* Get the start of the 'all' block */ + /* (Always '0' coordinates for now) */ + HDmemset(start,0,sizeof(hssize_t)*iter->rank); + + /* Compute the end of the 'all' block */ + /* (Always size of the extent for now) */ + for(u=0; urank; u++) + end[u]=iter->dims[u]-1; + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* H5S_all_iter_coords() */ + + +/*------------------------------------------------------------------------- * Function: H5S_all_iter_nelmts * * Purpose: Return number of elements left to process in iterator @@ -124,21 +178,15 @@ done: * *------------------------------------------------------------------------- */ -hsize_t +static hsize_t H5S_all_iter_nelmts (const H5S_sel_iter_t *iter) { - hsize_t ret_value; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_all_iter_nelmts, 0); + FUNC_ENTER_NOINIT(H5S_all_iter_nelmts); /* Check args */ assert (iter); - /* Set return value */ - ret_value=iter->elmt_left; - -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(iter->elmt_left); } /* H5S_all_iter_nelmts() */ @@ -146,6 +194,35 @@ done: NAME H5S_all_iter_next PURPOSE + Check if there is another block left in the current iterator + USAGE + htri_t H5S_all_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_all_iter_has_next_block (const H5S_sel_iter_t UNUSED *iter) +{ + FUNC_ENTER_NOINIT(H5S_all_iter_has_next_block); + + /* Check args */ + assert (iter); + + FUNC_LEAVE_NOAPI(FALSE); +} /* H5S_all_iter_has_next_block() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_all_iter_next + PURPOSE Increment selection iterator USAGE herr_t H5S_all_iter_next(iter, nelem) @@ -160,12 +237,10 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +static herr_t H5S_all_iter_next(H5S_sel_iter_t *iter, size_t nelem) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_all_iter_next, FAIL); + FUNC_ENTER_NOINIT(H5S_all_iter_next); /* Check args */ assert (iter); @@ -174,13 +249,41 @@ H5S_all_iter_next(H5S_sel_iter_t *iter, size_t nelem) /* Increment the iterator */ iter->u.all.offset+=nelem; -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_all_iter_next() */ /*-------------------------------------------------------------------------- NAME + H5S_all_iter_next_block + PURPOSE + Increment selection iterator to next block + USAGE + herr_t H5S_all_iter_next_block(iter) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Advance selection iterator to the next block in the selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_all_iter_next_block(H5S_sel_iter_t UNUSED *iter) +{ + FUNC_ENTER_NOINIT(H5S_all_iter_next_block); + + /* Check args */ + assert (iter); + + FUNC_LEAVE_NOAPI(FAIL); +} /* H5S_all_iter_next_block() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_all_iter_release PURPOSE Release "all" selection iterator information for a dataspace @@ -196,18 +299,15 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +static herr_t H5S_all_iter_release (H5S_sel_iter_t UNUSED * iter) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_all_iter_release, FAIL); + FUNC_ENTER_NOINIT(H5S_all_iter_release); /* Check args */ assert (iter); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_all_iter_release() */ @@ -436,10 +536,10 @@ done: PURPOSE Gets the bounding box containing the selection. USAGE - herr_t H5S_all_bounds(space, hsize_t *start, hsize_t *end) + herr_t H5S_all_bounds(space, start, end) H5S_t *space; IN: Dataspace pointer of selection to query - hsize_t *start; OUT: Starting coordinate of bounding box - hsize_t *end; OUT: Opposite coordinate of bounding box + hssize_t *start; OUT: Starting coordinate of bounding box + hssize_t *end; OUT: Opposite coordinate of bounding box RETURNS Non-negative on success, negative on failure DESCRIPTION @@ -456,7 +556,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) +H5S_all_bounds(const H5S_t *space, hssize_t *start, hssize_t *end) { int rank; /* Dataspace rank */ int i; /* index variable */ @@ -474,7 +574,7 @@ H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) /* Just copy over the complete extent */ for(i=0; iextent.u.simple.size[i]-1; + H5_ASSIGN_OVERFLOW(end[i],space->extent.u.simple.size[i]-1,hsize_t,hssize_t); } /* end for */ done: 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_dimiter_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; urank; u++) + end[u]=(start[u]+iter->u.hyp.diminfo[u].block)-1; + } /* end if */ + else { + /* Copy the start of the block */ + for(u=0; urank; u++) + start[u]=iter->u.hyp.span[u]->low; + + /* Copy the end of the block */ + for(u=0; urank; 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; urank; 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; urank; 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_rankrank) { + /* 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; uu.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]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_dimdown); + 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])low+offset[rank])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; ilow,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_dimextent.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() */ diff --git a/src/H5Snone.c b/src/H5Snone.c index a1d6127..7d1aa12 100644 --- a/src/H5Snone.c +++ b/src/H5Snone.c @@ -28,11 +28,22 @@ #include "H5Vprivate.h" #include "H5Dprivate.h" -/* Interface initialization */ +/* Pablo mask */ #define PABLO_MASK H5Snone_mask + +/* Interface initialization */ #define INTERFACE_INIT NULL static int interface_initialize_g = 0; +/* Static function prototypes */ +static herr_t H5S_none_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); +static herr_t H5S_none_iter_block(const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end); +static hsize_t H5S_none_iter_nelmts(const H5S_sel_iter_t *iter); +static htri_t H5S_none_iter_has_next_block(const H5S_sel_iter_t *iter); +static herr_t H5S_none_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); +static herr_t H5S_none_iter_next_block(H5S_sel_iter_t *sel_iter); +static herr_t H5S_none_iter_release(H5S_sel_iter_t *sel_iter); + /*------------------------------------------------------------------------- * Function: H5S_none_iter_init @@ -61,8 +72,11 @@ H5S_none_iter_init (H5S_sel_iter_t *iter, const H5S_t UNUSED *space, size_t UNUS /* Initialize methods for selection iterator */ iter->iter_coords=H5S_none_iter_coords; + iter->iter_block=H5S_none_iter_block; iter->iter_nelmts=H5S_none_iter_nelmts; + iter->iter_has_next_block=H5S_none_iter_has_next_block; iter->iter_next=H5S_none_iter_next; + iter->iter_next_block=H5S_none_iter_next_block; iter->iter_release=H5S_none_iter_release; done: @@ -85,23 +99,49 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5S_none_iter_coords (const H5S_sel_iter_t UNUSED *iter, hssize_t UNUSED *coords) { - herr_t ret_value=FAIL; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_none_iter_coords, FAIL); + FUNC_ENTER_NOINIT(H5S_none_iter_coords); /* Check args */ assert (iter); assert (coords); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(FAIL); } /* H5S_none_iter_coords() */ /*------------------------------------------------------------------------- + * Function: H5S_none_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 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_none_iter_block (const H5S_sel_iter_t UNUSED *iter, hssize_t UNUSED *start, hssize_t UNUSED *end) +{ + FUNC_ENTER_NOINIT(H5S_none_iter_block); + + /* Check args */ + assert (iter); + assert (start); + assert (end); + + FUNC_LEAVE_NOAPI(FAIL); +} /* H5S_none_iter_block() */ + + +/*------------------------------------------------------------------------- * Function: H5S_none_iter_nelmts * * Purpose: Return number of elements left to process in iterator @@ -115,23 +155,49 @@ done: * *------------------------------------------------------------------------- */ -hsize_t +static hsize_t H5S_none_iter_nelmts (const H5S_sel_iter_t UNUSED *iter) { - hsize_t ret_value=0; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_none_iter_nelmts, 0); + FUNC_ENTER_NOINIT(H5S_none_iter_nelmts); /* Check args */ assert (iter); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(0); } /* H5S_none_iter_nelmts() */ /*-------------------------------------------------------------------------- NAME + H5S_none_iter_has_next_block + PURPOSE + Check if there is another block left in the current iterator + USAGE + htri_t H5S_none_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_none_iter_has_next_block(const H5S_sel_iter_t UNUSED *iter) +{ + FUNC_ENTER_NOINIT(H5S_none_iter_has_next_block); + + /* Check args */ + assert (iter); + + FUNC_LEAVE_NOAPI(FAIL); +} /* H5S_none_iter_has_next_block() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_none_iter_next PURPOSE Increment selection iterator @@ -148,24 +214,50 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +static herr_t H5S_none_iter_next(H5S_sel_iter_t UNUSED *iter, size_t UNUSED nelem) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_none_iter_next, FAIL); + FUNC_ENTER_NOINIT(H5S_none_iter_next); /* Check args */ assert (iter); assert (nelem>0); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_none_iter_next() */ /*-------------------------------------------------------------------------- NAME + H5S_none_iter_next_block + PURPOSE + Increment selection iterator to next block + USAGE + herr_t H5S_none_iter_next(iter) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Advance selection iterator to the next block in the selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_none_iter_next_block(H5S_sel_iter_t UNUSED *iter) +{ + FUNC_ENTER_NOINIT(H5S_none_iter_next); + + /* Check args */ + assert (iter); + + FUNC_LEAVE_NOAPI(FAIL); +} /* H5S_none_iter_next_block() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_none_iter_release PURPOSE Release "none" selection iterator information for a dataspace @@ -181,18 +273,15 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +static herr_t H5S_none_iter_release (H5S_sel_iter_t UNUSED * iter) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_none_iter_release, FAIL); + FUNC_ENTER_NOINIT(H5S_none_iter_release); /* Check args */ assert (iter); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_none_iter_release() */ @@ -416,10 +505,10 @@ done: PURPOSE Gets the bounding box containing the selection. USAGE - herr_t H5S_none_bounds(space, hsize_t *start, hsize_t *end) + herr_t H5S_none_bounds(space, start, end) H5S_t *space; IN: Dataspace pointer of selection to query - hsize_t *start; OUT: Starting coordinate of bounding box - hsize_t *end; OUT: Opposite coordinate of bounding box + hssize_t *start; OUT: Starting coordinate of bounding box + hssize_t *end; OUT: Opposite coordinate of bounding box RETURNS Non-negative on success, negative on failure DESCRIPTION @@ -436,7 +525,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_none_bounds(const H5S_t UNUSED *space, hsize_t UNUSED *start, hsize_t UNUSED *end) +H5S_none_bounds(const H5S_t UNUSED *space, hssize_t UNUSED *start, hssize_t UNUSED *end) { herr_t ret_value=FAIL; /* Return value */ diff --git a/src/H5Spkg.h b/src/H5Spkg.h index 9d10460..e23cda9 100644 --- a/src/H5Spkg.h +++ b/src/H5Spkg.h @@ -139,7 +139,7 @@ typedef hssize_t (*H5S_sel_serial_size_func_t)(const H5S_t *space); /* Method to store current selection in "serialized" form (a byte sequence suitable for storing on disk) */ typedef herr_t (*H5S_sel_serialize_func_t)(const H5S_t *space, uint8_t *buf); /* Method to determine to smallest n-D bounding box containing the current selection */ -typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hsize_t *start, hsize_t *end); +typedef herr_t (*H5S_sel_bounds_func_t)(const H5S_t *space, hssize_t *start, hssize_t *end); /* Method to determine if current selection is contiguous */ typedef htri_t (*H5S_sel_is_contiguous_func_t)(const H5S_t *space); /* Method to determine if current selection is a single block */ @@ -184,15 +184,9 @@ H5_DLL herr_t H5S_release_simple(H5S_simple_t *simple); H5_DLL herr_t H5S_extent_copy(H5S_extent_t *dst, const H5S_extent_t *src); /* Operations on selections */ -H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src); -H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2); /* Point selection iterator functions */ H5_DLL herr_t H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); -H5_DLL herr_t H5S_point_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); -H5_DLL hsize_t H5S_point_iter_nelmts(const H5S_sel_iter_t *iter); -H5_DLL herr_t H5S_point_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); -H5_DLL herr_t H5S_point_iter_release(H5S_sel_iter_t *sel_iter); /* Point selection functions */ H5_DLL herr_t H5S_point_release(H5S_t *space); @@ -202,7 +196,7 @@ H5_DLL htri_t H5S_point_is_valid(const H5S_t *space); H5_DLL hssize_t H5S_point_serial_size(const H5S_t *space); H5_DLL herr_t H5S_point_serialize(const H5S_t *space, uint8_t *buf); H5_DLL herr_t H5S_point_deserialize(H5S_t *space, const uint8_t *buf); -H5_DLL herr_t H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_point_bounds(const H5S_t *space, hssize_t *start, hssize_t *end); H5_DLL htri_t H5S_point_is_contiguous(const H5S_t *space); H5_DLL htri_t H5S_point_is_single(const H5S_t *space); H5_DLL htri_t H5S_point_is_regular(const H5S_t *space); @@ -212,10 +206,6 @@ H5_DLL herr_t H5S_point_get_seq_list(const H5S_t *space, unsigned flags, /* "All" selection iterator functions */ H5_DLL herr_t H5S_all_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); -H5_DLL herr_t H5S_all_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); -H5_DLL hsize_t H5S_all_iter_nelmts(const H5S_sel_iter_t *iter); -H5_DLL herr_t H5S_all_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); -H5_DLL herr_t H5S_all_iter_release(H5S_sel_iter_t *sel_iter); /* "All" selection functions */ H5_DLL herr_t H5S_all_release(H5S_t *space); @@ -224,7 +214,7 @@ H5_DLL htri_t H5S_all_is_valid(const H5S_t *space); H5_DLL hssize_t H5S_all_serial_size(const H5S_t *space); H5_DLL herr_t H5S_all_serialize(const H5S_t *space, uint8_t *buf); H5_DLL herr_t H5S_all_deserialize(H5S_t *space, const uint8_t *buf); -H5_DLL herr_t H5S_all_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_all_bounds(const H5S_t *space, hssize_t *start, hssize_t *end); H5_DLL htri_t H5S_all_is_contiguous(const H5S_t *space); H5_DLL htri_t H5S_all_is_single(const H5S_t *space); H5_DLL htri_t H5S_all_is_regular(const H5S_t *space); @@ -234,10 +224,6 @@ H5_DLL herr_t H5S_all_get_seq_list(const H5S_t *space, unsigned flags, /* Hyperslab selection iterator functions */ H5_DLL herr_t H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); -H5_DLL herr_t H5S_hyper_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); -H5_DLL hsize_t H5S_hyper_iter_nelmts(const H5S_sel_iter_t *iter); -H5_DLL herr_t H5S_hyper_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); -H5_DLL herr_t H5S_hyper_iter_release(H5S_sel_iter_t *sel_iter); /* Hyperslab selection functions */ H5_DLL herr_t H5S_hyper_release(H5S_t *space); @@ -247,7 +233,7 @@ H5_DLL htri_t H5S_hyper_is_valid(const H5S_t *space); H5_DLL hssize_t H5S_hyper_serial_size(const H5S_t *space); H5_DLL herr_t H5S_hyper_serialize(const H5S_t *space, uint8_t *buf); H5_DLL herr_t H5S_hyper_deserialize(H5S_t *space, const uint8_t *buf); -H5_DLL herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_hyper_bounds(const H5S_t *space, hssize_t *start, hssize_t *end); H5_DLL htri_t H5S_hyper_is_contiguous(const H5S_t *space); H5_DLL htri_t H5S_hyper_is_single(const H5S_t *space); H5_DLL htri_t H5S_hyper_is_regular(const H5S_t *space); @@ -257,10 +243,6 @@ H5_DLL herr_t H5S_hyper_get_seq_list(const H5S_t *space, unsigned flags, /* "None" selection iterator functions */ H5_DLL herr_t H5S_none_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t elmt_size); -H5_DLL herr_t H5S_none_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); -H5_DLL hsize_t H5S_none_iter_nelmts(const H5S_sel_iter_t *iter); -H5_DLL herr_t H5S_none_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); -H5_DLL herr_t H5S_none_iter_release(H5S_sel_iter_t *sel_iter); /* "None" selection functions */ H5_DLL herr_t H5S_none_release(H5S_t *space); @@ -269,7 +251,7 @@ H5_DLL htri_t H5S_none_is_valid(const H5S_t *space); H5_DLL hssize_t H5S_none_serial_size(const H5S_t *space); H5_DLL herr_t H5S_none_serialize(const H5S_t *space, uint8_t *buf); H5_DLL herr_t H5S_none_deserialize(H5S_t *space, const uint8_t *buf); -H5_DLL herr_t H5S_none_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_none_bounds(const H5S_t *space, hssize_t *start, hssize_t *end); H5_DLL htri_t H5S_none_is_contiguous(const H5S_t *space); H5_DLL htri_t H5S_none_is_single(const H5S_t *space); H5_DLL htri_t H5S_none_is_regular(const H5S_t *space); @@ -303,4 +285,9 @@ H5_DLL htri_t H5S_mpio_opt_possible(const H5S_t *mem_space, #endif /* H5_HAVE_PARALLEL */ +/* Testing functions */ +#ifdef H5S_TESTING +H5_DLL htri_t H5S_select_shape_same_test(hid_t sid1, hid_t sid2); +#endif /* H5S_TESTING */ + #endif /*_H5Spkg_H*/ diff --git a/src/H5Spoint.c b/src/H5Spoint.c index 7c45a11..8da8884 100644 --- a/src/H5Spoint.c +++ b/src/H5Spoint.c @@ -29,14 +29,23 @@ #include "H5Spkg.h" /* Dataspace functions */ #include "H5Vprivate.h" /* Vector functions */ -/* Interface initialization */ +/* Pablo mask */ #define PABLO_MASK H5Spoint_mask + +/* Interface initialization */ #define INTERFACE_INIT NULL static int interface_initialize_g = 0; /* Static function prototypes */ static herr_t H5S_select_elements (H5S_t *space, H5S_seloper_t op, size_t num_elem, const hssize_t **coord); +static herr_t H5S_point_iter_coords(const H5S_sel_iter_t *iter, hssize_t *coords); +static herr_t H5S_point_iter_block(const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end); +static hsize_t H5S_point_iter_nelmts(const H5S_sel_iter_t *iter); +static htri_t H5S_point_iter_has_next_block(const H5S_sel_iter_t *iter); +static herr_t H5S_point_iter_next(H5S_sel_iter_t *sel_iter, size_t nelem); +static herr_t H5S_point_iter_next_block(H5S_sel_iter_t *sel_iter); +static herr_t H5S_point_iter_release(H5S_sel_iter_t *sel_iter); /* Declare a free list to manage the H5S_pnt_node_t struct */ H5FL_DEFINE_STATIC(H5S_pnt_node_t); @@ -78,8 +87,11 @@ H5S_point_iter_init(H5S_sel_iter_t *iter, const H5S_t *space, size_t UNUSED elmt /* Initialize methods for selection iterator */ iter->iter_coords=H5S_point_iter_coords; + iter->iter_block=H5S_point_iter_block; iter->iter_nelmts=H5S_point_iter_nelmts; + iter->iter_has_next_block=H5S_point_iter_has_next_block; iter->iter_next=H5S_point_iter_next; + iter->iter_next_block=H5S_point_iter_next_block; iter->iter_release=H5S_point_iter_release; done: @@ -102,12 +114,10 @@ done: * *------------------------------------------------------------------------- */ -herr_t +static herr_t H5S_point_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_point_iter_coords, FAIL); + FUNC_ENTER_NOINIT(H5S_point_iter_coords); /* Check args */ assert (iter); @@ -116,12 +126,44 @@ H5S_point_iter_coords (const H5S_sel_iter_t *iter, hssize_t *coords) /* Copy the offset of the current point */ HDmemcpy(coords,iter->u.pnt.curr->pnt,sizeof(hssize_t)*iter->rank); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_point_iter_coords() */ /*------------------------------------------------------------------------- + * Function: H5S_point_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 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_point_iter_block (const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end) +{ + FUNC_ENTER_NOINIT(H5S_point_iter_block); + + /* Check args */ + assert (iter); + assert (start); + assert (end); + + /* Copy the current point as a block */ + HDmemcpy(start,iter->u.pnt.curr->pnt,sizeof(hssize_t)*iter->rank); + HDmemcpy(end,iter->u.pnt.curr->pnt,sizeof(hssize_t)*iter->rank); + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* H5S_point_iter_block() */ + + +/*------------------------------------------------------------------------- * Function: H5S_point_iter_nelmts * * Purpose: Return number of elements left to process in iterator @@ -135,22 +177,52 @@ done: * *------------------------------------------------------------------------- */ -hsize_t +static hsize_t H5S_point_iter_nelmts (const H5S_sel_iter_t *iter) { - hsize_t ret_value; /* Return value */ + FUNC_ENTER_NOINIT(H5S_point_iter_nelmts); - FUNC_ENTER_NOAPI(H5S_point_iter_nelmts, 0); + /* Check args */ + assert (iter); + + FUNC_LEAVE_NOAPI(iter->elmt_left); +} /* H5S_point_iter_nelmts() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_point_iter_has_next_block + PURPOSE + Check if there is another block left in the current iterator + USAGE + htri_t H5S_point_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_point_iter_has_next_block(const H5S_sel_iter_t *iter) +{ + htri_t ret_value=TRUE; /* Return value */ + + FUNC_ENTER_NOINIT(H5S_point_iter_has_next_block); /* Check args */ assert (iter); - /* Set return value */ - ret_value=iter->elmt_left; + /* Check if there is another point in the list */ + if(iter->u.pnt.curr->next==NULL) + HGOTO_DONE(FALSE); done: FUNC_LEAVE_NOAPI(ret_value); -} /* H5S_point_iter_nelmts() */ +} /* H5S_point_iter_has_next_block() */ /*-------------------------------------------------------------------------- @@ -171,12 +243,10 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +static herr_t H5S_point_iter_next(H5S_sel_iter_t *iter, size_t nelem) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_point_iter_next, FAIL); + FUNC_ENTER_NOINIT(H5S_point_iter_next); /* Check args */ assert (iter); @@ -188,13 +258,44 @@ H5S_point_iter_next(H5S_sel_iter_t *iter, size_t nelem) nelem--; } /* end while */ -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_point_iter_next() */ /*-------------------------------------------------------------------------- NAME + H5S_point_iter_next_block + PURPOSE + Increment selection iterator to next block + USAGE + herr_t H5S_point_iter_next_block(iter) + H5S_sel_iter_t *iter; IN: Pointer to selection iterator + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Advance selection iterator to the next block in the selection. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_point_iter_next_block(H5S_sel_iter_t *iter) +{ + FUNC_ENTER_NOINIT(H5S_point_iter_next_block); + + /* Check args */ + assert (iter); + + /* Increment the iterator */ + iter->u.pnt.curr=iter->u.pnt.curr->next; + + FUNC_LEAVE_NOAPI(SUCCEED); +} /* H5S_point_iter_next_block() */ + + +/*-------------------------------------------------------------------------- + NAME H5S_point_iter_release PURPOSE Release point selection iterator information for a dataspace @@ -210,18 +311,15 @@ done: EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ -herr_t +static herr_t H5S_point_iter_release (H5S_sel_iter_t UNUSED * iter) { - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(H5S_point_iter_release, FAIL); + FUNC_ENTER_NOINIT(H5S_point_iter_release); /* Check args */ assert (iter); -done: - FUNC_LEAVE_NOAPI(ret_value); + FUNC_LEAVE_NOAPI(SUCCEED); } /* H5S_point_iter_release() */ @@ -962,10 +1060,10 @@ done: PURPOSE Gets the bounding box containing the selection. USAGE - herr_t H5S_point_bounds(space, hsize_t *start, hsize_t *end) + herr_t H5S_point_bounds(space, start, end) H5S_t *space; IN: Dataspace pointer of selection to query - hsize_t *start; OUT: Starting coordinate of bounding box - hsize_t *end; OUT: Opposite coordinate of bounding box + hssize_t *start; OUT: Starting coordinate of bounding box + hssize_t *end; OUT: Opposite coordinate of bounding box RETURNS Non-negative on success, negative on failure DESCRIPTION @@ -983,7 +1081,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) +H5S_point_bounds(const H5S_t *space, hssize_t *start, hssize_t *end) { H5S_pnt_node_t *node; /* Point node */ int rank; /* Dataspace rank */ @@ -1001,17 +1099,17 @@ H5S_point_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) /* Set the start and end arrays up */ for(i=0; iselect.sel_info.pnt_lst->head; while(node!=NULL) { for(i=0; i(hsize_t)(node->pnt[i]+space->select.offset[i])) + if(start[i]>(node->pnt[i]+space->select.offset[i])) start[i]=node->pnt[i]+space->select.offset[i]; - if(end[i]<(hsize_t)(node->pnt[i]+space->select.offset[i])) + if(end[i]<(node->pnt[i]+space->select.offset[i])) end[i]=node->pnt[i]+space->select.offset[i]; } /* end for */ node=node->next; diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index 4e6eda7..c05df2a 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -79,10 +79,16 @@ typedef struct H5S_sel_iter_t H5S_sel_iter_t; /* Method to retrieve the current coordinates of iterator for current selection */ typedef herr_t (*H5S_sel_iter_coords_func_t)(const H5S_sel_iter_t *iter, hssize_t *coords); +/* Method to retrieve the current block of iterator for current selection */ +typedef herr_t (*H5S_sel_iter_block_func_t)(const H5S_sel_iter_t *iter, hssize_t *start, hssize_t *end); /* Method to determine number of elements left in iterator for current selection */ typedef hsize_t (*H5S_sel_iter_nelmts_func_t)(const H5S_sel_iter_t *iter); +/* Method to determine if there are more blocks left in the current selection */ +typedef htri_t (*H5S_sel_iter_has_next_block_func_t)(const H5S_sel_iter_t *iter); /* Method to move selection iterator to the next element in the selection */ typedef herr_t (*H5S_sel_iter_next_func_t)(H5S_sel_iter_t *iter, size_t nelem); +/* Method to move selection iterator to the next block in the selection */ +typedef herr_t (*H5S_sel_iter_next_block_func_t)(H5S_sel_iter_t *iter); /* Method to release iterator for current selection */ typedef herr_t (*H5S_sel_iter_release_func_t)(H5S_sel_iter_t *iter); @@ -102,8 +108,11 @@ struct H5S_sel_iter_t { /* Methods on selections */ H5S_sel_iter_coords_func_t iter_coords; /* Method to retrieve the current coordinates of iterator for current selection */ + H5S_sel_iter_block_func_t iter_block; /* Method to retrieve the current block of iterator for current selection */ H5S_sel_iter_nelmts_func_t iter_nelmts; /* Method to determine number of elements left in iterator for current selection */ + H5S_sel_iter_has_next_block_func_t iter_has_next_block; /* Method to query if there is another block left in the selection */ H5S_sel_iter_next_func_t iter_next; /* Method to move selection iterator to the next element in the selection */ + H5S_sel_iter_next_block_func_t iter_next_block; /* Method to move selection iterator to the next block in the selection */ H5S_sel_iter_release_func_t iter_release; /* Method to release iterator for current selection */ }; @@ -205,8 +214,10 @@ H5_DLL herr_t H5S_select_write(H5F_t *f, struct H5O_layout_t *layout, const void *buf/*out*/); H5_DLL htri_t H5S_select_valid(const H5S_t *space); H5_DLL hssize_t H5S_get_select_npoints(const H5S_t *space); -H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hsize_t *start, hsize_t *end); +H5_DLL herr_t H5S_get_select_bounds(const H5S_t *space, hssize_t *start, hssize_t *end); H5_DLL herr_t H5S_select_offset(H5S_t *space, const hssize_t *offset); +H5_DLL herr_t H5S_select_copy(H5S_t *dst, const H5S_t *src); +H5_DLL htri_t H5S_select_shape_same(const H5S_t *space1, const H5S_t *space2); H5_DLL herr_t H5S_select_release(H5S_t *ds); H5_DLL herr_t H5S_select_all(H5S_t *space, unsigned rel_prev); H5_DLL herr_t H5S_select_none(H5S_t *space); diff --git a/test/tselect.c b/test/tselect.c index 598df68..e3b72ec 100644 --- a/test/tselect.c +++ b/test/tselect.c @@ -22,9 +22,14 @@ * *************************************************************/ -#include "testhdf5.h" +#define H5S_PACKAGE /*suppress error about including H5Spkg */ + +/* Define this macro to indicate that the testing APIs should be available */ +#define H5S_TESTING +#include "testhdf5.h" #include "hdf5.h" +#include "H5Spkg.h" /* Dataspaces */ #define FILENAME "tselect.h5" @@ -91,6 +96,12 @@ #define SPACE8_DIM3 17 #define SPACE8_DIM4 19 +/* Another 2-D dataset with easy dimension sizes */ +#define SPACE9_NAME "Space9" +#define SPACE9_RANK 2 +#define SPACE9_DIM1 12 +#define SPACE9_DIM2 12 + /* Element selection information */ #define POINT1_NPOINTS 10 @@ -5218,10 +5229,7 @@ test_scalar_select(void) static void test_scalar_select2(void) { - hid_t fid1; /* HDF5 File IDs */ - hid_t dataset; /* Dataset ID */ hid_t sid; /* Dataspace ID */ - hsize_t dims2[] = {SPACE7_DIM1, SPACE7_DIM2}; hssize_t coord1[1]; /* Coordinates for point selection */ hssize_t start[1]; /* Hyperslab start */ hsize_t count[1]; /* Hyperslab block count */ @@ -5262,7 +5270,859 @@ test_scalar_select2(void) CHECK(ret, FAIL, "H5Sclose"); } /* test_scalar_select2() */ +/**************************************************************** +** +** test_shape_same(): Tests selections on dataspace, verify that +** "shape same" routine is working correctly. +** +****************************************************************/ +static void +test_shape_same(void) +{ + hid_t all_sid; /* Dataspace ID with "all" selection */ + hid_t none_sid; /* Dataspace ID with "none" selection */ + hid_t single_pt_sid; /* Dataspace ID with single point selection */ + hid_t mult_pt_sid; /* Dataspace ID with multiple point selection */ + hid_t single_hyper_sid; /* Dataspace ID with single block hyperslab selection */ + hid_t single_hyper_all_sid; /* Dataspace ID with single block hyperslab + * selection that is the entire dataspace + */ + hid_t single_hyper_pt_sid; /* Dataspace ID with single block hyperslab + * selection that is the same as the single + * point selection + */ + hid_t regular_hyper_sid; /* Dataspace ID with regular hyperslab selection */ + hid_t irreg_hyper_sid; /* Dataspace ID with irregular hyperslab selection */ + hid_t none_hyper_sid; /* Dataspace ID with "no hyperslabs" selection */ + hid_t tmp_sid; /* Temporary dataspace ID */ + hsize_t dims[] = {SPACE9_DIM1, SPACE9_DIM2}; + hssize_t coord1[1][SPACE2_RANK]; /* Coordinates for single point selection */ + hssize_t coord2[SPACE9_DIM2][SPACE9_RANK]; /* Coordinates for multiple point selection */ + hssize_t start[SPACE9_RANK]; /* Hyperslab start */ + hsize_t stride[SPACE9_RANK]; /* Hyperslab stride */ + hsize_t count[SPACE9_RANK]; /* Hyperslab block count */ + hsize_t block[SPACE9_RANK]; /* Hyperslab block size */ + unsigned u,v; /* Local index variables */ + htri_t check; /* Shape comparison return value */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(6, ("Testing Same Shape Comparisons\n")); + assert(SPACE9_DIM2>=POINT1_NPOINTS); + + /* Create dataspace for "all" selection */ + all_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(all_sid, FAIL, "H5Screate_simple"); + + /* Select entire extent for dataspace */ + ret = H5Sselect_all(all_sid); + CHECK(ret, FAIL, "H5Sselect_all"); + + /* Create dataspace for "none" selection */ + none_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(none_sid, FAIL, "H5Screate_simple"); + + /* Un-Select entire extent for dataspace */ + ret = H5Sselect_none(none_sid); + CHECK(ret, FAIL, "H5Sselect_none"); + + /* Create dataspace for single point selection */ + single_pt_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(single_pt_sid, FAIL, "H5Screate_simple"); + + /* Select sequence of ten points for multiple point selection */ + coord1[0][0]=2; coord1[0][1]=2; + ret = H5Sselect_elements(single_pt_sid,H5S_SELECT_SET,1,(const hssize_t **)coord1); + CHECK(ret, FAIL, "H5Sselect_elements"); + + /* Create dataspace for multiple point selection */ + mult_pt_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(mult_pt_sid, FAIL, "H5Screate_simple"); + + /* Select sequence of ten points for multiple point selection */ + coord2[0][0]=2; coord2[0][1]=2; + coord2[1][0]=7; coord2[1][1]=2; + coord2[2][0]=1; coord2[2][1]=4; + coord2[3][0]=2; coord2[3][1]=6; + coord2[4][0]=0; coord2[4][1]=8; + coord2[5][0]=3; coord2[5][1]=2; + coord2[6][0]=4; coord2[6][1]=4; + coord2[7][0]=1; coord2[7][1]=0; + coord2[8][0]=5; coord2[8][1]=1; + coord2[9][0]=9; coord2[9][1]=3; + ret = H5Sselect_elements(mult_pt_sid,H5S_SELECT_SET,POINT1_NPOINTS,(const hssize_t **)coord2); + CHECK(ret, FAIL, "H5Sselect_elements"); + + /* Create dataspace for single hyperslab selection */ + single_hyper_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(single_hyper_sid, FAIL, "H5Screate_simple"); + + /* Select 10x10 hyperslab for single hyperslab selection */ + start[0]=1; start[1]=1; + stride[0]=1; stride[1]=1; + count[0]=1; count[1]=1; + block[0]=(SPACE9_DIM1-2); block[1]=(SPACE9_DIM2-2); + ret = H5Sselect_hyperslab(single_hyper_sid,H5S_SELECT_SET,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Create dataspace for single hyperslab selection with entire extent selected */ + single_hyper_all_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(single_hyper_all_sid, FAIL, "H5Screate_simple"); + + /* Select entire extent for hyperslab selection */ + start[0]=0; start[1]=0; + stride[0]=1; stride[1]=1; + count[0]=1; count[1]=1; + block[0]=SPACE9_DIM1; block[1]=SPACE9_DIM2; + ret = H5Sselect_hyperslab(single_hyper_all_sid,H5S_SELECT_SET,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Create dataspace for single hyperslab selection with single point selected */ + single_hyper_pt_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(single_hyper_pt_sid, FAIL, "H5Screate_simple"); + + /* Select entire extent for hyperslab selection */ + start[0]=2; start[1]=2; + stride[0]=1; stride[1]=1; + count[0]=1; count[1]=1; + block[0]=1; block[1]=1; + ret = H5Sselect_hyperslab(single_hyper_pt_sid,H5S_SELECT_SET,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Create dataspace for regular hyperslab selection */ + regular_hyper_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(regular_hyper_sid, FAIL, "H5Screate_simple"); + + /* Select regular, strided hyperslab selection */ + start[0]=2; start[1]=2; + stride[0]=2; stride[1]=2; + count[0]=5; count[1]=2; + block[0]=1; block[1]=1; + ret = H5Sselect_hyperslab(regular_hyper_sid,H5S_SELECT_SET,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Create dataspace for irregular hyperslab selection */ + irreg_hyper_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(irreg_hyper_sid, FAIL, "H5Screate_simple"); + + /* Create irregular hyperslab selection by OR'ing two blocks together */ + start[0]=2; start[1]=2; + stride[0]=1; stride[1]=1; + count[0]=1; count[1]=1; + block[0]=1; block[1]=1; + ret = H5Sselect_hyperslab(irreg_hyper_sid,H5S_SELECT_SET,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + start[0]=4; start[1]=4; + stride[0]=1; stride[1]=1; + count[0]=1; count[1]=1; + block[0]=3; block[1]=3; + ret = H5Sselect_hyperslab(irreg_hyper_sid,H5S_SELECT_OR,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Create dataspace for "no" hyperslab selection */ + none_hyper_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(none_hyper_sid, FAIL, "H5Screate_simple"); + + /* Create "no" hyperslab selection by XOR'ing same blocks together */ + start[0]=2; start[1]=2; + stride[0]=1; stride[1]=1; + count[0]=1; count[1]=1; + block[0]=1; block[1]=1; + ret = H5Sselect_hyperslab(none_hyper_sid,H5S_SELECT_SET,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + ret = H5Sselect_hyperslab(none_hyper_sid,H5S_SELECT_XOR,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + + /* Compare "all" selection to all the selections created */ + /* Compare against itself */ + check=H5S_select_shape_same_test(all_sid,all_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid=H5Scopy(all_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check=H5S_select_shape_same_test(all_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare against "none" selection */ + check=H5S_select_shape_same_test(all_sid,none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against single point selection */ + check=H5S_select_shape_same_test(all_sid,single_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against multiple point selection */ + check=H5S_select_shape_same_test(all_sid,mult_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "plain" single hyperslab selection */ + check=H5S_select_shape_same_test(all_sid,single_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "all" single hyperslab selection */ + check=H5S_select_shape_same_test(all_sid,single_hyper_all_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check=H5S_select_shape_same_test(all_sid,single_hyper_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check=H5S_select_shape_same_test(all_sid,regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check=H5S_select_shape_same_test(all_sid,irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check=H5S_select_shape_same_test(all_sid,none_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare "none" selection to all the selections created */ + /* Compare against itself */ + check=H5S_select_shape_same_test(none_sid,none_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid=H5Scopy(none_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check=H5S_select_shape_same_test(none_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare against "all" selection */ + check=H5S_select_shape_same_test(none_sid,all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against single point selection */ + check=H5S_select_shape_same_test(none_sid,single_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against multiple point selection */ + check=H5S_select_shape_same_test(none_sid,mult_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "plain" single hyperslab selection */ + check=H5S_select_shape_same_test(none_sid,single_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "all" single hyperslab selection */ + check=H5S_select_shape_same_test(none_sid,single_hyper_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check=H5S_select_shape_same_test(none_sid,single_hyper_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check=H5S_select_shape_same_test(none_sid,regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check=H5S_select_shape_same_test(none_sid,irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check=H5S_select_shape_same_test(none_sid,none_hyper_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare single point selection to all the selections created */ + /* Compare against itself */ + check=H5S_select_shape_same_test(single_pt_sid,single_pt_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid=H5Scopy(single_pt_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check=H5S_select_shape_same_test(single_pt_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare against "all" selection */ + check=H5S_select_shape_same_test(single_pt_sid,all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "none" selection */ + check=H5S_select_shape_same_test(single_pt_sid,none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against multiple point selection */ + check=H5S_select_shape_same_test(single_pt_sid,mult_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "plain" single hyperslab selection */ + check=H5S_select_shape_same_test(single_pt_sid,single_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "all" single hyperslab selection */ + check=H5S_select_shape_same_test(single_pt_sid,single_hyper_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check=H5S_select_shape_same_test(single_pt_sid,single_hyper_pt_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check=H5S_select_shape_same_test(single_pt_sid,regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check=H5S_select_shape_same_test(single_pt_sid,irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check=H5S_select_shape_same_test(single_pt_sid,none_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare multiple point selection to all the selections created */ + /* Compare against itself */ + check=H5S_select_shape_same_test(mult_pt_sid,mult_pt_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid=H5Scopy(mult_pt_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check=H5S_select_shape_same_test(mult_pt_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + /* Compare against "all" selection */ + check=H5S_select_shape_same_test(mult_pt_sid,all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "none" selection */ + check=H5S_select_shape_same_test(mult_pt_sid,none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against single point selection */ + check=H5S_select_shape_same_test(mult_pt_sid,single_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "plain" single hyperslab selection */ + check=H5S_select_shape_same_test(mult_pt_sid,single_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "all" single hyperslab selection */ + check=H5S_select_shape_same_test(mult_pt_sid,single_hyper_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check=H5S_select_shape_same_test(mult_pt_sid,single_hyper_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check=H5S_select_shape_same_test(mult_pt_sid,regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check=H5S_select_shape_same_test(mult_pt_sid,irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check=H5S_select_shape_same_test(mult_pt_sid,none_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare single "normal" hyperslab selection to all the selections created */ + /* Compare against itself */ + check=H5S_select_shape_same_test(single_hyper_sid,single_hyper_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid=H5Scopy(single_hyper_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check=H5S_select_shape_same_test(single_hyper_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare against "all" selection */ + check=H5S_select_shape_same_test(single_hyper_sid,all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "none" selection */ + check=H5S_select_shape_same_test(single_hyper_sid,none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against single point selection */ + check=H5S_select_shape_same_test(single_hyper_sid,single_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against multiple point selection */ + check=H5S_select_shape_same_test(single_hyper_sid,mult_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "all" single hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_sid,single_hyper_all_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_sid,single_hyper_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_sid,regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_sid,irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_sid,none_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + +#ifdef NOT_YET +/* In theory, these two selections are the same shape, but the + * H5S_select_shape_same() routine is just not this sophisticated yet and it + * would take too much effort to make this work. The worst case is that the + * non-optimized chunk mapping routines will be invoked instead of the more + * optimized routines, so this only hurts performance, not correctness + */ + /* Construct point selection which matches "plain" hyperslab selection */ + /* Create dataspace for point selection */ + tmp_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(tmp_sid, FAIL, "H5Screate_simple"); + + /* Select sequence of points for point selection */ + for(u=1; u<(SPACE9_DIM1-1); u++) { + for(v=1; v<(SPACE9_DIM2-1); v++) { + coord2[v-1][0]=u; coord2[v-1][1]=v; + } /* end for */ + ret = H5Sselect_elements(tmp_sid,H5S_SELECT_APPEND,(SPACE9_DIM2-2),(const hssize_t **)coord2); + CHECK(ret, FAIL, "H5Sselect_elements"); + } /* end for */ + + /* Compare against hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); +#endif /* NOT_YET */ + + /* Construct hyperslab selection which matches "plain" hyperslab selection */ + /* Create dataspace for hyperslab selection */ + tmp_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(tmp_sid, FAIL, "H5Screate_simple"); + + /* Un-select entire extent */ + ret = H5Sselect_none(tmp_sid); + CHECK(ret, FAIL, "H5Sselect_none"); + + /* Select sequence of rows for hyperslab selection */ + for(u=1; u<(SPACE9_DIM1-1); u++) { + start[0]=u; start[1]=1; + stride[0]=1; stride[1]=1; + count[0]=1; count[1]=1; + block[0]=1; block[1]=(SPACE9_DIM2-2); + ret = H5Sselect_hyperslab(tmp_sid,H5S_SELECT_OR,start,stride,count,block); + CHECK(ret, FAIL, "H5Sselect_hyperslab"); + } /* end for */ + + /* Compare against hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare single "all" hyperslab selection to all the selections created */ + /* Compare against itself */ + check=H5S_select_shape_same_test(single_hyper_all_sid,single_hyper_all_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against copy of itself */ + tmp_sid=H5Scopy(single_hyper_all_sid); + CHECK(tmp_sid, FAIL, "H5Scopy"); + + check=H5S_select_shape_same_test(single_hyper_all_sid,tmp_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + ret = H5Sclose(tmp_sid); + CHECK(ret, FAIL, "H5Sclose"); + + /* Compare against "all" selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,all_sid); + VERIFY(check, TRUE, "H5S_select_shape_same_test"); + + /* Compare against "none" selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,none_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against single point selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,single_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against multiple point selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,mult_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "plain" single hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,single_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "single point" single hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,single_hyper_pt_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against regular, strided hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,regular_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against irregular hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,irreg_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + + /* Compare against "no" hyperslab selection */ + check=H5S_select_shape_same_test(single_hyper_all_sid,none_hyper_sid); + VERIFY(check, FALSE, "H5S_select_shape_same_test"); + +#ifdef NOT_YET +/* In theory, these two selections are the same shape, but the + * H5S_select_shape_same() routine is just not this sophisticated yet and it + * would take too much effort to make this work. The worst case is that the + * non-optimized chunk mapping routines will be invoked instead of the more + * optimized routines, so this only hurts performance, not correctness + */ + /* Construct point selection which matches "all" hyperslab selection */ + /* Create dataspace for point selection */ + tmp_sid = H5Screate_simple(SPACE9_RANK, dims, NULL); + CHECK(tmp_sid, FAIL, "H5Screate_simple"); + + /* Select sequence of points for point selection */ + for(u=0; u