diff options
-rw-r--r-- | src/H5Shyper.c | 337 | ||||
-rw-r--r-- | src/H5Sprivate.h | 6 |
2 files changed, 173 insertions, 170 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c index f215b30..6cc6cdd 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -71,9 +71,9 @@ 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); /* Static function for optimizing hyperslab */ -static htri_t H5S_hyper_can_rebuild(H5S_t *space); -static int H5S_hyper_check_opt(H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab_info[], int rank); -static int compare_regular_info( H5S_hyper_dim_t span_slab_info_1, H5S_hyper_dim_t span_slab_info_2); +static hbool_t H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, + H5S_hyper_dim_t span_slab_info[], unsigned rank); +static htri_t H5S_hyper_rebuild(H5S_t *space); /* Selection properties for hyperslab selections */ const H5S_select_class_t H5S_sel_hyper[1] = {{ @@ -5338,179 +5338,200 @@ done: /*-------------------------------------------------------------------------- NAME - H5S_hyper_can_rebuild + H5S_hyper_rebuild_helper PURPOSE - Check if optimized hyperslab information can be recovered - If it can be recovered with regular selection, just recovered. + Helper routine to rebuild optimized hyperslab information if possible. + (It can be recovered with regular selection) USAGE - htri_t H5S_hyper_can_rebuild(space) + herr_t H5S_hyper_rebuild_helper(space) + const H5S_hyper_span_t *span; IN: Portion of span tree to check + H5S_hyper_dim_t span_slab[]; OUT: Rebuilt section of hyperslab description + unsigned rank; IN: Current dimension to work on + RETURNS + >=0 on success, <0 on failure + DESCRIPTION + Examine the span tree for a hyperslab selection and rebuild + the start/stride/count/block information for the selection, if possible. + + 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. + + EXAMPLES + REVISION LOG + KY, 2005/9/22 +--------------------------------------------------------------------------*/ +static hbool_t +H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab_info[], + unsigned rank) +{ + hsize_t curr_stride, next_stride; + hsize_t curr_block, next_block; + hsize_t curr_start; + hsize_t curr_low; + int outcount; + H5S_hyper_dim_t canon_down_span_slab_info; + hbool_t ret_value = TRUE; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_rebuild_helper) + + if(span) { + /* Initialization */ + curr_stride = 1; + curr_block = 0; + outcount = 0; + curr_low = 0; + + /* Get "canonical" down span information */ + if(span->down) { + HDassert(span->down->head); + + /* Go to the next down span and check whether the selection can be rebuilt.*/ + if(!H5S_hyper_rebuild_helper(span->down->head, span_slab_info, rank - 1)) + HGOTO_DONE(FALSE) + + canon_down_span_slab_info = span_slab_info[rank - 2]; + } /* end if */ + + /* Assign the initial starting point & block size */ + curr_start = span->low; + curr_block = (span->high - span->low) + 1; + + /* Loop the span */ + while(span) { + if(outcount > 0) { + if(span->down) { + H5S_hyper_dim_t *curr_down_span_slab_info; + + HDassert(span->down->head); + + /* Go to the next down span and check whether the selection can be rebuilt.*/ + if(!H5S_hyper_rebuild_helper(span->down->head, span_slab_info, rank - 1)) + HGOTO_DONE(FALSE) + + /* Point to hyperslab span information set up by recursive call */ + curr_down_span_slab_info = &span_slab_info[rank - 2]; + + /* Compare the slab information of the adjacent spans in the down span tree.*/ + if(curr_down_span_slab_info->count > 0 && canon_down_span_slab_info.count > 0) { + if(curr_down_span_slab_info->start != canon_down_span_slab_info.start + || curr_down_span_slab_info->stride != canon_down_span_slab_info.stride + || curr_down_span_slab_info->block != canon_down_span_slab_info.block + || curr_down_span_slab_info->count != canon_down_span_slab_info.count) + HGOTO_DONE(FALSE) + } /* end if */ + else if (!((curr_down_span_slab_info->count == 0) && (canon_down_span_slab_info.count == 0))) + HGOTO_DONE(FALSE) + } /* end if */ + } /* end if */ + + /* Obtain values for stride and block */ + next_stride = span->low - curr_low; + next_block = (span->high - span->low) + 1; + + /* Compare stride and block in this span, to compare stride, + * three spans are needed. Ignore the first two spans. + */ + if(outcount > 1 && curr_stride != next_stride) + HGOTO_DONE(FALSE) + if(outcount != 0 && next_block != curr_block) + HGOTO_DONE(FALSE) + + /* Keep the isolated stride to be 1 */ + if(outcount != 0) + curr_stride = next_stride; + + /* Keep current starting point */ + curr_low = span->low; + + /* Advance to next span */ + span = span->next; + outcount++; + } /* end while */ + + /* Save the span information. */ + span_slab_info[rank - 1].start = curr_start; + span_slab_info[rank - 1].count = outcount; + span_slab_info[rank - 1].block = curr_block; + span_slab_info[rank - 1].stride = curr_stride; + } /* end if */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_hyper_rebuild_helper() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_rebuild + PURPOSE + Rebuild optimized hyperslab information if possible. + (It can be recovered with regular selection) + USAGE + herr_t H5S_hyper_rebuild(space) const H5S_t *space; IN: Dataspace to check RETURNS - TRUE/FALSE on success, <0 on failure + >=0 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. + Examine the span tree for a hyperslab selection and rebuild + the start/stride/count/block information for the selection, if possible. 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. + EXAMPLES + REVISION LOG + This routine is the optimization of the old version. The previous version can only detect a singluar selection. This version is general enough to detect any regular selection. KY, 2005/9/22 - - EXAMPLES - REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_hyper_can_rebuild (H5S_t *space) +H5S_hyper_rebuild(H5S_t *space) { - H5S_hyper_dim_t *top_span_slab_info; + H5S_hyper_dim_t top_span_slab_info[H5O_LAYOUT_NDIMS]; H5S_hyper_dim_t *diminfo; H5S_hyper_dim_t *app_diminfo; - int rank,curr_dim; - htri_t ret_value=TRUE; /* Return value */ + unsigned rank, curr_dim; + htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_can_rebuild); + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_rebuild) /* Check args */ - assert (space); - assert (space->select.sel_info.hslab->span_lst); + HDassert(space); + HDassert(space->select.sel_info.hslab->span_lst); /* Check the rank of space */ rank = space->extent.rank; - top_span_slab_info = calloc((unsigned)rank,sizeof(H5S_hyper_dim_t)); /* Check whether the slab can be rebuilt. Only regular selection can be rebuilt. If yes, fill in correct values.*/ - if(H5S_hyper_check_opt(space->select.sel_info.hslab->span_lst->head,top_span_slab_info,rank)== -1){ - ret_value = FALSE; - } + if(!H5S_hyper_rebuild_helper(space->select.sel_info.hslab->span_lst->head, top_span_slab_info, rank)) { + HGOTO_DONE(FALSE) + } /* end if */ else { - diminfo=space->select.sel_info.hslab->opt_diminfo; - app_diminfo=space->select.sel_info.hslab->app_diminfo; - - for(curr_dim = 0; curr_dim <rank; curr_dim++) { - - app_diminfo[rank-curr_dim-1].start = diminfo[rank-curr_dim-1].start = top_span_slab_info[curr_dim].start; - app_diminfo[rank-curr_dim-1].stride = diminfo[rank-curr_dim-1].stride = top_span_slab_info[curr_dim].stride; - app_diminfo[rank-curr_dim-1].count = diminfo[rank-curr_dim-1].count = top_span_slab_info[curr_dim].count; - app_diminfo[rank-curr_dim-1].block = diminfo[rank-curr_dim-1].block = top_span_slab_info[curr_dim].block; - - } - - space->select.sel_info.hslab->diminfo_valid=TRUE; - } - /* For each level of the span tree check that there is only one span at - * that level. - */ - - FUNC_LEAVE_NOAPI(ret_value); -} /* H5S_hyper_can_rebuild() */ - -/* Check whether the selection in span-tree form can be rebuilt as a regular hyperslab selection. */ + diminfo=space->select.sel_info.hslab->opt_diminfo; + app_diminfo=space->select.sel_info.hslab->app_diminfo; -static int H5S_hyper_check_opt(H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab_info[], int rank) { + for(curr_dim = 0; curr_dim < rank; curr_dim++) { - hsize_t curr_stride,next_stride; - hsize_t curr_block,next_block; - hsize_t curr_start; - hsize_t curr_low; - int outcount; - int ret_value; + app_diminfo[(rank - curr_dim) - 1].start = diminfo[(rank - curr_dim) - 1].start = top_span_slab_info[curr_dim].start; + app_diminfo[(rank - curr_dim) - 1].stride = diminfo[(rank - curr_dim) - 1].stride = top_span_slab_info[curr_dim].stride; + app_diminfo[(rank - curr_dim) - 1].count = diminfo[(rank - curr_dim) - 1].count = top_span_slab_info[curr_dim].count; + app_diminfo[(rank - curr_dim) - 1].block = diminfo[(rank - curr_dim) - 1].block = top_span_slab_info[curr_dim].block; - H5S_hyper_dim_t next_down_span_slab_info; - H5S_hyper_dim_t curr_down_span_slab_info; - H5S_hyper_span_t *orig_span; - H5S_hyper_span_t *next_down_span; - - /* Initialization */ - curr_stride = 1; - curr_block = 0; - outcount = 0; - curr_low = 0; + } /* end for */ - orig_span = span; + space->select.sel_info.hslab->diminfo_valid = TRUE; + } /* end else */ - /* Loop the span */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* H5S_hyper_rebuild() */ - while(span) { - if(span->down) { - next_down_span = span->down->head; - - /* Go to the next down span and check whether the selection can be rebuilt.*/ - if(next_down_span) { - ret_value = H5S_hyper_check_opt(next_down_span,span_slab_info,rank-1); - if(ret_value == -1) return -1; - next_down_span_slab_info = span_slab_info[rank-2]; - } - else - next_down_span_slab_info.count = 0; - } - else - next_down_span_slab_info.count = 0; - - /* Obtain values for stride and block */ - next_stride = span->low - curr_low; - next_block = span->high - span->low+1; - - /* Compare stride and block in this span, to compare stride, three spans are needed. Ignore the first two spans.*/ - if(outcount >1 && curr_stride != next_stride) return -1; - if(outcount!=0 && next_block != curr_block) return -1; - - /* Keep the isolated stride to be 1 */ - if(outcount != 0) curr_stride = next_stride; - curr_block = next_block; - curr_low = span->low; - - /* Assign the current starting point */ - if(outcount == 0) curr_start = curr_low; - - /* Compare the slab information of the adjacent spans in the down span tree.*/ - if(outcount !=0 && !compare_regular_info(curr_down_span_slab_info,next_down_span_slab_info)) return -1; - - curr_down_span_slab_info = next_down_span_slab_info; - span = span->next; - outcount ++; - } - - /* Save the span information. */ - if(orig_span) { - span_slab_info[rank-1].start = curr_start; - span_slab_info[rank-1].count = outcount; - span_slab_info[rank-1].block = curr_block; - span_slab_info[rank-1].stride = curr_stride; - } - - return 0; - - } - - /*Compare the slab information of two adjacent down span trees, this function shouldn't - be used as a general approach to compare two regular slabs. - - non-zero(true) should be returned if the two slabs are equal or are both NULL. - zero should be returned for other cases. - */ - - static int compare_regular_info( H5S_hyper_dim_t span_slab_info_1, H5S_hyper_dim_t span_slab_info_2) { - - /* Only when the first span of the current span tree has no "down span tree", - and the second span of the current span tree has no "down span tree", the selection is a regular selection. - Otherwise, the selection is irregular.*/ - - if((span_slab_info_1.count == 0) && (span_slab_info_2.count ==0 )) return 1; - if((span_slab_info_1.count) && (span_slab_info_2.count)) - return((span_slab_info_1.start == span_slab_info_2.start) && - (span_slab_info_1.stride == span_slab_info_2.stride) && - (span_slab_info_1.block == span_slab_info_2.block) && - (span_slab_info_1.count == span_slab_info_2.count)); - else - return 0; -} - /*-------------------------------------------------------------------------- NAME @@ -5783,20 +5804,11 @@ H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op, else { /* Check if we updated the spans */ if(updated_spans) { - htri_t status; /* Status from internal calls */ - - /* Check if the resulting hyperslab span tree can be used to re-build - * "optimized" start/stride/count/block information. + /* Attempt to rebuild "optimized" start/stride/count/block information. + * from resulting hyperslab span tree */ - status=H5S_hyper_can_rebuild(space); -#if 0 - if(status<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't check for rebuilding hyperslab info"); - printf("status = %d\n",status); - if(status>0) - if(H5S_hyper_rebuild(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info"); -#endif + if(H5S_hyper_rebuild(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info") } /* end if */ } /* end else */ } /* end else */ @@ -6318,20 +6330,11 @@ H5S_operate_hyperslab (H5S_t *result, H5S_hyper_span_info_t *spans1, H5S_seloper else { /* Check if we updated the spans */ if(updated_spans) { - htri_t status; /* Status from internal calls */ - - /* Check if the resulting hyperslab span tree can be used to re-build - * "optimized" start/stride/count/block information. + /* Attempt to rebuild "optimized" start/stride/count/block information. + * from resulting hyperslab span tree */ - status=H5S_hyper_can_rebuild(result); - #if 0 - if(status<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't check for rebuilding hyperslab info"); - printf("status = %d\n",status); - if(status>0) - if(H5S_hyper_rebuild(result)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info"); - #endif + if(H5S_hyper_rebuild(result) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info") } /* end if */ } /* end else */ } /* end else */ diff --git a/src/H5Sprivate.h b/src/H5Sprivate.h index fe982b6..a902918 100644 --- a/src/H5Sprivate.h +++ b/src/H5Sprivate.h @@ -49,9 +49,9 @@ typedef struct H5S_hyper_span_info_t H5S_hyper_span_info_t; /* Information about one dimension in a hyperslab selection */ typedef struct H5S_hyper_dim_t { hsize_t start; - hsize_t stride; - hsize_t count; - hsize_t block; + hsize_t stride; + hsize_t count; + hsize_t block; } H5S_hyper_dim_t; /* Point selection iteration container */ |