diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 2014-06-13 06:23:57 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 2014-06-13 06:23:57 (GMT) |
commit | 4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8 (patch) | |
tree | 860f585f1589250b03aec29371acb13ebbf2e022 /src/H5Shyper.c | |
parent | c2bc22d51cdf528c9b04ec115ac22c7e79fd7c6d (diff) | |
download | hdf5-4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8.zip hdf5-4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8.tar.gz hdf5-4ccb865c70f977a4a97d75df3d6e792c8cbdfdd8.tar.bz2 |
[svn-r25273] Description:
Bring in Chao/Neil/my changes to optimize hyperslab selection operations
further, along with 3 new public API routines: H5Scombine_hyperslab(),
H5Sselect_select() and H5Scombine_select(), along with many minor cleanups to
the code and fixing a few compiler warnings.
Tested on:
Mac OSX/64 10.9.3 w/gcc 4.9.x and parallel w/OpenMPI
(h5commttest forthcoming)
Diffstat (limited to 'src/H5Shyper.c')
-rw-r--r-- | src/H5Shyper.c | 3915 |
1 files changed, 2204 insertions, 1711 deletions
diff --git a/src/H5Shyper.c b/src/H5Shyper.c index c97c9b6..37fef93 100644 --- a/src/H5Shyper.c +++ b/src/H5Shyper.c @@ -17,7 +17,7 @@ * Programmer: Quincey Koziol <koziol@ncsa.uiuc.edu> * Thursday, June 18, 1998 * - * Purpose: Hyperslab selection data space I/O functions. + * Purpose: Hyperslab selection dataspace I/O functions. */ #define H5S_PACKAGE /*suppress error about including H5Spkg */ @@ -30,21 +30,72 @@ #include "H5Spkg.h" /* Dataspace functions */ #include "H5VMprivate.h" /* Vector functions */ +/* Local Macros */ +#define H5S_HYPER_COMPUTE_B_NOT_A 0x01 +#define H5S_HYPER_COMPUTE_A_AND_B 0x02 +#define H5S_HYPER_COMPUTE_A_NOT_B 0x04 + /* Local datatypes */ /* Static function prototypes */ +static H5S_hyper_span_t *H5S_hyper_new_span(hsize_t low, hsize_t high, + H5S_hyper_span_info_t *down, H5S_hyper_span_t *next); +static herr_t H5S_hyper_span_precompute(H5S_hyper_span_info_t *spans, size_t elmt_size); +static void H5S_hyper_span_scratch(H5S_hyper_span_info_t *spans, void *scr_value); +static H5S_hyper_span_info_t *H5S_hyper_copy_span(H5S_hyper_span_info_t *spans); +static htri_t H5S_hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1, + const H5S_hyper_span_info_t *span_info2); static herr_t H5S_hyper_free_span_info(H5S_hyper_span_info_t *span_info); static herr_t H5S_hyper_free_span(H5S_hyper_span_t *span); -static H5S_hyper_span_info_t *H5S_hyper_copy_span(H5S_hyper_span_info_t *spans); -static void H5S_hyper_span_scratch(H5S_hyper_span_info_t *spans, void *scr_value); -static herr_t H5S_hyper_span_precompute(H5S_hyper_span_info_t *spans, size_t elmt_size); -static herr_t H5S_generate_hyperslab(H5S_t *space, H5S_seloper_t op, - const hsize_t start[], const hsize_t stride[], const hsize_t count[], const hsize_t block[]); +static herr_t H5S_hyper_span_blocklist(const H5S_hyper_span_info_t *spans, + hsize_t start[], hsize_t end[], hsize_t rank, hsize_t *startblock, hsize_t *numblocks, + hsize_t **buf); +static herr_t H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, + hsize_t startblock, hsize_t numblocks, hsize_t *buf); +static herr_t H5S_hyper_recover_span(hbool_t *recover, H5S_hyper_span_t **curr_span, + H5S_hyper_span_t *next_span); +static H5S_hyper_span_t *H5S_hyper_coord_to_span(unsigned rank, const hsize_t *coords); +static herr_t H5S_hyper_append_span(H5S_hyper_span_t **prev_span, + H5S_hyper_span_info_t **span_tree, hsize_t low, hsize_t high, + H5S_hyper_span_info_t *down, H5S_hyper_span_t *next); +static herr_t H5S_hyper_clip_spans(H5S_hyper_span_info_t *a_spans, + H5S_hyper_span_info_t *b_spans, unsigned int selector, + unsigned cur_dim, unsigned dim_size, const hsize_t *span_a_b_bounds[4], + hsize_t *all_clips_bounds, H5S_hyper_span_info_t **a_not_b, + H5S_hyper_span_info_t **a_and_b, H5S_hyper_span_info_t **b_not_a); +static herr_t H5S_hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans); +static hsize_t H5S_hyper_spans_nelem(const H5S_hyper_span_info_t *spans); +static herr_t H5S_hyper_add_disjoint_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans); +static H5S_hyper_span_info_t *H5S_hyper_make_spans(unsigned rank, + const hsize_t *start, const hsize_t *stride, + const hsize_t *count, const hsize_t *block); +static herr_t H5S_hyper_update_diminfo(H5S_t *space, H5S_seloper_t op, + const H5S_hyper_dim_t *new_hyper_diminfo); +static hbool_t H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, + H5S_hyper_dim_t span_slab_info[], unsigned rank); static herr_t H5S_hyper_generate_spans(H5S_t *space); -/* Needed for use in hyperslab code (H5Shyper.c) */ -#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_update_bound_box(H5S_t *space, H5S_seloper_t op, + const hsize_t low_bounds[], const hsize_t high_bounds[]); +static herr_t H5S_fill_in_new_space(H5S_t *space1, H5S_seloper_t op, H5S_hyper_span_info_t *space2_span_lst, const hsize_t *space2_low_bound, const hsize_t *space2_high_bound, hbool_t can_own_span2, hbool_t *span2_owned, hbool_t *updated_spans, H5S_t **result); +static herr_t H5S_generate_hyperslab(H5S_t *space, H5S_seloper_t op, + const hsize_t start[], const hsize_t stride[], const hsize_t count[], + const hsize_t block[]); +static herr_t H5S_fill_in_hyperslab(H5S_t *old_space, H5S_seloper_t op, + const hsize_t start[], const hsize_t *stride, const hsize_t count[], + const hsize_t *block, H5S_t **new_space); +static herr_t H5S_fill_in_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2, + H5S_t **result); +static H5S_t *H5S_combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2); +static herr_t H5S_select_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2); +static herr_t H5S_hyper_get_seq_list_gen(const H5S_t *space, H5S_sel_iter_t *iter, + size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, + size_t *len); +static herr_t H5S_hyper_get_seq_list_opt(const H5S_t *space, H5S_sel_iter_t *iter, + size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, + size_t *len); +static herr_t H5S_hyper_get_seq_list_single(const H5S_t *space, H5S_sel_iter_t *iter, + size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, + size_t *len); /* Selection callbacks */ static herr_t H5S_hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection); @@ -75,11 +126,6 @@ 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); -/* Static function for optimizing hyperslab */ -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] = {{ H5S_SEL_HYPERSLABS, @@ -214,6 +260,116 @@ H5S_hyper_print_diminfo(FILE *f, const H5S_t *space) FUNC_LEAVE_NOAPI(SUCCEED) } + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_print_spans_dfs + PURPOSE + Output the span elements for one span list in depth-first order + USAGE + herr_t H5S_hyper_print_spans_dfs(f, span_lst, depth) + FILE *f; IN: the file to output + const H5S_hyper_span_info_t *span_lst; IN: the span list to output + unsigned depth; IN: the level of this span list + RETURNS + non-negative on success, negative on failure + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_print_spans_dfs(FILE *f, const H5S_hyper_span_info_t *span_lst, + unsigned depth) +{ + H5S_hyper_span_t *actual_tail = NULL; + H5S_hyper_span_t *cur_elem; + unsigned num_elems = 0; + unsigned i, elem_idx; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_print_spans_dfs) + + /* get the actual tail from head */ + cur_elem = span_lst->head; + HDassert(cur_elem); /* at least 1 element */ + while(cur_elem) { + actual_tail = cur_elem; + cur_elem = cur_elem->next; + num_elems++; + } /* end while */ + + for(i = 0; i < depth; i++) + HDfprintf(f, "\t"); + HDfprintf(f, "DIM[%u]: ref_count=%u, #elems=%u, scratch=%p, head=%p, tail=%p, actual_tail=%p, matched=%t\n", depth, + span_lst->count, num_elems, span_lst->scratch, span_lst->head, + span_lst->tail, actual_tail, (span_lst->tail == actual_tail)); + + cur_elem = span_lst->head; + elem_idx = 0; + while(cur_elem) { + for(i = 0; i < depth; i++) + HDfprintf(f, "\t"); + HDfprintf(f, "ELEM[%u]: ptr=%p, low=%Hu, high=%Hu, nelem=%Hu, pstride=%Hu, down=%p\n", + elem_idx++, cur_elem, cur_elem->low, cur_elem->high, cur_elem->nelem, + cur_elem->pstride, cur_elem->down); + if(cur_elem->down) + H5S_hyper_print_spans_dfs(f, cur_elem->down, depth + 1); + cur_elem = cur_elem->next; + } /* end while */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5S_hyper_print_spans_dfs() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_print_space_dfs + PURPOSE + Output the span elements for one hyperslab selection space in depth-first order + USAGE + herr_t H5S_hyper_print_space_dfs(f, space) + FILE *f; IN: the file to output + const H5S_t *space; IN: the selection space to output + RETURNS + non-negative on success, negative on failure + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_print_space_dfs(FILE *f, const H5S_t *space) +{ + const H5S_hyper_sel_t *hslab = space->select.sel_info.hslab; + const unsigned dims = space->extent.rank; + unsigned i; + + FUNC_ENTER_NOAPI_NOINIT_NOFUNC(H5S_hyper_print_space_dfs) + HDassert(hslab); + + HDfprintf(f, "=======================\n"); + HDfprintf(f, "SPACE: span_lst=%p, #dims=%u, offset_changed=%d\n", hslab->span_lst, dims, space->select.offset_changed); + HDfprintf(f, " offsets=["); + for(i = 0; i < dims - 1; i++) + HDfprintf(f, "%lld,", space->select.offset[i]); + HDfprintf(f, "%lld]\n", space->select.offset[dims-1]); + HDfprintf(f, " low_bounds=["); + for(i = 0; i < dims-1; i++) + HDfprintf(f, "%llu,", space->select.low_bounds[i]); + HDfprintf(f, "%llu]\n", space->select.low_bounds[dims-1]); + HDfprintf(f, " high_bounds=["); + for(i = 0; i < dims - 1; i++) + HDfprintf(f, "%llu,", space->select.high_bounds[i]); + HDfprintf(f, "%llu]\n", space->select.high_bounds[dims-1]); + + /* Start print out the highest-order of dimension */ + if(hslab->span_lst) + H5S_hyper_print_spans_dfs(f, hslab->span_lst, 0); + HDfprintf(f, "=======================\n\n"); + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5S_hyper_print_space_dfs() */ #endif /* H5S_HYPER_DEBUG */ @@ -256,11 +412,17 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) /* Get the rank of the dataspace */ rank = space->extent.rank; + /* Rebuild diminfo if it is invalid and has not been confirmed to be + * impossible */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) + /* Casting away const OK -NAF */ + (void)H5S_hyper_rebuild((H5S_t *)space); + /* Set the temporary pointer to the dimension information */ tdiminfo = space->select.sel_info.hslab->opt_diminfo; /* Check for the special case of just one H5Sselect_hyperslab call made */ - if(space->select.sel_info.hslab->diminfo_valid) { + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { /* Initialize the information needed for regular hyperslab I/O */ const hsize_t *mem_size; /* Temporary pointer to dataspace extent's dimension sizes */ hsize_t acc; /* Accumulator for "flattened" dimension's sizes */ @@ -407,7 +569,7 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) iter->type = H5S_sel_iter_hyper; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_iter_init() */ +} /* end H5S_hyper_iter_init() */ /*------------------------------------------------------------------------- @@ -421,12 +583,10 @@ H5S_hyper_iter_init(H5S_sel_iter_t *iter, const H5S_t *space) * Programmer: Quincey Koziol * Tuesday, April 22, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t -H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords) +H5S_hyper_iter_coords(const H5S_sel_iter_t *iter, hsize_t *coords) { FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -494,7 +654,7 @@ H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords) HDmemcpy(coords, iter->u.hyp.off, sizeof(hsize_t) * iter->rank); FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_iter_coords() */ +} /* end H5S_hyper_iter_coords() */ /*------------------------------------------------------------------------- @@ -511,12 +671,10 @@ H5S_hyper_iter_coords (const H5S_sel_iter_t *iter, hsize_t *coords) * 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, hsize_t *start, hsize_t *end) +H5S_hyper_iter_block(const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) { unsigned u; /* Local index variable */ @@ -548,7 +706,7 @@ H5S_hyper_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_iter_block() */ +} /* end H5S_hyper_iter_block() */ /*------------------------------------------------------------------------- @@ -561,12 +719,10 @@ H5S_hyper_iter_block (const H5S_sel_iter_t *iter, hsize_t *start, hsize_t *end) * Programmer: Quincey Koziol * Tuesday, June 16, 1998 * - * Modifications: - * *------------------------------------------------------------------------- */ static hsize_t -H5S_hyper_iter_nelmts (const H5S_sel_iter_t *iter) +H5S_hyper_iter_nelmts(const H5S_sel_iter_t *iter) { FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -574,7 +730,7 @@ H5S_hyper_iter_nelmts (const H5S_sel_iter_t *iter) HDassert(iter); FUNC_LEAVE_NOAPI(iter->elmt_left) -} /* H5S_hyper_iter_nelmts() */ +} /* end H5S_hyper_iter_nelmts() */ /*-------------------------------------------------------------------------- @@ -630,7 +786,7 @@ H5S_hyper_iter_has_next_block(const H5S_sel_iter_t *iter) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_iter_has_next_block() */ +} /* end H5S_hyper_iter_has_next_block() */ /*------------------------------------------------------------------------- @@ -645,10 +801,6 @@ done: * Programmer: Quincey Koziol * Friday, September 8, 2000 * - * Modifications: - * Modified for both general and optimized hyperslab I/O - * Quincey Koziol, April 17, 2003 - * *------------------------------------------------------------------------- */ static herr_t @@ -847,7 +999,7 @@ H5S_hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem) } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_iter_next() */ +} /* end H5S_hyper_iter_next() */ /*------------------------------------------------------------------------- @@ -862,8 +1014,6 @@ H5S_hyper_iter_next(H5S_sel_iter_t *iter, size_t nelem) * Programmer: Quincey Koziol * Tuesday, June 3, 2003 * - * Modifications: - * *------------------------------------------------------------------------- */ static herr_t @@ -1032,7 +1182,7 @@ H5S_hyper_iter_next_block(H5S_sel_iter_t *iter) } /* end else */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_iter_next() */ +} /* end H5S_hyper_iter_next() */ /*-------------------------------------------------------------------------- @@ -1053,7 +1203,7 @@ H5S_hyper_iter_next_block(H5S_sel_iter_t *iter) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_iter_release (H5S_sel_iter_t *iter) +H5S_hyper_iter_release(H5S_sel_iter_t *iter) { FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -1066,7 +1216,7 @@ H5S_hyper_iter_release (H5S_sel_iter_t *iter) H5S_hyper_free_span_info(iter->u.hyp.spans); FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_iter_release() */ +} /* end H5S_hyper_iter_release() */ /*-------------------------------------------------------------------------- @@ -1115,7 +1265,7 @@ H5S_hyper_new_span(hsize_t low, hsize_t high, H5S_hyper_span_info_t *down, H5S_h done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_new_span() */ +} /* end H5S_hyper_new_span() */ /*-------------------------------------------------------------------------- @@ -1138,17 +1288,17 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_span_precompute_helper (H5S_hyper_span_info_t *spans, size_t elmt_size) +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 */ + H5S_hyper_span_t *span; /* Hyperslab span */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT HDassert(spans); /* Check if we've already set this down span tree */ - if(spans->scratch!=(H5S_hyper_span_info_t *)~((size_t)NULL)) { + if(spans->scratch != (H5S_hyper_span_info_t *)~((size_t)NULL)) { /* Set the tree's scratch pointer */ spans->scratch=(H5S_hyper_span_info_t *)~((size_t)NULL); @@ -1174,7 +1324,7 @@ H5S_hyper_span_precompute_helper (H5S_hyper_span_info_t *spans, size_t elmt_size done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_span_precompute_helper() */ +} /* end H5S_hyper_span_precompute_helper() */ /*-------------------------------------------------------------------------- @@ -1214,7 +1364,7 @@ H5S_hyper_span_precompute(H5S_hyper_span_info_t *spans, size_t elmt_size) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_span_precompute() */ +} /* end H5S_hyper_span_precompute() */ /*-------------------------------------------------------------------------- @@ -1261,7 +1411,7 @@ H5S_hyper_span_scratch(H5S_hyper_span_info_t *spans, void *scr_value) } /* end if */ FUNC_LEAVE_NOAPI_VOID -} /* H5S_hyper_span_scratch() */ +} /* end H5S_hyper_span_scratch() */ /*-------------------------------------------------------------------------- @@ -1282,7 +1432,7 @@ H5S_hyper_span_scratch(H5S_hyper_span_info_t *spans, void *scr_value) REVISION LOG --------------------------------------------------------------------------*/ static H5S_hyper_span_info_t * -H5S_hyper_copy_span_helper (H5S_hyper_span_info_t *spans) +H5S_hyper_copy_span_helper(H5S_hyper_span_info_t *spans) { H5S_hyper_span_t *span; /* Hyperslab span */ H5S_hyper_span_t *new_span; /* Temporary hyperslab span */ @@ -1304,13 +1454,11 @@ H5S_hyper_copy_span_helper (H5S_hyper_span_info_t *spans) } /* end if */ else { /* Allocate a new span_info node */ - if(NULL == (ret_value = H5FL_MALLOC(H5S_hyper_span_info_t))) + if(NULL == (ret_value = H5FL_CALLOC(H5S_hyper_span_info_t))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span info") - /* Copy the span_info information */ + /* Set the non-zero span_info information */ ret_value->count = 1; - ret_value->scratch = NULL; - ret_value->head = NULL; /* Set the scratch pointer in the node being copied to the newly allocated node */ spans->scratch = ret_value; @@ -1345,11 +1493,14 @@ H5S_hyper_copy_span_helper (H5S_hyper_span_info_t *spans) /* Advance to next span */ span = span->next; } /* end while */ + + /* Retain a pointer to the last span */ + ret_value->tail = prev_span; } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_copy_span_helper() */ +} /* end H5S_hyper_copy_span_helper() */ /*-------------------------------------------------------------------------- @@ -1389,7 +1540,7 @@ H5S_hyper_copy_span(H5S_hyper_span_info_t *spans) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_copy_span() */ +} /* end H5S_hyper_copy_span() */ /*-------------------------------------------------------------------------- @@ -1412,19 +1563,20 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_hyper_cmp_spans (H5S_hyper_span_info_t *span_info1, H5S_hyper_span_info_t *span_info2) +H5S_hyper_cmp_spans(const H5S_hyper_span_info_t *span_info1, const H5S_hyper_span_info_t *span_info2) { - H5S_hyper_span_t *span1; - H5S_hyper_span_t *span2; - htri_t nest=FAIL; - htri_t ret_value=FAIL; + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Check for redundant comparison */ - if(span_info1==span_info2) - ret_value=TRUE; + if(span_info1 == span_info2) + ret_value = TRUE; else { + const H5S_hyper_span_t *span1; + const H5S_hyper_span_t *span2; + htri_t nest = FAIL; + /* Check for both spans being NULL */ if(span_info1==NULL && span_info2==NULL) ret_value=TRUE; @@ -1492,7 +1644,7 @@ H5S_hyper_cmp_spans (H5S_hyper_span_info_t *span_info1, H5S_hyper_span_info_t *s } /* end else */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_cmp_spans() */ +} /* end H5S_hyper_cmp_spans() */ /*-------------------------------------------------------------------------- @@ -1515,7 +1667,7 @@ H5S_hyper_cmp_spans (H5S_hyper_span_info_t *span_info1, H5S_hyper_span_info_t *s REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_free_span_info (H5S_hyper_span_info_t *span_info) +H5S_hyper_free_span_info(H5S_hyper_span_info_t *span_info) { H5S_hyper_span_t *span, *next_span; herr_t ret_value=SUCCEED; /* Return value */ @@ -1545,7 +1697,7 @@ H5S_hyper_free_span_info (H5S_hyper_span_info_t *span_info) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_free_span_info() */ +} /* end H5S_hyper_free_span_info() */ /*-------------------------------------------------------------------------- @@ -1568,7 +1720,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_free_span (H5S_hyper_span_t *span) +H5S_hyper_free_span(H5S_hyper_span_t *span) { herr_t ret_value=SUCCEED; @@ -1587,7 +1739,7 @@ H5S_hyper_free_span (H5S_hyper_span_t *span) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_free_span() */ +} /* end H5S_hyper_free_span() */ /*-------------------------------------------------------------------------- @@ -1615,14 +1767,15 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) +H5S_hyper_copy(H5S_t *dst, const H5S_t *src, hbool_t share_selection) { H5S_hyper_sel_t *dst_hslab; /* Pointer to destination hyperslab info */ const H5S_hyper_sel_t *src_hslab; /* Pointer to source hyperslab info */ - herr_t ret_value=SUCCEED; /* return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) + /* Sanity check */ HDassert(src); HDassert(dst); @@ -1631,24 +1784,21 @@ H5S_hyper_copy (H5S_t *dst, const H5S_t *src, hbool_t share_selection) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info") /* Set temporary pointers */ - dst_hslab=dst->select.sel_info.hslab; - src_hslab=src->select.sel_info.hslab; + dst_hslab = dst->select.sel_info.hslab; + src_hslab = src->select.sel_info.hslab; /* Copy the hyperslab information */ - dst_hslab->diminfo_valid=src_hslab->diminfo_valid; - if(src_hslab->diminfo_valid) { - size_t u; /* Local index variable */ - - for(u=0; u<src->extent.rank; u++) { - dst_hslab->opt_diminfo[u]=src_hslab->opt_diminfo[u]; - dst_hslab->app_diminfo[u]=src_hslab->app_diminfo[u]; - } /* end for */ + dst_hslab->diminfo_valid = src_hslab->diminfo_valid; + if(src_hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { + HDmemcpy(dst_hslab->opt_diminfo, src_hslab->opt_diminfo, sizeof(H5S_hyper_dim_t) * src->extent.rank); + HDmemcpy(dst_hslab->app_diminfo, src_hslab->app_diminfo, sizeof(H5S_hyper_dim_t) * src->extent.rank); } /* end if */ - dst->select.sel_info.hslab->span_lst=src->select.sel_info.hslab->span_lst; + + dst->select.sel_info.hslab->span_lst = src->select.sel_info.hslab->span_lst; /* Check if there is hyperslab span information to copy */ /* (Regular hyperslab information is copied with the selection structure) */ - if(src->select.sel_info.hslab->span_lst!=NULL) { + if(src->select.sel_info.hslab->span_lst != NULL) { if(share_selection) { /* Share the source's span tree by incrementing the reference count on it */ dst->select.sel_info.hslab->span_lst->count++; @@ -1665,72 +1815,6 @@ done: /*-------------------------------------------------------------------------- NAME - H5S_hyper_is_valid_helper - PURPOSE - Check whether the selection fits within the extent, with the current - offset defined. - USAGE - htri_t H5S_hyper_is_valid_helper(spans, offset, rank); - const H5S_hyper_span_info_t *spans; IN: Pointer to current hyperslab span tree - const hssize_t *offset; IN: Pointer to offset array - const hsize_t *size; IN: Pointer to size array - hsize_t rank; IN: Current rank looking at - RETURNS - TRUE if the selection fits within the extent, FALSE if it does not and - Negative on an error. - DESCRIPTION - Determines if the current selection at the current offet fits within the - extent for the dataspace. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static htri_t -H5S_hyper_is_valid_helper (const H5S_hyper_span_info_t *spans, const hssize_t *offset, const hsize_t *size, hsize_t rank) -{ - H5S_hyper_span_t *curr; /* Hyperslab information nodes */ - htri_t tmp; /* temporary return value */ - htri_t ret_value=TRUE; /* return value */ - - FUNC_ENTER_NOAPI_NOINIT_NOERR - - HDassert(spans); - HDassert(offset); - HDassert(size); - HDassert(rank < H5O_LAYOUT_NDIMS); - - /* Check each point to determine whether selection+offset is within extent */ - curr=spans->head; - while(curr!=NULL && ret_value==TRUE) { - /* Check if an offset has been defined */ - /* Bounds check the selected point + offset against the extent */ - if((((hssize_t)curr->low+offset[rank])>=(hssize_t)size[rank]) - || (((hssize_t)curr->low+offset[rank])<0) - || (((hssize_t)curr->high+offset[rank])>=(hssize_t)size[rank]) - || (((hssize_t)curr->high+offset[rank])<0)) { - ret_value=FALSE; - break; - } /* end if */ - - /* Recurse if this node has down spans */ - if(curr->down!=NULL) { - if((tmp=H5S_hyper_is_valid_helper(curr->down,offset,size,rank+1))!=TRUE) { - ret_value=tmp; - break; - } /* end if */ - } /* end if */ - - /* Advance to next node */ - curr=curr->next; - } /* end while */ - - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_hyper_is_valid_helper() */ - - -/*-------------------------------------------------------------------------- - NAME H5S_hyper_is_valid PURPOSE Check whether the selection fits within the extent, with the current @@ -1750,43 +1834,23 @@ H5S_hyper_is_valid_helper (const H5S_hyper_span_info_t *spans, const hssize_t *o REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_hyper_is_valid (const H5S_t *space) +H5S_hyper_is_valid(const H5S_t *space) { - unsigned u; /* Counter */ - htri_t ret_value=TRUE; /* return value */ + unsigned u; /* Counter */ + htri_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI_NOERR HDassert(space); - /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { - const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab->opt_diminfo; /* local alias for diminfo */ - hssize_t end; /* The high bound of a region in a dimension */ - - /* Check each dimension */ - for(u=0; u<space->extent.rank; u++) { - /* if block or count is zero, then can skip the test since */ - /* no data point is chosen */ - if (diminfo[u].count && diminfo[u].block) { - /* Bounds check the start point in this dimension */ - if(((hssize_t)diminfo[u].start+space->select.offset[u])<0 || - ((hssize_t)diminfo[u].start+space->select.offset[u])>=(hssize_t)space->extent.size[u]) - HGOTO_DONE(FALSE) - - /* Compute the largest location in this dimension */ - end=(hssize_t)(diminfo[u].start+diminfo[u].stride*(diminfo[u].count-1)+(diminfo[u].block-1))+space->select.offset[u]; - - /* Bounds check the end point in this dimension */ - if(end<0 || end>=(hssize_t)space->extent.size[u]) - HGOTO_DONE(FALSE) - } /* end if */ - } /* end for */ - } /* end if */ - else { - /* Call the recursive routine to validate the span tree */ - ret_value=H5S_hyper_is_valid_helper(space->select.sel_info.hslab->span_lst,space->select.offset,space->extent.size,(hsize_t)0); - } /* end else */ + /* Check each dimension */ + for(u = 0; u < space->extent.rank; u++) { + /* Bounds check the selected point + offset against the extent */ + if(((hssize_t)space->select.low_bounds[u] + space->select.offset[u]) < 0) + HGOTO_DONE(FALSE) + if((space->select.high_bounds[u] + (hsize_t)space->select.offset[u]) >= space->extent.size[u]) + HGOTO_DONE(FALSE) + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) @@ -1835,7 +1899,7 @@ H5S_hyper_span_nblocks(H5S_hyper_span_info_t *spans) } /* end else */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_span_nblocks() */ +} /* end H5S_hyper_span_nblocks() */ /*-------------------------------------------------------------------------- @@ -1858,14 +1922,15 @@ H5S_hyper_span_nblocks(H5S_hyper_span_info_t *spans) static hsize_t H5S_get_select_hyper_nblocks(H5S_t *space) { - hsize_t ret_value; /* return value */ + hsize_t ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR HDassert(space); /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (No need to rebuild the dimension info yet -QAK) */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { unsigned u; /* Local index variable */ /* Check each dimension */ @@ -1876,7 +1941,7 @@ H5S_get_select_hyper_nblocks(H5S_t *space) ret_value = H5S_hyper_span_nblocks(space->select.sel_info.hslab->span_lst); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_get_select_hyper_nblocks() */ +} /* end H5S_get_select_hyper_nblocks() */ /*-------------------------------------------------------------------------- @@ -1907,7 +1972,7 @@ H5Sget_select_hyper_nblocks(hid_t spaceid) /* Check args */ if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") if(H5S_GET_SELECT_TYPE(space) != H5S_SEL_HYPERSLABS) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection") @@ -1915,7 +1980,7 @@ H5Sget_select_hyper_nblocks(hid_t spaceid) done: FUNC_LEAVE_API(ret_value) -} /* H5Sget_select_hyper_nblocks() */ +} /* end H5Sget_select_hyper_nblocks() */ /*-------------------------------------------------------------------------- @@ -1955,7 +2020,10 @@ H5S_hyper_serial_size(const H5S_t *space) ret_value = 24; /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (It would be useful to rebuild the regular hyperslab selection, if we + * encoded it efficiently, which we aren't currently. *sigh* -QAK) + */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { /* Check each dimension */ for(block_count = 1, u = 0; u < space->extent.rank; u++) block_count *= space->select.sel_info.hslab->opt_diminfo[u].count; @@ -1994,7 +2062,7 @@ H5S_hyper_serial_size(const H5S_t *space) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_serialize_helper (const H5S_hyper_span_info_t *spans, hsize_t *start, hsize_t *end, hsize_t rank, uint8_t **buf) +H5S_hyper_serialize_helper(const H5S_hyper_span_info_t *spans, hsize_t *start, hsize_t *end, hsize_t rank, uint8_t **buf) { H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */ hsize_t u; /* Index variable */ @@ -2046,7 +2114,7 @@ H5S_hyper_serialize_helper (const H5S_hyper_span_info_t *spans, hsize_t *start, done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_serialize_helper() */ +} /* end H5S_hyper_serialize_helper() */ /*-------------------------------------------------------------------------- @@ -2069,7 +2137,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) +H5S_hyper_serialize(const H5S_t *space, uint8_t *buf) { const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */ @@ -2100,13 +2168,16 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) len += 4; /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (It would be useful to rebuild the regular hyperslab selection, if we + * encoded it efficiently, which we aren't currently. *sigh* -QAK) + */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { unsigned u; /* Local counting variable */ - /* Set some convienence values */ + /* Set some convenience values */ ndims = space->extent.rank; fast_dim = ndims - 1; - diminfo=space->select.sel_info.hslab->opt_diminfo; + diminfo = space->select.sel_info.hslab->opt_diminfo; /* Check each dimension */ for(block_count = 1, u = 0; u < ndims; u++) @@ -2197,7 +2268,7 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) /* Add 8 bytes times the rank for each hyperslab selected */ H5_CHECK_OVERFLOW((8 * space->extent.rank * block_count), hsize_t, size_t); - len += (size_t)(8 * space->extent.rank * block_count); + len += (uint32_t)(8 * space->extent.rank * block_count); /* Encode each hyperslab in selection */ H5S_hyper_serialize_helper(space->select.sel_info.hslab->span_lst, start, end, (hsize_t)0, &buf); @@ -2207,7 +2278,7 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) UINT32ENCODE(lenp, (uint32_t)len); /* Store the length of the extra information */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_serialize() */ +} /* end H5S_hyper_serialize() */ /*-------------------------------------------------------------------------- @@ -2230,7 +2301,7 @@ H5S_hyper_serialize (const H5S_t *space, uint8_t *buf) REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_deserialize (H5S_t *space, const uint8_t *buf) +H5S_hyper_deserialize(H5S_t *space, const uint8_t *buf) { uint32_t rank; /* rank of points */ size_t num_elem=0; /* number of elements in selection */ @@ -2287,7 +2358,7 @@ H5S_hyper_deserialize (H5S_t *space, const uint8_t *buf) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_deserialize() */ +} /* end H5S_hyper_deserialize() */ /*-------------------------------------------------------------------------- @@ -2324,9 +2395,11 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_span_blocklist(H5S_hyper_span_info_t *spans, hsize_t start[], hsize_t end[], hsize_t rank, hsize_t *startblock, hsize_t *numblocks, hsize_t **buf) +H5S_hyper_span_blocklist(const H5S_hyper_span_info_t *spans, hsize_t start[], + hsize_t end[], hsize_t rank, hsize_t *startblock, hsize_t *numblocks, + hsize_t **buf) { - H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */ + const H5S_hyper_span_t *curr; /* Pointer to current hyperslab span */ hsize_t u; /* Index variable */ herr_t ret_value = SUCCEED; /* return value */ @@ -2391,7 +2464,7 @@ H5S_hyper_span_blocklist(H5S_hyper_span_info_t *spans, hsize_t start[], hsize_t done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_span_blocklist() */ +} /* end H5S_hyper_span_blocklist() */ /*-------------------------------------------------------------------------- @@ -2434,8 +2507,13 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc HDassert(space); HDassert(buf); + /* Rebuild diminfo if it is invalid and has not been confirmed to be + * impossible */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) + (void)H5S_hyper_rebuild(space); + /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { const H5S_hyper_dim_t *diminfo; /* Alias for dataspace's diminfo information */ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary hyperslab counts */ hsize_t offset[H5O_LAYOUT_NDIMS]; /* Offset of element in dataspace */ @@ -2547,7 +2625,7 @@ H5S_get_select_hyper_blocklist(H5S_t *space, hbool_t internal, hsize_t startbloc } /* end else */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_get_select_hyper_blocklist() */ +} /* end H5S_get_select_hyper_blocklist() */ /*-------------------------------------------------------------------------- @@ -2594,7 +2672,7 @@ H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, if(buf == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid pointer") if(NULL == (space = (H5S_t *)H5I_object_verify(spaceid, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") if(H5S_GET_SELECT_TYPE(space)!=H5S_SEL_HYPERSLABS) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a hyperslab selection") @@ -2606,77 +2684,7 @@ H5Sget_select_hyper_blocklist(hid_t spaceid, hsize_t startblock, done: FUNC_LEAVE_API(ret_value) -} /* H5Sget_select_hyper_blocklist() */ - - -/*-------------------------------------------------------------------------- - NAME - H5S_hyper_bounds_helper - PURPOSE - Gets the bounding box containing the selection. - USAGE - htri_t H5S_hyper_bounds_helper(spans, offset, rank); - const H5S_hyper_span_info_t *spans; IN: Pointer to current hyperslab span tree - const hssize_t *offset; IN: Pointer to offset array - hsize_t rank; IN: Current rank looking at - hsize_t *start; OUT: Start array bounds - hsize_t *end; OUT: End array bounds - RETURNS - Non-negative on success, negative on failure - DESCRIPTION - Retrieves the bounding box containing the current selection and places - it into the user's buffers. The start and end buffers must be large - enough to hold the dataspace rank number of coordinates. The bounding box - exactly contains the selection, ie. if a 2-D element selection is currently - defined with the following points: (4,5), (6,8) (10,7), the bounding box - with be (4, 5), (10, 8). - The bounding box calculations _does_ include the current offset of the - selection within the dataspace extent. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - 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_span_t *curr; /* Hyperslab information nodes */ - herr_t ret_value = SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - HDassert(spans); - HDassert(offset); - HDassert(rank < H5O_LAYOUT_NDIMS); - HDassert(start); - HDassert(end); - - /* Check each point to determine whether selection+offset is within extent */ - curr=spans->head; - while(curr!=NULL) { - /* Check for offset moving selection negative */ - if(((hssize_t)curr->low + offset[rank]) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") - - /* Check if the current span extends the bounding box */ - if((curr->low + (hsize_t)offset[rank]) < start[rank]) - start[rank] = curr->low + (hsize_t)offset[rank]; - if((curr->high + (hsize_t)offset[rank]) > end[rank]) - end[rank] = curr->high + (hsize_t)offset[rank]; - - /* Recurse if this node has down spans */ - if(curr->down != NULL) { - if(H5S_hyper_bounds_helper(curr->down, offset, (rank + 1), start, end) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "failure in lower dimension") - } /* end if */ - - /* Advance to next node */ - curr = curr->next; - } /* end while */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_hyper_bounds_helper() */ +} /* end H5Sget_select_hyper_blocklist() */ /*-------------------------------------------------------------------------- @@ -2708,48 +2716,33 @@ done: static herr_t H5S_hyper_bounds(const H5S_t *space, hsize_t *start, hsize_t *end) { - unsigned rank; /* Dataspace rank */ - unsigned i; /* index variable */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ - FUNC_ENTER_NOAPI(FAIL) + FUNC_ENTER_NOAPI_NOINIT + /* Sanity check */ HDassert(space); HDassert(start); HDassert(end); - /* Set the start and end arrays up */ - rank = space->extent.rank; - for(i = 0; i < rank; i++) { - start[i] = HSIZET_MAX; - end[i] = 0; - } /* end for */ - - /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { - const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* local alias for diminfo */ - - /* Check each dimension */ - for(i = 0; i < rank; i++) { - /* Check for offset moving selection negative */ - if((space->select.offset[i] + (hssize_t)diminfo[i].start) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") + /* Loop over dimensions */ + for(u = 0; u < space->extent.rank; u++) { + /* Sanity check */ + HDassert(space->select.low_bounds[u] <= space->select.high_bounds[u]); - /* Compute the smallest location in this dimension */ - start[i] = diminfo[i].start + (hsize_t)space->select.offset[i]; + /* Check for offset moving selection negative */ + if(((hssize_t)space->select.low_bounds[u] + space->select.offset[u]) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "offset moves selection out of bounds") - /* Compute the largest location in this dimension */ - end[i] = diminfo[i].start + diminfo[i].stride * (diminfo[i].count - 1) + (diminfo[i].block - 1) + (hsize_t)space->select.offset[i]; - } /* end for */ - } /* end if */ - else { - /* Call the recursive routine to get the bounds for the span tree */ - ret_value = H5S_hyper_bounds_helper(space->select.sel_info.hslab->span_lst, space->select.offset, (hsize_t)0, start, end); - } /* end if */ + /* Set the low & high bounds in this dimension */ + start[u] = (hsize_t)((hssize_t)space->select.low_bounds[u] + space->select.offset[u]); + end[u] = (hsize_t)((hssize_t)space->select.high_bounds[u] + space->select.offset[u]); + } /* end for */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_bounds() */ +} /* end H5S_hyper_bounds() */ /*-------------------------------------------------------------------------- @@ -2796,7 +2789,8 @@ H5S_hyper_offset(const H5S_t *space, hsize_t *offset) dim_size = space->extent.size; /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (No need to rebuild the dimension info yet -QAK) */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Local alias for diminfo */ /* Loop through starting coordinates, calculating the linear offset */ @@ -2857,7 +2851,7 @@ H5S_hyper_offset(const H5S_t *space, hsize_t *offset) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_offset() */ +} /* end H5S_hyper_offset() */ /*-------------------------------------------------------------------------- @@ -2891,7 +2885,8 @@ H5S_hyper_is_contiguous(const H5S_t *space) HDassert(space); /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (No need to rebuild the dimension info yet -QAK) */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { const H5S_hyper_dim_t *diminfo=space->select.sel_info.hslab->opt_diminfo; /* local alias for diminfo */ /* @@ -3042,7 +3037,7 @@ H5S_hyper_is_contiguous(const H5S_t *space) } /* end else */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_is_contiguous() */ +} /* end H5S_hyper_is_contiguous() */ /*-------------------------------------------------------------------------- @@ -3076,7 +3071,8 @@ H5S_hyper_is_single(const H5S_t *space) HDassert(space); /* Check for a "single" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (No need to rebuild the dimension info yet -QAK) */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { /* * For a regular hyperslab to be single, it must have only one * block (i.e. count==1 in all dimensions) @@ -3110,7 +3106,7 @@ H5S_hyper_is_single(const H5S_t *space) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_is_single() */ +} /* end H5S_hyper_is_single() */ /*-------------------------------------------------------------------------- @@ -3143,14 +3139,20 @@ H5S_hyper_is_regular(const H5S_t *space) /* Check args */ HDassert(space); + /* Rebuild diminfo if it is invalid and has not been confirmed to be + * impossible */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) + /* Casting away const OK -NAF */ + (void)H5S_hyper_rebuild((H5S_t *)space); + /* Only simple check for regular hyperslabs for now... */ - if(space->select.sel_info.hslab->diminfo_valid) - ret_value=TRUE; + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) + ret_value = TRUE; else - ret_value=FALSE; + ret_value = FALSE; FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_is_regular() */ +} /* end H5S_hyper_is_regular() */ /*-------------------------------------------------------------------------- @@ -3172,8 +3174,8 @@ H5S_hyper_is_regular(const H5S_t *space) * Robb Matzke, 1998-08-25 * The fields which are freed are set to NULL to prevent them from being * freed again later. This fixes some allocation problems where - * changing the hyperslab selection of one data space causes a core dump - * when closing some other data space. + * changing the hyperslab selection of one dataspace causes a core dump + * when closing some other dataspace. --------------------------------------------------------------------------*/ static herr_t H5S_hyper_release(H5S_t *space) @@ -3199,7 +3201,7 @@ H5S_hyper_release(H5S_t *space) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_release() */ +} /* end H5S_hyper_release() */ /*-------------------------------------------------------------------------- @@ -3209,7 +3211,7 @@ done: Recover a generated span, if appropriate USAGE herr_t H5S_hyper_recover_span(recover, curr_span, next_span) - unsigned *recover; IN/OUT: Pointer recover flag + hbool_t *recover; IN/OUT: Pointer recover flag H5S_hyper_span_t **curr_span; IN/OUT: Pointer to current span in list H5S_hyper_span_t *next_span; IN: Pointer to next span RETURNS @@ -3223,7 +3225,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_recover_span (unsigned *recover, H5S_hyper_span_t **curr_span, H5S_hyper_span_t *next_span) +H5S_hyper_recover_span(hbool_t *recover, H5S_hyper_span_t **curr_span, H5S_hyper_span_t *next_span) { FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -3233,14 +3235,14 @@ H5S_hyper_recover_span (unsigned *recover, H5S_hyper_span_t **curr_span, H5S_hyp /* Check if the span should be recovered */ if(*recover) { H5S_hyper_free_span(*curr_span); - *recover=0; + *recover = FALSE; } /* end if */ /* Set the current span to next span */ - *curr_span=next_span; + *curr_span = next_span; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_recover_span() */ +} /* end H5S_hyper_recover_span() */ /*-------------------------------------------------------------------------- @@ -3262,11 +3264,11 @@ H5S_hyper_recover_span (unsigned *recover, H5S_hyper_span_t **curr_span, H5S_hyp REVISION LOG --------------------------------------------------------------------------*/ static H5S_hyper_span_t * -H5S_hyper_coord_to_span(unsigned rank, hsize_t *coords) +H5S_hyper_coord_to_span(unsigned rank, const hsize_t *coords) { H5S_hyper_span_t *new_span; /* Pointer to new span tree for coordinate */ - H5S_hyper_span_info_t *down=NULL; /* Pointer to new span tree for next level down */ - H5S_hyper_span_t *ret_value=NULL; /* Return value */ + H5S_hyper_span_info_t *down = NULL; /* Pointer to new span tree for next level down */ + H5S_hyper_span_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -3274,37 +3276,32 @@ H5S_hyper_coord_to_span(unsigned rank, hsize_t *coords) HDassert(coords); /* Search for location to insert new element in tree */ - if(rank>1) { + if(rank > 1) { /* Allocate a span info node */ - if((down = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) + if(NULL == (down = H5FL_CALLOC(H5S_hyper_span_info_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") - /* Set the reference count */ - down->count=0; - - /* Reset the scratch pad space */ - down->scratch=0; - /* Build span tree for coordinates below this one */ - if((down->head=H5S_hyper_coord_to_span(rank-1,&coords[1]))==NULL) + if(NULL == (down->head = H5S_hyper_coord_to_span(rank - 1, &coords[1]))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") + + /* Update the tail pointer of the down dimension, and it's a single span element */ + down->tail = down->head; } /* end if */ /* Build span for this coordinate */ - if((new_span = H5S_hyper_new_span(coords[0],coords[0],down,NULL))==NULL) + if(NULL == (new_span = H5S_hyper_new_span(coords[0], coords[0], down, NULL))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Set return value */ - ret_value=new_span; + ret_value = new_span; done: - if(ret_value==NULL) { - if(down!=NULL) - H5S_hyper_free_span_info(down); - } /* end if */ + if(ret_value == NULL && down!=NULL) + H5S_hyper_free_span_info(down); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_coord_to_span() */ +} /* end H5S_hyper_coord_to_span() */ /*-------------------------------------------------------------------------- @@ -3324,18 +3321,29 @@ done: GLOBAL VARIABLES COMMENTS, BUGS, ASSUMPTIONS Assumes that the element is not already covered by the span tree + + NOTE: There's an assumption about the context of this function call. + This function is only called is only being called from + H5D_chunk_mem_cb in src/H5Dchunk, when the library is + iterating over a memory selection, so the coordinates passed + to H5S_hyper_add_span_element will always be in increasing + order (according to a row-major (i.e. C, not FORTRAN) scan + over the dataset. Therefore, for every input of coordinates, + only the last span element (i.e., the tail pointer) in one + dimension is checked against the input. EXAMPLES REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, unsigned rank, hsize_t *coords) +H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, + unsigned rank, const hsize_t *coords) { H5S_hyper_span_info_t *tspan_info; /* Temporary pointer to span info */ H5S_hyper_span_info_t *prev_span_info; /* Pointer to span info for level above current position */ - H5S_hyper_span_t *tmp_span; /* Temporary pointer to a span */ + H5S_hyper_span_t *tail_span; /* Pointer to the tail span of one dimension */ H5S_hyper_span_t *tmp2_span; /* Another temporary pointer to a span */ H5S_hyper_span_t *new_span; /* New span created for element */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -3344,38 +3352,26 @@ H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, unsigned ran HDassert(coords); /* Get pointer to last span in span tree */ - tspan_info=span_tree; - if(span_tree->scratch) - tmp_span=(H5S_hyper_span_t *)span_tree->scratch; - else { - tmp_span=span_tree->head; - HDassert(tmp_span); - span_tree->scratch=(H5S_hyper_span_info_t *)tmp_span; - } /* end else */ + tail_span = span_tree->tail; /* Find last span tree which includes a portion of the coordinate */ - prev_span_info=NULL; - while(coords[0]>=tmp_span->low && coords[0]<=tmp_span->high) { + tspan_info = span_tree; + prev_span_info = NULL; + while(coords[0] >= tail_span->low && coords[0] <= tail_span->high) { /* Move rank & coordinate offset down a dimension */ rank--; coords++; /* Remember the span tree we are descending into */ - prev_span_info=tspan_info; - tspan_info=tmp_span->down; - - /* Get the last span in this span's 'down' tree */ - if(tspan_info->scratch) - tmp_span=(H5S_hyper_span_t *)tspan_info->scratch; - else { - tmp_span=tspan_info->head; - HDassert(tmp_span); - tspan_info->scratch=(H5S_hyper_span_info_t *)tmp_span; - } /* end else */ + prev_span_info = tspan_info; + tspan_info = tail_span->down; + HDassert(tspan_info); + tail_span = tspan_info->tail; } /* end while */ + HDassert(rank > 0); /* Check if we made it all the way to the bottom span in the tree */ - if(rank>1) { + if(rank > 1) { /* Before we create another span at this level in the tree, check if * the last span's "down tree" was equal to any other spans in this * list of spans in the span tree. @@ -3384,31 +3380,31 @@ H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, unsigned ran * previous span (if possible), or at least share their "down tree" * information. */ - tmp2_span=tspan_info->head; - while(tmp2_span!=tmp_span) { - if(H5S_hyper_cmp_spans(tmp2_span->down,tmp_span->down)==TRUE) { + tmp2_span = tspan_info->head; + while(tmp2_span != tail_span) { + if(TRUE == H5S_hyper_cmp_spans(tmp2_span->down, tail_span->down)) { /* Check for merging into previous span */ - if(tmp2_span->high+1==tmp_span->low) { + if(tmp2_span->high + 1 == tail_span->low) { /* Release last span created */ - H5S_hyper_free_span(tmp_span); + H5S_hyper_free_span(tail_span); /* Increase size of previous span */ tmp2_span->high++; tmp2_span->nelem++; /* Reset the 'tmp_span' for the rest of this block's algorithm */ - tmp_span=tmp2_span; + tail_span = tmp2_span; } /* end if */ /* Span is disjoint, but has the same "down tree" selection */ else { /* Release "down tree" information */ - H5S_hyper_free_span_info(tmp_span->down); + H5S_hyper_free_span_info(tail_span->down); /* Point at earlier span's "down tree" */ - tmp_span->down=tmp2_span->down; + tail_span->down = tmp2_span->down; /* Increment reference count on shared "down tree" */ - tmp_span->down->count++; + tail_span->down->count++; } /* end else */ /* Found span to merge into, break out now */ @@ -3416,32 +3412,30 @@ H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, unsigned ran } /* end if */ /* Advance to next span to check */ - tmp2_span=tmp2_span->next; + tmp2_span = tmp2_span->next; } /* end while */ /* Make span tree for current coordinates */ - if((new_span=H5S_hyper_coord_to_span(rank,coords))==NULL) + if(NULL == (new_span = H5S_hyper_coord_to_span(rank, coords))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Add new span tree as span */ - HDassert(tmp_span); - tmp_span->next=new_span; - - /* Make scratch pointer point to last span in list */ + HDassert(tail_span); + tail_span->next = new_span; HDassert(tspan_info); - tspan_info->scratch=(H5S_hyper_span_info_t *)new_span; + tspan_info->tail = new_span; /* Set the proper 'pstride' for new span */ - new_span->pstride=new_span->low-tmp_span->low; + new_span->pstride = new_span->low - tail_span->low; } /* end if */ else { /* Does new node adjoin existing node? */ - if(tmp_span->high+1==coords[0]) { - tmp_span->high++; - tmp_span->nelem++; + if(tail_span->high + 1 == coords[0]) { + tail_span->high++; + tail_span->nelem++; /* Check if this span tree should now be merged with a level higher in the tree */ - if(prev_span_info!=NULL) { + if(prev_span_info != NULL) { /* Before we create another span at this level in the tree, check if * the last span's "down tree" was equal to any other spans in this * list of spans in the span tree. @@ -3450,33 +3444,33 @@ H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, unsigned ran * previous span (if possible), or at least share their "down tree" * information. */ - tmp2_span=prev_span_info->head; - tmp_span=(H5S_hyper_span_t *)prev_span_info->scratch; - while(tmp2_span!=tmp_span) { - if(H5S_hyper_cmp_spans(tmp2_span->down,tmp_span->down)==TRUE) { + tmp2_span = prev_span_info->head; + tail_span = prev_span_info->tail; + while(tmp2_span != tail_span) { + if(TRUE == H5S_hyper_cmp_spans(tmp2_span->down, tail_span->down)) { /* Check for merging into previous span */ - if(tmp2_span->high+1==tmp_span->low) { + if(tmp2_span->high + 1 == tail_span->low) { /* Release last span created */ - H5S_hyper_free_span(tmp_span); + H5S_hyper_free_span(tail_span); /* Increase size of previous span */ tmp2_span->high++; tmp2_span->nelem++; /* Update pointers */ - tmp2_span->next=NULL; - prev_span_info->scratch=(H5S_hyper_span_info_t *)tmp2_span; + tmp2_span->next = NULL; + prev_span_info->tail = tmp2_span; } /* end if */ /* Span is disjoint, but has the same "down tree" selection */ else { /* Release "down tree" information */ - H5S_hyper_free_span_info(tmp_span->down); + H5S_hyper_free_span_info(tail_span->down); /* Point at earlier span's "down tree" */ - tmp_span->down=tmp2_span->down; + tail_span->down = tmp2_span->down; /* Increment reference count on shared "down tree" */ - tmp_span->down->count++; + tail_span->down->count++; } /* end else */ /* Found span to merge into, break out now */ @@ -3484,29 +3478,27 @@ H5S_hyper_add_span_element_helper(H5S_hyper_span_info_t *span_tree, unsigned ran } /* end if */ /* Advance to next span to check */ - tmp2_span=tmp2_span->next; + tmp2_span = tmp2_span->next; } /* end while */ } /* end if */ } /* end if */ else { - if((new_span = H5S_hyper_new_span(coords[0],coords[0],NULL,NULL))==NULL) + if(NULL == (new_span = H5S_hyper_new_span(coords[0], coords[0], NULL, NULL))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Add new span tree as span */ - HDassert(tmp_span); - tmp_span->next=new_span; - - /* Make scratch pointer point to last span in list */ - tspan_info->scratch=(H5S_hyper_span_info_t *)new_span; + HDassert(tail_span); + tail_span->next = new_span; + tspan_info->tail = new_span; /* Set the proper 'pstride' for new span */ - new_span->pstride=new_span->low-tmp_span->low; + new_span->pstride = new_span->low - tail_span->low; } /* end else */ } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_add_span_element_helper() */ +} /* end H5S_hyper_add_span_element_helper() */ /*-------------------------------------------------------------------------- @@ -3530,7 +3522,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ herr_t -H5S_hyper_add_span_element(H5S_t *space, unsigned rank, hsize_t *coords) +H5S_hyper_add_span_element(H5S_t *space, unsigned rank, const hsize_t *coords) { H5S_hyper_span_info_t *head = NULL; /* Pointer to new head of span tree */ herr_t ret_value = SUCCEED; /* Return value */ @@ -3540,23 +3532,24 @@ H5S_hyper_add_span_element(H5S_t *space, unsigned rank, hsize_t *coords) HDassert(space); HDassert(rank > 0); HDassert(coords); + HDassert(space->extent.rank == rank); /* Check if this is the first element in the selection */ if(NULL == space->select.sel_info.hslab) { /* Allocate a span info node */ - if(NULL == (head = H5FL_MALLOC(H5S_hyper_span_info_t))) + if(NULL == (head = H5FL_CALLOC(H5S_hyper_span_info_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Set the reference count */ head->count = 1; - /* Reset the scratch pad space */ - head->scratch = 0; - /* Build span tree for this coordinate */ if(NULL == (head->head = H5S_hyper_coord_to_span(rank, coords))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + /* Update the tail pointer of this newly created span in dimension "rank" */ + head->tail = head->head; + /* Allocate selection info */ if(NULL == (space->select.sel_info.hslab = H5FL_MALLOC(H5S_hyper_sel_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info") @@ -3568,7 +3561,7 @@ H5S_hyper_add_span_element(H5S_t *space, unsigned rank, hsize_t *coords) space->select.type = H5S_sel_hyper; /* Reset "regular" hyperslab flag */ - space->select.sel_info.hslab->diminfo_valid = FALSE; + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; /* Set # of elements in selection */ space->select.num_elem = 1; @@ -3587,7 +3580,7 @@ done: H5S_hyper_free_span_info(head); FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_add_span_element() */ +} /* end H5S_hyper_add_span_element() */ /*-------------------------------------------------------------------------- @@ -3621,7 +3614,7 @@ H5S_hyper_reset_scratch(H5S_t *space) H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst, NULL); FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_reset_scratch() */ +} /* end H5S_hyper_reset_scratch() */ /*-------------------------------------------------------------------------- @@ -3691,126 +3684,7 @@ H5S_hyper_convert(H5S_t *space) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_convert() */ - -#ifdef LATER - -/*-------------------------------------------------------------------------- - NAME - H5S_hyper_intersect_helper - PURPOSE - Helper routine to detect intersections in span trees - USAGE - htri_t H5S_hyper_intersect_helper(spans1, spans2) - H5S_hyper_span_info_t *spans1; IN: First span tree to operate with - H5S_hyper_span_info_t *spans2; IN: Second span tree to operate with - RETURNS - Non-negative on success, negative on failure - DESCRIPTION - Quickly detect intersections between two span trees - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -static htri_t -H5S_hyper_intersect_helper (H5S_hyper_span_info_t *spans1, H5S_hyper_span_info_t *spans2) -{ - H5S_hyper_span_t *curr1; /* Pointer to current span in 1st span tree */ - H5S_hyper_span_t *curr2; /* Pointer to current span in 2nd span tree */ - htri_t status; /* Status from recursive call */ - htri_t ret_value=FALSE; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Sanity check */ - HDassert((spans1 && spans2) || (spans1 == NULL && spans2 == NULL)); - - /* "NULL" span trees compare as overlapping */ - if(spans1==NULL && spans2==NULL) - HGOTO_DONE(TRUE); - - /* Get the span lists for each span in this tree */ - curr1=spans1->head; - curr2=spans2->head; - - /* Iterate over the spans in each tree */ - while(curr1!=NULL && curr2!=NULL) { - /* Check for 1st span entirely before 2nd span */ - if(curr1->high<curr2->low) - curr1=curr1->next; - /* Check for 2nd span entirely before 1st span */ - else if(curr2->high<curr1->low) - curr2=curr2->next; - /* Spans must overlap */ - else { - /* Recursively check spans in next dimension down */ - if((status=H5S_hyper_intersect_helper(curr1->down,curr2->down))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check") - - /* If there is a span intersection in the down dimensions, the span trees overlap */ - if(status==TRUE) - HGOTO_DONE(TRUE); - - /* No intersection in down dimensions, advance to next span */ - if(curr1->high<curr2->high) - curr1=curr1->next; - else - curr2=curr2->next; - } /* end else */ - } /* end while */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_intersect_helper() */ - - -/*-------------------------------------------------------------------------- - NAME - H5S_hyper_intersect - PURPOSE - Detect intersections in span trees - USAGE - htri_t H5S_hyper_intersect(space1, space2) - H5S_t *space1; IN: First dataspace to operate on span tree - H5S_t *space2; IN: Second dataspace to operate on span tree - RETURNS - Non-negative on success, negative on failure - DESCRIPTION - Quickly detect intersections between two span trees - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -htri_t -H5S_hyper_intersect (H5S_t *space1, H5S_t *space2) -{ - htri_t ret_value=FAIL; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Sanity check */ - HDassert(space1); - HDassert(space2); - - /* Check that the space selections both have span trees */ - if(space1->select.sel_info.hslab->span_lst==NULL || - space2->select.sel_info.hslab->span_lst==NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree") - - /* Check that the dataspaces are both the same rank */ - if(space1->extent.rank!=space2->extent.rank) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "dataspace ranks don't match") - - /* Perform the span-by-span intersection check */ - if((ret_value=H5S_hyper_intersect_helper(space1->select.sel_info.hslab->span_lst,space2->select.sel_info.hslab->span_lst))<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check") - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_intersect() */ -#endif /* LATER */ +} /* end H5S_hyper_convert() */ /*-------------------------------------------------------------------------- @@ -3834,7 +3708,8 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static htri_t -H5S_hyper_intersect_block_helper (const H5S_hyper_span_info_t *spans, hsize_t *start, hsize_t *end) +H5S_hyper_intersect_block_helper(const H5S_hyper_span_info_t *spans, + const hsize_t *start, const hsize_t *end) { H5S_hyper_span_t *curr; /* Pointer to current span in 1st span tree */ htri_t status; /* Status from recursive call */ @@ -3880,7 +3755,7 @@ H5S_hyper_intersect_block_helper (const H5S_hyper_span_info_t *spans, hsize_t *s done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_intersect_block_helper() */ +} /* end H5S_hyper_intersect_block_helper() */ /*-------------------------------------------------------------------------- @@ -3903,9 +3778,9 @@ done: REVISION LOG --------------------------------------------------------------------------*/ htri_t -H5S_hyper_intersect_block (H5S_t *space, hsize_t *start, hsize_t *end) +H5S_hyper_intersect_block(H5S_t *space, const hsize_t *start, const hsize_t *end) { - htri_t ret_value=FAIL; /* Return value */ + htri_t ret_value = FAIL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -3916,30 +3791,30 @@ H5S_hyper_intersect_block (H5S_t *space, hsize_t *start, hsize_t *end) /* Check for 'all' selection, instead of a hyperslab selection */ /* (Technically, this shouldn't be in the "hyperslab" routines...) */ - if(H5S_GET_SELECT_TYPE(space)==H5S_SEL_ALL) + if(H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL) HGOTO_DONE(TRUE); /* Check that the space selection has a span tree */ - if(space->select.sel_info.hslab->span_lst==NULL) - if(H5S_hyper_generate_spans(space)<0) + if(space->select.sel_info.hslab->span_lst == NULL) + if(H5S_hyper_generate_spans(space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree") /* Perform the span-by-span intersection check */ - if((ret_value=H5S_hyper_intersect_block_helper(space->select.sel_info.hslab->span_lst,start,end))<0) + if((ret_value = H5S_hyper_intersect_block_helper(space->select.sel_info.hslab->span_lst, start, end)) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab intersection check") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_intersect_block() */ +} /* end H5S_hyper_intersect_block() */ /*-------------------------------------------------------------------------- NAME - H5S_hyper_adjust_helper_u + H5S_hyper_adjust_u_helper PURPOSE Helper routine to adjust offsets in span trees USAGE - herr_t H5S_hyper_adjust_helper_u(spans, offset) + herr_t H5S_hyper_adjust_u_helper(spans, offset) H5S_hyper_span_info_t *spans; IN: Span tree to operate with const hsize_t *offset; IN: Offset to subtract RETURNS @@ -3952,7 +3827,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_adjust_helper_u (H5S_hyper_span_info_t *spans, const hsize_t *offset) +H5S_hyper_adjust_u_helper(H5S_hyper_span_info_t *spans, const hsize_t *offset) { H5S_hyper_span_t *span; /* Pointer to current span in span tree */ @@ -3979,7 +3854,7 @@ H5S_hyper_adjust_helper_u (H5S_hyper_span_info_t *spans, const hsize_t *offset) /* Recursively adjust spans in next dimension down */ if(span->down!=NULL) - H5S_hyper_adjust_helper_u(span->down,offset+1); + H5S_hyper_adjust_u_helper(span->down,offset+1); /* Advance to next span in this dimension */ span=span->next; @@ -3987,7 +3862,7 @@ H5S_hyper_adjust_helper_u (H5S_hyper_span_info_t *spans, const hsize_t *offset) } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_adjust_helper_u() */ +} /* end H5S_hyper_adjust_u_helper() */ /*-------------------------------------------------------------------------- @@ -4011,8 +3886,9 @@ H5S_hyper_adjust_helper_u (H5S_hyper_span_info_t *spans, const hsize_t *offset) static herr_t H5S_hyper_adjust_u(H5S_t *space, const hsize_t *offset) { + hbool_t update_bound = FALSE; /* Indicate whether to update bound */ unsigned u; /* Local index variable */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -4020,25 +3896,39 @@ H5S_hyper_adjust_u(H5S_t *space, const hsize_t *offset) HDassert(offset); /* Subtract the offset from the "regular" coordinates, if they exist */ - if(space->select.sel_info.hslab->diminfo_valid) { - for(u=0; u<space->extent.rank; u++) { - HDassert(space->select.sel_info.hslab->opt_diminfo[u].start>=offset[u]); - space->select.sel_info.hslab->opt_diminfo[u].start-=offset[u]; + /* (No need to rebuild the dimension info yet -QAK) */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { + for(u = 0; u < space->extent.rank; u++) { + HDassert(space->select.sel_info.hslab->opt_diminfo[u].start >= offset[u]); + space->select.sel_info.hslab->opt_diminfo[u].start -= offset[u]; } /* end for */ + + update_bound = TRUE; } /* end if */ /* Subtract the offset from the span tree coordinates, if they exist */ if(space->select.sel_info.hslab->span_lst) { - if(H5S_hyper_adjust_helper_u(space->select.sel_info.hslab->span_lst,offset)<0) + if(H5S_hyper_adjust_u_helper(space->select.sel_info.hslab->span_lst, offset) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab offset adjustment") /* Reset the scratch pointers for the next routine which needs them */ H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst, NULL); + + update_bound = TRUE; + } /* end if */ + + if(update_bound) { + /* Update the bound box of this hyperslab */ + for(u = 0; u < space->extent.rank; u++) { + HDassert(space->select.low_bounds[u] >= offset[u]); + space->select.low_bounds[u] -= offset[u]; + space->select.high_bounds[u] -= offset[u]; + } /* end for */ } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_adjust_u() */ +} /* end H5S_hyper_adjust_u() */ /*------------------------------------------------------------------------- @@ -4067,7 +3957,8 @@ H5S_hyper_project_scalar(const H5S_t *space, hsize_t *offset) HDassert(offset); /* Check for a "regular" hyperslab selection */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (No need to rebuild the dimension info yet -QAK) */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { const H5S_hyper_dim_t *diminfo = space->select.sel_info.hslab->opt_diminfo; /* Alias for dataspace's diminfo information */ unsigned u; /* Counter */ @@ -4102,11 +3993,11 @@ H5S_hyper_project_scalar(const H5S_t *space, hsize_t *offset) } /* end else */ /* Calculate offset of selection in projected buffer */ - *offset = H5VM_array_offset(space->extent.rank, space->extent.size, block); + *offset = H5VM_array_offset(space->extent.rank, space->extent.size, block); done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_project_scalar() */ +} /* end H5S_hyper_project_scalar() */ /*------------------------------------------------------------------------- @@ -4127,6 +4018,7 @@ H5S_hyper_project_simple_lower(const H5S_t *base_space, H5S_t *new_space) { H5S_hyper_span_info_t *down; /* Pointer to list of spans */ unsigned curr_dim; /* Current dimension being operated on */ + unsigned u; /* Local index variable */ FUNC_ENTER_NOAPI_NOINIT_NOERR @@ -4148,12 +4040,18 @@ H5S_hyper_project_simple_lower(const H5S_t *base_space, H5S_t *new_space) } /* end while */ HDassert(down); + /* Update the bounding box */ + for(u = 0; u < new_space->extent.rank; u++) { + new_space->select.low_bounds[u] = base_space->select.low_bounds[u + curr_dim]; + new_space->select.high_bounds[u] = base_space->select.high_bounds[u + curr_dim]; + } /* end for */ + /* Share the underlying hyperslab span information */ new_space->select.sel_info.hslab->span_lst = down; new_space->select.sel_info.hslab->span_lst->count++; FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_project_simple_lower() */ +} /* end H5S_hyper_project_simple_lower() */ /*------------------------------------------------------------------------- @@ -4174,6 +4072,7 @@ H5S_hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space) { H5S_hyper_span_t *prev_span = NULL; /* Pointer to previous list of spans */ unsigned curr_dim; /* Current dimension being operated on */ + unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -4191,7 +4090,7 @@ H5S_hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space) H5S_hyper_span_t *new_span; /* Temporary hyperslab span */ /* Allocate a new span_info node */ - if(NULL == (new_span_info = H5FL_MALLOC(H5S_hyper_span_info_t))) { + if(NULL == (new_span_info = H5FL_CALLOC(H5S_hyper_span_info_t))) { if(prev_span) if(H5S_hyper_free_span(prev_span) < 0) HERROR(H5E_DATASPACE, H5E_CANTFREE, "can't free hyperslab span"); @@ -4203,7 +4102,7 @@ H5S_hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space) prev_span->down = new_span_info; /* Allocate a new node */ - if(NULL == (new_span = H5S_hyper_new_span(0, 0, NULL, NULL))) { + if(NULL == (new_span = H5S_hyper_new_span((hsize_t)0, (hsize_t)0, NULL, NULL))) { HDassert(new_span_info); if(!prev_span) (void)H5FL_FREE(H5S_hyper_span_info_t, new_span_info); @@ -4212,8 +4111,8 @@ H5S_hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space) /* Set the span_info information */ new_span_info->count = 1; - new_span_info->scratch = NULL; new_span_info->head = new_span; + new_span_info->tail = new_span; /* Attach to new space, if top span info */ if(NULL == new_space->select.sel_info.hslab->span_lst) @@ -4228,6 +4127,16 @@ H5S_hyper_project_simple_higher(const H5S_t *base_space, H5S_t *new_space) HDassert(new_space->select.sel_info.hslab->span_lst); HDassert(prev_span); + /* Update the bounding box */ + for(u = 0; u < curr_dim; u++) { + new_space->select.low_bounds[u] = 0; + new_space->select.high_bounds[u] = 0; + } /* end for */ + for(; u < new_space->extent.rank; u++) { + new_space->select.low_bounds[u] = base_space->select.low_bounds[u - curr_dim]; + new_space->select.high_bounds[u] = base_space->select.high_bounds[u - curr_dim]; + } /* end for */ + /* Share the underlying hyperslab span information */ prev_span->down = base_space->select.sel_info.hslab->span_lst; prev_span->down->count++; @@ -4243,7 +4152,7 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_project_simple_higher() */ +} /* end H5S_hyper_project_simple_higher() */ /*------------------------------------------------------------------------- @@ -4280,21 +4189,22 @@ H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info") /* Check for a "regular" hyperslab selection */ - if(base_space->select.sel_info.hslab->diminfo_valid) { + /* (No need to rebuild the dimension info yet -QAK) */ + if(base_space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { unsigned base_space_dim; /* Current dimension in the base dataspace */ unsigned new_space_dim; /* Current dimension in the new dataspace */ + unsigned u; /* Local index variable */ /* Check if the new space's rank is < or > base space's rank */ if(new_space->extent.rank < base_space->extent.rank) { const H5S_hyper_dim_t *opt_diminfo = base_space->select.sel_info.hslab->opt_diminfo; /* Alias for dataspace's diminfo information */ hsize_t block[H5S_MAX_RANK]; /* Block selected in base dataspace */ - unsigned u; /* Local index variable */ /* Compute the offset for the down-projection */ HDmemset(block, 0, sizeof(block)); for(u = 0; u < (base_space->extent.rank - new_space->extent.rank); u++) block[u] = opt_diminfo[u].start; - *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block); + *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block); /* Set the correct dimensions for the base & new spaces */ base_space_dim = base_space->extent.rank - new_space->extent.rank; @@ -4325,22 +4235,22 @@ H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off /* Copy the diminfo */ while(base_space_dim < base_space->extent.rank) { - new_space->select.sel_info.hslab->app_diminfo[new_space_dim].start = + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].start = base_space->select.sel_info.hslab->app_diminfo[base_space_dim].start; - new_space->select.sel_info.hslab->app_diminfo[new_space_dim].stride = + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].stride = base_space->select.sel_info.hslab->app_diminfo[base_space_dim].stride; - new_space->select.sel_info.hslab->app_diminfo[new_space_dim].count = + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].count = base_space->select.sel_info.hslab->app_diminfo[base_space_dim].count; - new_space->select.sel_info.hslab->app_diminfo[new_space_dim].block = + new_space->select.sel_info.hslab->app_diminfo[new_space_dim].block = base_space->select.sel_info.hslab->app_diminfo[base_space_dim].block; - new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].start = + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].start = base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].start; new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].stride = base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].stride; - new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].count = + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].count = base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].count; - new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].block = + new_space->select.sel_info.hslab->opt_diminfo[new_space_dim].block = base_space->select.sel_info.hslab->opt_diminfo[base_space_dim].block; /* Advance to next dimensions */ @@ -4348,8 +4258,14 @@ H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off new_space_dim++; } /* end for */ + /* Update the bounding box */ + for(u = 0; u < new_space->extent.rank; u++) { + new_space->select.low_bounds[u] = new_space->select.sel_info.hslab->opt_diminfo[u].start; + new_space->select.high_bounds[u] = new_space->select.low_bounds[u] + new_space->select.sel_info.hslab->opt_diminfo[u].stride * (new_space->select.sel_info.hslab->opt_diminfo[u].count - 1) + (new_space->select.sel_info.hslab->opt_diminfo[u].block - 1); + } /* end for */ + /* Indicate that the dimension information is valid */ - new_space->select.sel_info.hslab->diminfo_valid = TRUE; + new_space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES; /* Indicate that there's no slab information */ new_space->select.sel_info.hslab->span_lst = NULL; @@ -4377,7 +4293,7 @@ H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off } /* end while */ /* Compute the offset for the down-projection */ - *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block); + *offset = H5VM_array_offset(base_space->extent.rank, base_space->extent.size, block); /* Project the base space's selection down in less dimensions */ if(H5S_hyper_project_simple_lower(base_space, new_space) < 0) @@ -4389,13 +4305,13 @@ H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off /* The offset is zero when projected into higher dimensions */ *offset = 0; - /* Project the base space's selection down in less dimensions */ + /* Project the base space's selection down in more dimensions */ if(H5S_hyper_project_simple_higher(base_space, new_space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't project hyperslab selection into less dimensions") } /* end else */ - /* Indicate that the dimension information is not valid */ - new_space->select.sel_info.hslab->diminfo_valid = FALSE; + /* Copy the status of the dimension information */ + new_space->select.sel_info.hslab->diminfo_valid = base_space->select.sel_info.hslab->diminfo_valid; } /* end else */ /* Number of elements selected will be the same */ @@ -4406,16 +4322,16 @@ H5S_hyper_project_simple(const H5S_t *base_space, H5S_t *new_space, hsize_t *off done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_project_simple() */ +} /* end H5S_hyper_project_simple() */ /*-------------------------------------------------------------------------- NAME - H5S_hyper_adjust_helper_s + H5S_hyper_adjust_s_helper PURPOSE Helper routine to adjust offsets in span trees USAGE - herr_t H5S_hyper_adjust_helper_s(spans, offset) + herr_t H5S_hyper_adjust_s_helper(spans, offset) H5S_hyper_span_info_t *spans; IN: Span tree to operate with const hssize_t *offset; IN: Offset to subtract RETURNS @@ -4428,7 +4344,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_adjust_helper_s(H5S_hyper_span_info_t *spans, const hssize_t *offset) +H5S_hyper_adjust_s_helper(H5S_hyper_span_info_t *spans, const hssize_t *offset) { H5S_hyper_span_t *span; /* Pointer to current span in span tree */ @@ -4455,7 +4371,7 @@ H5S_hyper_adjust_helper_s(H5S_hyper_span_info_t *spans, const hssize_t *offset) /* Recursively adjust spans in next dimension down */ if(span->down != NULL) - H5S_hyper_adjust_helper_s(span->down, offset + 1); + H5S_hyper_adjust_s_helper(span->down, offset + 1); /* Advance to next span in this dimension */ span = span->next; @@ -4463,7 +4379,7 @@ H5S_hyper_adjust_helper_s(H5S_hyper_span_info_t *spans, const hssize_t *offset) } /* end if */ FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_adjust_helper_s() */ +} /* end H5S_hyper_adjust_s_helper() */ /*-------------------------------------------------------------------------- @@ -4487,6 +4403,7 @@ H5S_hyper_adjust_helper_s(H5S_hyper_span_info_t *spans, const hssize_t *offset) herr_t H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset) { + hbool_t update_bound = FALSE; /* Indicate whether to update bound */ unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ @@ -4496,25 +4413,42 @@ H5S_hyper_adjust_s(H5S_t *space, const hssize_t *offset) HDassert(offset); /* Subtract the offset from the "regular" coordinates, if they exist */ - if(space->select.sel_info.hslab->diminfo_valid) { + /* (No need to rebuild the dimension info yet -QAK) */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { for(u = 0; u < space->extent.rank; u++) { HDassert((hssize_t)space->select.sel_info.hslab->opt_diminfo[u].start >= offset[u]); space->select.sel_info.hslab->opt_diminfo[u].start = (hsize_t)((hssize_t)space->select.sel_info.hslab->opt_diminfo[u].start - offset[u]); } /* end for */ + + update_bound = TRUE; } /* end if */ /* Subtract the offset from the span tree coordinates, if they exist */ if(space->select.sel_info.hslab->span_lst) { - if(H5S_hyper_adjust_helper_s(space->select.sel_info.hslab->span_lst, offset) < 0) + if(H5S_hyper_adjust_s_helper(space->select.sel_info.hslab->span_lst, offset) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_BADSELECT, FAIL, "can't perform hyperslab offset adjustment") /* Reset the scratch pointers for the next routine which needs them */ H5S_hyper_span_scratch(space->select.sel_info.hslab->span_lst, NULL); + + update_bound = TRUE; + } /* end if */ + + if(update_bound) { + /* Update the bound box of this hyperslab */ + for(u = 0; u < space->extent.rank; u++) { + hssize_t tmp = (hssize_t)space->select.low_bounds[u]; + + HDassert(tmp >= offset[u]); + space->select.low_bounds[u] = (hsize_t)(tmp - offset[u]); + tmp = (hssize_t)space->select.high_bounds[u]; + space->select.high_bounds[u] = (hsize_t)(tmp - offset[u]); + } /* end for */ } /* end if */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_adjust_s() */ +} /* end H5S_hyper_adjust_s() */ /*-------------------------------------------------------------------------- @@ -4569,7 +4503,7 @@ H5S_hyper_normalize_offset(H5S_t *space, hssize_t *old_offset) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_normalize_offset() */ +} /* end H5S_hyper_normalize_offset() */ /*-------------------------------------------------------------------------- @@ -4612,7 +4546,7 @@ H5S_hyper_denormalize_offset(H5S_t *space, const hssize_t *old_offset) done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_denormalize_offset() */ +} /* end H5S_hyper_denormalize_offset() */ /*-------------------------------------------------------------------------- @@ -4638,7 +4572,8 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_append_span (H5S_hyper_span_t **prev_span, H5S_hyper_span_info_t ** span_tree, hsize_t low, hsize_t high, H5S_hyper_span_info_t *down, H5S_hyper_span_t *next) +H5S_hyper_append_span(H5S_hyper_span_t **prev_span, H5S_hyper_span_info_t **span_tree, + hsize_t low, hsize_t high, H5S_hyper_span_info_t *down, H5S_hyper_span_t *next) { H5S_hyper_span_t *new_span = NULL; herr_t ret_value = SUCCEED; /* Return value */ @@ -4649,51 +4584,51 @@ H5S_hyper_append_span (H5S_hyper_span_t **prev_span, H5S_hyper_span_info_t ** sp HDassert(span_tree); /* Check for adding first node to merged spans */ - if(*prev_span==NULL) { + if(*prev_span == NULL) { /* Allocate new span node to append to list */ - if((new_span = H5S_hyper_new_span(low,high,down,next))==NULL) + if(NULL == (new_span = H5S_hyper_new_span(low, high, down, next))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Make first node in span list */ /* Check that we haven't already allocated a span tree */ - HDassert(*span_tree==NULL); + HDassert(*span_tree == NULL); /* Allocate a new span_info node */ - if((*span_tree = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) + if(NULL == (*span_tree = H5FL_CALLOC(H5S_hyper_span_info_t))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Set the span tree's basic information */ - (*span_tree)->count=1; - (*span_tree)->scratch=NULL; - (*span_tree)->head=new_span; + (*span_tree)->count = 1; + (*span_tree)->head = new_span; + (*span_tree)->tail = new_span; /* Update previous merged span */ - *prev_span=new_span; + *prev_span = new_span; } /* end if */ /* Merge or append to existing merged spans list */ else { /* Check if span can just extend the previous merged span */ - if((((*prev_span)->high+1)==low) && - H5S_hyper_cmp_spans(down,(*prev_span)->down)==TRUE) { + if((((*prev_span)->high + 1) == low) && + TRUE == H5S_hyper_cmp_spans(down, (*prev_span)->down)) { /* Extend previous merged span to include new high bound */ - (*prev_span)->high=high; - (*prev_span)->nelem+=(high-low)+1; + (*prev_span)->high = high; + (*prev_span)->nelem += (high - low) + 1; } /* end if */ else { /* Allocate new span node to append to list */ - if((new_span = H5S_hyper_new_span(low,high,down,next))==NULL) + if(NULL == (new_span = H5S_hyper_new_span(low, high, down, next))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Check if there is actually a down span */ if(new_span->down) { /* Check if the down spans for the new span node are the same as the previous span node */ - if(H5S_hyper_cmp_spans(new_span->down,(*prev_span)->down)==TRUE) { + if(TRUE == H5S_hyper_cmp_spans(new_span->down, (*prev_span)->down)) { /* Release the down span for the new node */ H5S_hyper_free_span_info(new_span->down); /* Point the new node's down span at the previous node's down span */ - new_span->down=(*prev_span)->down; + new_span->down = (*prev_span)->down; /* Increment the reference count to the shared down span */ new_span->down->count++; @@ -4701,23 +4636,23 @@ H5S_hyper_append_span (H5S_hyper_span_t **prev_span, H5S_hyper_span_info_t ** sp } /* end if */ /* Indicate elements from previous span */ - new_span->pstride=low-(*prev_span)->low; + new_span->pstride = low - (*prev_span)->low; /* Append to end of merged spans list */ - (*prev_span)->next=new_span; - *prev_span=new_span; + (*prev_span)->next = new_span; + *prev_span = new_span; + + (*span_tree)->tail = new_span; } /* end else */ } /* end else */ done: - if(ret_value < 0) { - if(new_span) - if(H5S_hyper_free_span(new_span) < 0) - HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "failed to release new hyperslab span") - } /* end if */ + if(ret_value < 0) + if(new_span && H5S_hyper_free_span(new_span) < 0) + HDONE_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "failed to release new hyperslab span") FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_append_span() */ +} /* end H5S_hyper_append_span() */ /*-------------------------------------------------------------------------- @@ -4726,9 +4661,24 @@ done: PURPOSE Clip a new span tree against the current spans in the hyperslab selection USAGE - herr_t H5S_hyper_clip_spans(span_a, span_b, a_not_b, a_and_b, b_not_a) + herr_t H5S_hyper_clip_spans(span_a, span_b, selector, cur_dim, dim_size, + span_a_b_bounds[4], all_clips_bound, + a_not_b, a_and_b, b_not_a) H5S_hyper_span_t *a_spans; IN: Span tree 'a' to clip with. H5S_hyper_span_t *b_spans; IN: Span tree 'b' to clip with. + unsigned int selector; IN: The parameter deciding which output is needed + (only considering the last three bits ABC: + If A is set, then a_not_b is needed; + If B is set, then a_and_b is needed; + If C is set, then b_not_a is needed; + ) + unsigned int cur_dim; IN: The dimension in which this clip operation + is performed. + unsigned int dim_size; IN: The dimension size. + const hsize_t *span_a_b_bounds[4]; IN: The bound box of span a and span b. + hsize_t *all_clips_bounds; OUT: The array containing the bounds box + of all three clipped span tree in the order + a_not_b, a_and_b and b_not_a. H5S_hyper_span_t **a_not_b; OUT: Span tree of 'a' hyperslab spans which doesn't overlap with 'b' hyperslab spans. @@ -4751,21 +4701,29 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans, +H5S_hyper_clip_spans(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans, + unsigned int selector, unsigned cur_dim, unsigned dim_size, + const hsize_t *span_a_b_bounds[4], hsize_t *all_clips_bounds, H5S_hyper_span_info_t **a_not_b, H5S_hyper_span_info_t **a_and_b, H5S_hyper_span_info_t **b_not_a) { - H5S_hyper_span_t *span_a; /* Pointer to a node in span tree 'a' */ - H5S_hyper_span_t *span_b; /* Pointer to a node in span tree 'b' */ - H5S_hyper_span_t *tmp_span; /* Temporary pointer to new span */ - H5S_hyper_span_t *last_a_not_b; /* Pointer to previous node in span tree 'a_not_b' */ - H5S_hyper_span_t *last_a_and_b; /* Pointer to previous node in span tree 'a_and_b' */ - H5S_hyper_span_t *last_b_not_a; /* Pointer to previous node in span tree 'b_not_a' */ - H5S_hyper_span_info_t *down_a_not_b; /* Temporary pointer to a_not_b span tree of down spans for overlapping nodes */ - H5S_hyper_span_info_t *down_a_and_b; /* Temporary pointer to a_and_b span tree of down spans for overlapping nodes */ - H5S_hyper_span_info_t *down_b_not_a; /* Temporary pointer to b_and_a span tree of down spans for overlapping nodes */ - unsigned recover_a, recover_b; /* Flags to indicate when to recover temporary spans */ - herr_t ret_value=SUCCEED; /* Return value */ + H5S_hyper_span_t *span_a; /* Pointer to a node in span tree 'a' */ + H5S_hyper_span_t *span_b; /* Pointer to a node in span tree 'b' */ + const hsize_t *span_a_low_bounds; /* The low bound array for span a */ + const hsize_t *span_a_high_bounds; /* The high bound array for span a */ + const hsize_t *span_b_low_bounds; /* The low bound array for span b */ + const hsize_t *span_b_high_bounds; /* The high bound array for span b */ + hsize_t *a_not_b_low_bounds; /* The low bound array for a_not_b */ + hsize_t *a_not_b_high_bounds; /* The high bound array for a_not_b */ + hsize_t *a_and_b_low_bounds; /* The low bound array for a_and_b */ + hsize_t *a_and_b_high_bounds; /* The high bound array for a_and_b */ + hsize_t *b_not_a_low_bounds; /* The low bound array for b_not_a */ + hsize_t *b_not_a_high_bounds; /* The high bound array for b_not_a */ + hbool_t need_a_not_b = FALSE; /* Whether to generate a_not_b list */ + hbool_t need_a_and_b = FALSE; /* Whether to generate a_and_b list */ + hbool_t need_b_not_a = FALSE; /* Whether to generate b_not_a list */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -4775,76 +4733,151 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s HDassert(a_not_b); HDassert(a_and_b); HDassert(b_not_a); + HDassert(cur_dim < dim_size); + HDassert(all_clips_bounds); + HDassert(span_a_b_bounds); + + /* Set the values of bound box pointers */ + span_a_low_bounds = span_a_b_bounds[0]; + span_a_high_bounds = span_a_b_bounds[1]; + span_b_low_bounds = span_a_b_bounds[2]; + span_b_high_bounds = span_a_b_bounds[3]; + a_not_b_low_bounds = all_clips_bounds; + a_not_b_high_bounds = all_clips_bounds + dim_size; + a_and_b_low_bounds = all_clips_bounds + 2 * dim_size; + a_and_b_high_bounds = all_clips_bounds + 3 * dim_size; + b_not_a_low_bounds = all_clips_bounds + 4 * dim_size; + b_not_a_high_bounds = all_clips_bounds + 5 * dim_size; + + /* Set which list(s) to be generated, based on selector */ + if(H5S_HYPER_COMPUTE_B_NOT_A == (selector & H5S_HYPER_COMPUTE_B_NOT_A)) + need_b_not_a = TRUE; + if(H5S_HYPER_COMPUTE_A_AND_B == (selector & H5S_HYPER_COMPUTE_A_AND_B)) + need_a_and_b = TRUE; + if(H5S_HYPER_COMPUTE_A_NOT_B == (selector & H5S_HYPER_COMPUTE_A_NOT_B)) + need_a_not_b = TRUE; /* Check if both span trees are not defined */ - if(a_spans==NULL && b_spans==NULL) { - *a_not_b=NULL; - *a_and_b=NULL; - *b_not_a=NULL; + if(a_spans == NULL && b_spans == NULL) { + *a_not_b = NULL; + *a_and_b = NULL; + *b_not_a = NULL; } /* end if */ /* If span 'a' is not defined, but 'b' is, copy 'b' and set the other return span trees to empty */ - else if(a_spans==NULL) { - *a_not_b=NULL; - *a_and_b=NULL; - if((*b_not_a=H5S_hyper_copy_span(b_spans))==NULL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree") + else if(a_spans == NULL) { + *a_not_b = NULL; + *a_and_b = NULL; + if(need_b_not_a) { + if(NULL == (*b_not_a = H5S_hyper_copy_span(b_spans))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree") + + /* update b_not_a's bound box based on the values from span_b's bound box */ + for(u = cur_dim; u < dim_size; u++) { + b_not_a_low_bounds[u] = MIN(b_not_a_low_bounds[u], span_b_low_bounds[u]); + b_not_a_high_bounds[u] = MAX(b_not_a_high_bounds[u], span_b_high_bounds[u]); + } /* end for */ + } /* end if */ + else + *b_not_a = NULL; } /* end if */ /* If span 'b' is not defined, but 'a' is, copy 'a' and set the other return span trees to empty */ - else if(b_spans==NULL) { - if((*a_not_b=H5S_hyper_copy_span(a_spans))==NULL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree") - *a_and_b=NULL; - *b_not_a=NULL; + else if(b_spans == NULL) { + *a_and_b = NULL; + *b_not_a = NULL; + if(need_a_not_b) { + if(NULL == (*a_not_b = H5S_hyper_copy_span(a_spans))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree") + + /* update b_not_a's bound box based on the values from span_a's bound box */ + for(u = cur_dim; u < dim_size; u++) { + a_not_b_low_bounds[u] = MIN(a_not_b_low_bounds[u], span_a_low_bounds[u]); + a_not_b_high_bounds[u] = MAX(a_not_b_high_bounds[u], span_a_high_bounds[u]); + } /* end for */ + } /* end if */ + else + *a_not_b = NULL; } /* end if */ /* If span 'a' and 'b' are both defined, calculate the proper span trees */ else { /* Check if both span trees completely overlap */ - if(H5S_hyper_cmp_spans(a_spans,b_spans)==TRUE) { - *a_not_b=NULL; - if((*a_and_b=H5S_hyper_copy_span(a_spans))==NULL) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree") - *b_not_a=NULL; + if(H5S_hyper_cmp_spans(a_spans, b_spans) == TRUE) { + *a_not_b = NULL; + *b_not_a = NULL; + if(need_a_and_b) { + if(NULL == (*a_and_b = H5S_hyper_copy_span(a_spans))) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, FAIL, "can't copy hyperslab span tree") + + /* update a_and_b's bound box based on the values from span_a's bound box */ + for(u = cur_dim; u < dim_size; u++) { + a_and_b_low_bounds[u] = MIN(a_and_b_low_bounds[u], span_a_low_bounds[u]); + a_and_b_high_bounds[u] = MAX(a_and_b_high_bounds[u], span_a_high_bounds[u]); + } /* end for */ + } /* end if */ + else + *a_and_b = NULL; } /* end if */ else { + H5S_hyper_span_t *last_a_not_b; /* Pointer to previous node in span tree 'a_not_b' */ + H5S_hyper_span_t *last_a_and_b; /* Pointer to previous node in span tree 'a_and_b' */ + H5S_hyper_span_t *last_b_not_a; /* Pointer to previous node in span tree 'b_not_a' */ + hbool_t update_a_not_b_bounds, update_b_not_a_bounds; /* Flags to indicate that bounds should be updated */ + hbool_t recover_a, recover_b; /* Flags to indicate when to recover temporary spans */ + /* Get the pointers to the new and old span lists */ - span_a=a_spans->head; - span_b=b_spans->head; + span_a = a_spans->head; + span_b = b_spans->head; - /* Set the pointer to the previous spans */ - last_a_not_b=NULL; - last_a_and_b=NULL; - last_b_not_a=NULL; + /* Reset the pointers to the previous spans */ + last_a_not_b = last_a_and_b = last_b_not_a = NULL; /* No spans to recover yet */ - recover_a=recover_b=0; + recover_a = recover_b = FALSE; + + /* No bounds to update yet */ + update_a_not_b_bounds = update_b_not_a_bounds = FALSE; /* Work through the list of spans in the new list */ - while(span_a!=NULL && span_b!=NULL) { + while(span_a != NULL && span_b != NULL) { + H5S_hyper_span_info_t *down_a_not_b; /* Temporary pointer to a_not_b span tree of down spans for overlapping nodes */ + H5S_hyper_span_info_t *down_a_and_b; /* Temporary pointer to a_and_b span tree of down spans for overlapping nodes */ + H5S_hyper_span_info_t *down_b_not_a; /* Temporary pointer to b_and_a span tree of down spans for overlapping nodes */ + H5S_hyper_span_t *tmp_span; /* Temporary pointer to new span */ + /* Check if span 'a' is completely before span 'b' */ /* AAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - if(span_a->high<span_b->low) { + if(span_a->high < span_b->low) { /* Copy span 'a' and add to a_not_b list */ /* Merge/add span 'a' with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_a->high,span_a->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_not_b) { + if(H5S_hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_a->high, span_a->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the a_not_b bounds should be updated */ + update_a_not_b_bounds = TRUE; + } /* end if */ /* Advance span 'a', leave span 'b' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); } /* end if */ /* Check if span 'a' overlaps only the lower bound */ /* of span 'b' , up to the upper bound of span 'b' */ /* AAAAAAAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if(span_a->low<span_b->low && (span_a->high>=span_b->low && span_a->high<=span_b->high)) { + else if(span_a->low < span_b->low && (span_a->high >= span_b->low && span_a->high <= span_b->high)) { /* Split span 'a' into two parts at the low bound of span 'b' */ /* Merge/add lower part of span 'a' with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_b->low-1,span_a->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_not_b) { + if(H5S_hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_b->low - 1, span_a->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the a_not_b bounds should be updated */ + update_a_not_b_bounds = TRUE; + } /* end if */ /* Check for overlaps between upper part of span 'a' and lower part of span 'b' */ @@ -4852,26 +4885,33 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL)); /* If there are no down spans, just add the overlapping area to the a_and_b list */ - if(span_a->down==NULL) { + if(span_a->down == NULL) { /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_b->low,span_a->high,NULL,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_and_b) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_b->low, span_a->high, NULL, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") } /* end if */ /* If there are down spans, check for the overlap in them and add to each appropriate list */ else { /* NULL out the temporary pointers to clipped areas in down spans */ - down_a_not_b=NULL; - down_a_and_b=NULL; - down_b_not_a=NULL; + down_a_not_b = NULL; + down_a_and_b = NULL; + down_b_not_a = NULL; /* Check for overlaps in the 'down spans' of span 'a' & 'b' */ - if(H5S_hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0) + /** Note: since the bound box of remaining dimensions + * has been updated in the following clip function (via + * all_clips_bounds), there's no need updating the bound box + * after each append call in the following codes */ + if(H5S_hyper_clip_spans(span_a->down, span_b->down, selector, cur_dim + 1, dim_size, span_a_b_bounds, all_clips_bounds, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") /* Check for additions to the a_not_b list */ - if(down_a_not_b!=NULL) { + if(down_a_not_b) { + HDassert(need_a_not_b == TRUE); + /* Merge/add overlapped part with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_b->low,span_a->high,down_a_not_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_not_b, a_not_b, span_b->low, span_a->high, down_a_not_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -4879,9 +4919,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the a_and_b list */ - if(down_a_and_b!=NULL) { + if(down_a_and_b) { + HDassert(need_a_and_b == TRUE); + /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_b->low,span_a->high,down_a_and_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_b->low, span_a->high, down_a_and_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -4889,9 +4931,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the b_not_a list */ - if(down_b_not_a!=NULL) { + if(down_b_not_a) { + HDassert(need_b_not_a == TRUE); + /* Merge/add overlapped part with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_a->high,down_b_not_a,NULL)==FAIL) + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_b->low, span_a->high, down_b_not_a, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -4902,23 +4946,23 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s /* Split off upper part of span 'b' at upper span of span 'a' */ /* Check if there is actually an upper part of span 'b' to split off */ - if(span_a->high<span_b->high) { + if(span_a->high < span_b->high) { /* Allocate new span node for upper part of span 'b' */ - if((tmp_span = H5S_hyper_new_span(span_a->high+1,span_b->high,span_b->down,span_b->next))==NULL) + if(NULL == (tmp_span = H5S_hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Advance span 'a' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); /* Make upper part of span 'b' into new span 'b' */ - H5S_hyper_recover_span(&recover_b,&span_b,tmp_span); - recover_b=1; + H5S_hyper_recover_span(&recover_b, &span_b, tmp_span); + recover_b = TRUE; } /* end if */ /* No upper part of span 'b' to split */ else { /* Advance both 'a' and 'b' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end else */ } /* end if */ /* Check if span 'a' overlaps the lower & upper bound */ @@ -4926,12 +4970,17 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s /* AAAAAAAAAAAAAAAAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if(span_a->low<span_b->low && span_a->high>span_b->high) { + else if(span_a->low < span_b->low && span_a->high > span_b->high) { /* Split off lower part of span 'a' at lower span of span 'b' */ /* Merge/add lower part of span 'a' with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_b->low-1,span_a->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_not_b) { + if(H5S_hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_b->low - 1, span_a->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the a_not_b bounds should be updated */ + update_a_not_b_bounds = TRUE; + } /* end if */ /* Check for overlaps between middle part of span 'a' and span 'b' */ @@ -4939,26 +4988,29 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL)); /* If there are no down spans, just add the overlapping area to the a_and_b list */ - if(span_a->down==NULL) { + if(span_a->down == NULL) { /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_b->low,span_b->high,NULL,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_and_b) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_b->low, span_b->high, NULL, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") } /* end if */ /* If there are down spans, check for the overlap in them and add to each appropriate list */ else { /* NULL out the temporary pointers to clipped areas in down spans */ - down_a_not_b=NULL; - down_a_and_b=NULL; - down_b_not_a=NULL; + down_a_not_b = NULL; + down_a_and_b = NULL; + down_b_not_a = NULL; /* Check for overlaps in the 'down spans' of span 'a' & 'b' */ - if(H5S_hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0) + if(H5S_hyper_clip_spans(span_a->down, span_b->down, selector, cur_dim + 1, dim_size, span_a_b_bounds, all_clips_bounds, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") /* Check for additions to the a_not_b list */ - if(down_a_not_b!=NULL) { + if(down_a_not_b) { + HDassert(need_a_not_b == TRUE); + /* Merge/add overlapped part with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_b->low,span_b->high,down_a_not_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_not_b, a_not_b,span_b->low, span_b->high, down_a_not_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -4966,9 +5018,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the a_and_b list */ - if(down_a_and_b!=NULL) { + if(down_a_and_b) { + HDassert(need_a_and_b == TRUE); + /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_b->low,span_b->high,down_a_and_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_b->low, span_b->high, down_a_and_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -4976,9 +5030,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the b_not_a list */ - if(down_b_not_a!=NULL) { + if(down_b_not_a) { + HDassert(need_b_not_a == TRUE); + /* Merge/add overlapped part with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_b->high,down_b_not_a,NULL)==FAIL) + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_b->low, span_b->high, down_b_not_a, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -4989,28 +5045,33 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s /* Split off upper part of span 'a' at upper span of span 'b' */ /* Allocate new span node for upper part of span 'a' */ - if((tmp_span = H5S_hyper_new_span(span_b->high+1,span_a->high,span_a->down,span_a->next))==NULL) + if(NULL == (tmp_span = H5S_hyper_new_span(span_b->high + 1, span_a->high, span_a->down, span_a->next))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Make upper part of span 'a' the new span 'a' */ - H5S_hyper_recover_span(&recover_a,&span_a,tmp_span); - recover_a=1; + H5S_hyper_recover_span(&recover_a, &span_a, tmp_span); + recover_a = TRUE; /* Advance span 'b' */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end if */ /* Check if span 'a' is entirely within span 'b' */ /* AAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if(span_a->low>=span_b->low && span_a->high<=span_b->high) { + else if(span_a->low >= span_b->low && span_a->high <= span_b->high) { /* Split off lower part of span 'b' at lower span of span 'a' */ /* Check if there is actually a lower part of span 'b' to split off */ - if(span_a->low>span_b->low) { + if(span_a->low > span_b->low) { /* Merge/add lower part of span 'b' with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_b_not_a) { + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_b->low, span_a->low - 1, span_b->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the b_not_a bounds should be updated */ + update_b_not_a_bounds = TRUE; + } /* end if */ } /* end if */ else { /* Keep going, nothing to split off */ @@ -5022,26 +5083,29 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL)); /* If there are no down spans, just add the overlapping area to the a_and_b list */ - if(span_a->down==NULL) { + if(span_a->down == NULL) { /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_a->high,NULL,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_and_b) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_a->low, span_a->high, NULL, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") } /* end if */ /* If there are down spans, check for the overlap in them and add to each appropriate list */ else { /* NULL out the temporary pointers to clipped areas in down spans */ - down_a_not_b=NULL; - down_a_and_b=NULL; - down_b_not_a=NULL; + down_a_not_b = NULL; + down_a_and_b = NULL; + down_b_not_a = NULL; /* Check for overlaps in the 'down spans' of span 'a' & 'b' */ - if(H5S_hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0) + if(H5S_hyper_clip_spans(span_a->down, span_b->down, selector, cur_dim + 1, dim_size, span_a_b_bounds, all_clips_bounds, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") /* Check for additions to the a_not_b list */ - if(down_a_not_b!=NULL) { + if(down_a_not_b) { + HDassert(need_a_not_b == TRUE); + /* Merge/add overlapped part with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_a->high,down_a_not_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_a->high, down_a_not_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -5049,9 +5113,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the a_and_b list */ - if(down_a_and_b!=NULL) { + if(down_a_and_b) { + HDassert(need_a_and_b == TRUE); + /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_a->high,down_a_and_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_a->low, span_a->high, down_a_and_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -5059,9 +5125,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the b_not_a list */ - if(down_b_not_a!=NULL) { + if(down_b_not_a) { + HDassert(need_b_not_a == TRUE); + /* Merge/add overlapped part with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_a->low,span_a->high,down_b_not_a,NULL)==FAIL) + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_a->low, span_a->high, down_b_not_a, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -5070,24 +5138,24 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end else */ /* Check if there is actually an upper part of span 'b' to split off */ - if(span_a->high<span_b->high) { + if(span_a->high < span_b->high) { /* Split off upper part of span 'b' at upper span of span 'a' */ /* Allocate new span node for upper part of spans 'a' */ - if((tmp_span = H5S_hyper_new_span(span_a->high+1,span_b->high,span_b->down,span_b->next))==NULL) + if(NULL == (tmp_span = H5S_hyper_new_span(span_a->high + 1, span_b->high, span_b->down, span_b->next))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* And advance span 'a' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); /* Make upper part of span 'b' the new span 'b' */ - H5S_hyper_recover_span(&recover_b,&span_b,tmp_span); - recover_b=1; + H5S_hyper_recover_span(&recover_b, &span_b, tmp_span); + recover_b = TRUE; } /* end if */ else { /* Advance both span 'a' & span 'b' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end else */ } /* end if */ /* Check if span 'a' overlaps only the upper bound */ @@ -5095,14 +5163,19 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s /* AAAAAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if((span_a->low>=span_b->low && span_a->low<=span_b->high) && span_a->high>span_b->high) { + else if((span_a->low >= span_b->low && span_a->low <= span_b->high) && span_a->high > span_b->high) { /* Check if there is actually a lower part of span 'b' to split off */ - if(span_a->low>span_b->low) { + if(span_a->low > span_b->low) { /* Split off lower part of span 'b' at lower span of span 'a' */ /* Merge/add lower part of span 'b' with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_b_not_a) { + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_b->low, span_a->low - 1, span_b->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the b_not_a bounds should be updated */ + update_b_not_a_bounds = TRUE; + } /* end if */ } /* end if */ else { /* Keep going, nothing to split off */ @@ -5114,26 +5187,29 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s HDassert((span_a->down != NULL && span_b->down != NULL) || (span_a->down == NULL && span_b->down == NULL)); /* If there are no down spans, just add the overlapping area to the a_and_b list */ - if(span_a->down==NULL) { + if(span_a->down == NULL) { /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_b->high,NULL,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_and_b) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_a->low, span_b->high, NULL, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") } /* end if */ /* If there are down spans, check for the overlap in them and add to each appropriate list */ else { /* NULL out the temporary pointers to clipped areas in down spans */ - down_a_not_b=NULL; - down_a_and_b=NULL; - down_b_not_a=NULL; + down_a_not_b = NULL; + down_a_and_b = NULL; + down_b_not_a = NULL; /* Check for overlaps in the 'down spans' of span 'a' & 'b' */ - if(H5S_hyper_clip_spans(span_a->down,span_b->down,&down_a_not_b,&down_a_and_b,&down_b_not_a)<0) + if(H5S_hyper_clip_spans(span_a->down, span_b->down, selector, cur_dim + 1, dim_size, span_a_b_bounds, all_clips_bounds, &down_a_not_b, &down_a_and_b, &down_b_not_a) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") /* Check for additions to the a_not_b list */ - if(down_a_not_b!=NULL) { + if(down_a_not_b) { + HDassert(need_a_not_b == TRUE); + /* Merge/add overlapped part with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_b->high,down_a_not_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_b->high, down_a_not_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -5141,9 +5217,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the a_and_b list */ - if(down_a_and_b!=NULL) { + if(down_a_and_b) { + HDassert(need_a_and_b == TRUE); + /* Merge/add overlapped part with/to a_and_b list */ - if(H5S_hyper_append_span(&last_a_and_b,a_and_b,span_a->low,span_b->high,down_a_and_b,NULL)==FAIL) + if(H5S_hyper_append_span(&last_a_and_b, a_and_b, span_a->low, span_b->high, down_a_and_b, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -5151,9 +5229,11 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s } /* end if */ /* Check for additions to the b_not_a list */ - if(down_b_not_a!=NULL) { + if(down_b_not_a) { + HDassert(need_b_not_a == TRUE); + /* Merge/add overlapped part with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_a->low,span_b->high,down_b_not_a,NULL)==FAIL) + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_a->low, span_b->high, down_b_not_a, NULL) < 0) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Release the down span tree generated */ @@ -5164,15 +5244,15 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s /* Split off upper part of span 'a' at upper span of span 'b' */ /* Allocate new span node for upper part of span 'a' */ - if((tmp_span = H5S_hyper_new_span(span_b->high+1,span_a->high,span_a->down,span_a->next))==NULL) + if(NULL == (tmp_span = H5S_hyper_new_span(span_b->high + 1, span_a->high, span_a->down, span_a->next))) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") /* Make upper part of span 'a' into new span 'a' */ - H5S_hyper_recover_span(&recover_a,&span_a,tmp_span); - recover_a=1; + H5S_hyper_recover_span(&recover_a, &span_a, tmp_span); + recover_a = TRUE; /* Advance span 'b' */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end if */ /* span 'a' must be entirely above span 'b' */ /* AAAAA */ @@ -5182,46 +5262,95 @@ H5S_hyper_clip_spans (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_s /* Copy span 'b' and add to b_not_a list */ /* Merge/add span 'b' with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_b->high,span_b->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_b_not_a) { + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_b->low, span_b->high, span_b->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the b_not_a bounds should be updated */ + update_b_not_a_bounds = TRUE; + } /* end if */ /* Advance span 'b', leave span 'a' */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end else */ } /* end while */ /* Clean up 'a' spans which haven't been covered yet */ - if(span_a!=NULL && span_b==NULL) { - while(span_a!=NULL) { + if(span_a != NULL && span_b == NULL) { + while(span_a != NULL) { /* Copy span 'a' and add to a_not_b list */ /* Merge/add span 'a' with/to a_not_b list */ - if(H5S_hyper_append_span(&last_a_not_b,a_not_b,span_a->low,span_a->high,span_a->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_a_not_b) { + if(H5S_hyper_append_span(&last_a_not_b, a_not_b, span_a->low, span_a->high, span_a->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the a_not_b bounds should be updated */ + update_a_not_b_bounds = TRUE; + } /* end if */ /* Advance to the next 'a' span */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); } /* end while */ } /* end if */ /* Clean up 'b' spans which haven't been covered yet */ - else if(span_a==NULL && span_b!=NULL) { - while(span_b!=NULL) { + else if(span_a == NULL && span_b != NULL) { + while(span_b != NULL) { /* Copy span 'b' and add to b_not_a list */ /* Merge/add span 'b' with/to b_not_a list */ - if(H5S_hyper_append_span(&last_b_not_a,b_not_a,span_b->low,span_b->high,span_b->down,NULL)==FAIL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(need_b_not_a) { + if(H5S_hyper_append_span(&last_b_not_a, b_not_a, span_b->low, span_b->high, span_b->down, NULL) < 0) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + + /* Indicate that the b_not_a bounds should be updated */ + update_b_not_a_bounds = TRUE; + } /* end if */ /* Advance to the next 'b' span */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end while */ } /* end if */ + + /* Check for needing to update each set of bounds */ + if(update_a_not_b_bounds) { + /* Update bounding box of a_not_b for remaining dimensions as a span was appended */ + for(u = cur_dim + 1; u < dim_size; u++) { + a_not_b_low_bounds[u] = MIN(a_not_b_low_bounds[u], span_a_low_bounds[u]); + a_not_b_high_bounds[u] = MAX(a_not_b_high_bounds[u], span_a_high_bounds[u]); + } /* end for */ + } /* end if */ + if(update_b_not_a_bounds) { + /* Update bounding box of b_not_a for remaining dimensions as a span was appended */ + for(u = cur_dim + 1; u < dim_size; u++) { + b_not_a_low_bounds[u] = MIN(b_not_a_low_bounds[u], span_b_low_bounds[u]); + b_not_a_high_bounds[u] = MAX(b_not_a_high_bounds[u], span_b_high_bounds[u]); + } /* end for */ + } /* end if */ + + /** + * Up to this point, the clip operation has been applied to one + * span list in one dimension. So it's time to update the bound + * box of the clipped span trees. + */ + if(need_a_not_b && *a_not_b != NULL) { + a_not_b_low_bounds[cur_dim] = MIN(a_not_b_low_bounds[cur_dim], (*a_not_b)->head->low); + a_not_b_high_bounds[cur_dim] = MAX(a_not_b_high_bounds[cur_dim], (*a_not_b)->tail->high); + } /* end if */ + if(need_a_and_b && *a_and_b != NULL) { + a_and_b_low_bounds[cur_dim] = MIN(a_and_b_low_bounds[cur_dim], (*a_and_b)->head->low); + a_and_b_high_bounds[cur_dim] = MAX(a_and_b_high_bounds[cur_dim], (*a_and_b)->tail->high); + } /* end if */ + if(need_b_not_a && *b_not_a != NULL) { + b_not_a_low_bounds[cur_dim] = MIN(b_not_a_low_bounds[cur_dim], (*b_not_a)->head->low); + b_not_a_high_bounds[cur_dim] = MAX(b_not_a_high_bounds[cur_dim], (*b_not_a)->tail->high); + } /* end if */ } /* end else */ } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_clip_spans() */ +} /* end H5S_hyper_clip_spans() */ /*-------------------------------------------------------------------------- @@ -5246,16 +5375,10 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static H5S_hyper_span_info_t * -H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans) +H5S_hyper_merge_spans_helper(H5S_hyper_span_info_t *a_spans, H5S_hyper_span_info_t *b_spans) { - H5S_hyper_span_info_t *merged_spans=NULL; /* Pointer to the merged span tree */ - H5S_hyper_span_info_t *tmp_spans; /* Pointer to temporary new span tree */ - H5S_hyper_span_t *tmp_span; /* Pointer to temporary new span */ - H5S_hyper_span_t *span_a; /* Pointer to current span 'a' working on */ - H5S_hyper_span_t *span_b; /* Pointer to current span 'b' working on */ - H5S_hyper_span_t *prev_span_merge; /* Pointer to previous merged span */ - unsigned recover_a, recover_b; /* Flags to indicate when to recover temporary spans */ - H5S_hyper_span_info_t *ret_value; + H5S_hyper_span_info_t *merged_spans = NULL; /* Pointer to the merged span tree */ + H5S_hyper_span_info_t *ret_value; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -5263,46 +5386,54 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HDassert((a_spans != NULL && b_spans != NULL) || (a_spans == NULL && b_spans == NULL)); /* Check if the span trees for the 'a' span and the 'b' span are the same */ - if(H5S_hyper_cmp_spans(a_spans,b_spans)==TRUE) { - if(a_spans==NULL) - merged_spans=NULL; + if(H5S_hyper_cmp_spans(a_spans, b_spans) == TRUE) { + if(a_spans == NULL) + merged_spans = NULL; else { /* Copy one of the span trees to return */ - if((merged_spans=H5S_hyper_copy_span(a_spans))==NULL) + if(NULL == (merged_spans = H5S_hyper_copy_span(a_spans))) HGOTO_ERROR(H5E_INTERNAL, H5E_CANTCOPY, NULL, "can't copy hyperslab span tree") } /* end else */ } /* end if */ else { + H5S_hyper_span_t *span_a; /* Pointer to current span 'a' working on */ + H5S_hyper_span_t *span_b; /* Pointer to current span 'b' working on */ + H5S_hyper_span_t *prev_span_merge; /* Pointer to previous merged span */ + hbool_t recover_a, recover_b; /* Flags to indicate when to recover temporary spans */ + /* Get the pointers to the 'a' and 'b' span lists */ - span_a=a_spans->head; - span_b=b_spans->head; + span_a = a_spans->head; + span_b = b_spans->head; /* Set the pointer to the previous spans */ - prev_span_merge=NULL; + prev_span_merge = NULL; /* No spans to recover yet */ - recover_a=recover_b=0; + recover_a = recover_b = FALSE; /* Work through the list of spans in the new list */ while(span_a!=NULL && span_b!=NULL) { + H5S_hyper_span_info_t *tmp_spans; /* Pointer to temporary new span tree */ + H5S_hyper_span_t *tmp_span; /* Pointer to temporary new span */ + /* Check if the 'a' span is completely before 'b' span */ /* AAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - if(span_a->high<span_b->low) { + if(span_a->high < span_b->low) { /* Merge/add span 'a' with/to the merged spans */ if(H5S_hyper_append_span(&prev_span_merge,&merged_spans,span_a->low,span_a->high,span_a->down,NULL)==FAIL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Advance span 'a' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); } /* end if */ /* Check if span 'a' overlaps only the lower bound */ /* of span 'b', up to the upper bound of span 'b' */ /* AAAAAAAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if(span_a->low<span_b->low && (span_a->high>=span_b->low && span_a->high<=span_b->high)) { + else if(span_a->low < span_b->low && (span_a->high >= span_b->low && span_a->high <= span_b->high)) { /* Check if span 'a' and span 'b' down spans are equal */ if(H5S_hyper_cmp_spans(span_a->down,span_b->down)==TRUE) { /* Merge/add copy of span 'a' with/to merged spans */ @@ -5326,7 +5457,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf } /* end else */ /* Check if there is an upper part of span 'b' */ - if(span_a->high<span_b->high) { + if(span_a->high < span_b->high) { /* Copy upper part of span 'b' as new span 'b' */ /* Allocate new span node to append to list */ @@ -5334,16 +5465,16 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Advance span 'a' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); /* Set new span 'b' to tmp_span */ - H5S_hyper_recover_span(&recover_b,&span_b,tmp_span); - recover_b=1; + H5S_hyper_recover_span(&recover_b, &span_b, tmp_span); + recover_b = TRUE; } /* end if */ else { /* Advance both span 'a' & 'b' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end else */ } /* end if */ /* Check if span 'a' overlaps the lower & upper bound */ @@ -5351,7 +5482,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf /* AAAAAAAAAAAAAAAAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if(span_a->low<span_b->low && span_a->high>span_b->high) { + else if(span_a->low < span_b->low && span_a->high > span_b->high) { /* Check if span 'a' and span 'b' down spans are equal */ if(H5S_hyper_cmp_spans(span_a->down,span_b->down)==TRUE) { /* Merge/add copy of lower & middle parts of span 'a' to merged spans */ @@ -5381,17 +5512,17 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Set new span 'a' to tmp_span */ - H5S_hyper_recover_span(&recover_a,&span_a,tmp_span); - recover_a=1; + H5S_hyper_recover_span(&recover_a, &span_a, tmp_span); + recover_a = TRUE; /* Advance span 'b' */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end if */ /* Check if span 'a' is entirely within span 'b' */ /* AAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if(span_a->low>=span_b->low && span_a->high<=span_b->high) { + else if(span_a->low >= span_b->low && span_a->high <= span_b->high) { /* Check if span 'a' and span 'b' down spans are equal */ if(H5S_hyper_cmp_spans(span_a->down,span_b->down)==TRUE) { /* Merge/add copy of lower & middle parts of span 'b' to merged spans */ @@ -5400,7 +5531,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf } /* end if */ else { /* Check if there is a lower part of span 'b' */ - if(span_a->low>span_b->low) { + if(span_a->low > span_b->low) { /* Merge/add lower part of span 'b' to merged spans */ if(H5S_hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") @@ -5421,7 +5552,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf } /* end else */ /* Check if there is an upper part of span 'b' */ - if(span_a->high<span_b->high) { + if(span_a->high < span_b->high) { /* Copy upper part of span 'b' as new span 'b' (remember to free) */ /* Allocate new span node to append to list */ @@ -5429,16 +5560,16 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Advance span 'a' */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); /* Set new span 'b' to tmp_span */ - H5S_hyper_recover_span(&recover_b,&span_b,tmp_span); - recover_b=1; + H5S_hyper_recover_span(&recover_b, &span_b, tmp_span); + recover_b = TRUE; } /* end if */ else { /* Advance both spans */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end else */ } /* end if */ /* Check if span 'a' overlaps only the upper bound */ @@ -5446,7 +5577,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf /* AAAAAAAAAA */ /* <-----------------------------------> */ /* BBBBBBBBBB */ - else if((span_a->low>=span_b->low && span_a->low<=span_b->high) && span_a->high>span_b->high) { + else if((span_a->low >= span_b->low && span_a->low <= span_b->high) && span_a->high > span_b->high) { /* Check if span 'a' and span 'b' down spans are equal */ if(H5S_hyper_cmp_spans(span_a->down,span_b->down)==TRUE) { /* Merge/add copy of span 'b' to merged spans if so */ @@ -5455,7 +5586,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf } /* end if */ else { /* Check if there is a lower part of span 'b' */ - if(span_a->low>span_b->low) { + if(span_a->low > span_b->low) { /* Merge/add lower part of span 'b' to merged spans */ if(H5S_hyper_append_span(&prev_span_merge,&merged_spans,span_b->low,span_a->low-1,span_b->down,NULL)==FAIL) HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") @@ -5482,11 +5613,11 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Set new span 'a' to tmp_span */ - H5S_hyper_recover_span(&recover_a,&span_a,tmp_span); - recover_a=1; + H5S_hyper_recover_span(&recover_a, &span_a, tmp_span); + recover_a = TRUE; /* Advance span 'b' */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end if */ /* Span 'a' must be entirely above span 'b' */ /* AAAAA */ @@ -5498,7 +5629,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Advance span 'b' */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end else */ } /* end while */ @@ -5510,7 +5641,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Advance to next 'a' span, until all processed */ - H5S_hyper_recover_span(&recover_a,&span_a,span_a->next); + H5S_hyper_recover_span(&recover_a, &span_a, span_a->next); } /* end while */ } /* end if */ @@ -5522,7 +5653,7 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab span") /* Advance to next 'b' span, until all processed */ - H5S_hyper_recover_span(&recover_b,&span_b,span_b->next); + H5S_hyper_recover_span(&recover_b, &span_b, span_b->next); } /* end while */ } /* end if */ } /* end else */ @@ -5531,14 +5662,12 @@ H5S_hyper_merge_spans_helper (H5S_hyper_span_info_t *a_spans, H5S_hyper_span_inf ret_value = merged_spans; done: - if(ret_value == NULL) { - if(merged_spans) - if(H5S_hyper_free_span_info(merged_spans) < 0) - HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, NULL, "failed to release merged hyperslab spans") - } /* end if */ + if(ret_value == NULL) + if(merged_spans && H5S_hyper_free_span_info(merged_spans) < 0) + HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, NULL, "failed to release merged hyperslab spans") FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_merge_spans_helper() */ +} /* end H5S_hyper_merge_spans_helper() */ /*-------------------------------------------------------------------------- @@ -5552,9 +5681,6 @@ done: selection. H5S_hyper_span_t *new_spans; IN: Span tree of new spans to add to hyperslab selection - hbool_t can_own; IN: Flag to indicate that it is OK to point - directly to the new spans, instead of - copying them. RETURNS non-negative on success, negative on failure DESCRIPTION @@ -5567,41 +5693,38 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_merge_spans (H5S_t *space, H5S_hyper_span_info_t *new_spans, hbool_t can_own) +H5S_hyper_merge_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans) { - FUNC_ENTER_NOAPI_NOINIT_NOERR + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT /* Check args */ HDassert(space); HDassert(new_spans); /* If this is the first span tree in the hyperslab selection, just use it */ - if(space->select.sel_info.hslab->span_lst==NULL) { - if(can_own) - space->select.sel_info.hslab->span_lst=new_spans; - else - space->select.sel_info.hslab->span_lst=H5S_hyper_copy_span(new_spans); - } /* end if */ + if(space->select.sel_info.hslab->span_lst == NULL) + space->select.sel_info.hslab->span_lst = new_spans; else { H5S_hyper_span_info_t *merged_spans; /* Get the merged spans */ - merged_spans=H5S_hyper_merge_spans_helper(space->select.sel_info.hslab->span_lst, new_spans); - - /* Sanity checking since we started with some spans, we should still have some after the merge */ - HDassert(merged_spans); + if(NULL == (merged_spans = H5S_hyper_merge_spans_helper(space->select.sel_info.hslab->span_lst, new_spans))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTMERGE, FAIL, "can't merge hyperslab spans") /* Free the previous spans */ - H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst); + if(H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTFREE, FAIL, "failed to release hyperslab spans") /* Point to the new merged spans */ - space->select.sel_info.hslab->span_lst=merged_spans; + space->select.sel_info.hslab->span_lst = merged_spans; } /* end else */ - FUNC_LEAVE_NOAPI(SUCCEED) -} /* H5S_hyper_merge_spans() */ +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_hyper_merge_spans() */ - /*-------------------------------------------------------------------------- NAME H5S_hyper_spans_nelem @@ -5620,34 +5743,150 @@ H5S_hyper_merge_spans (H5S_t *space, H5S_hyper_span_info_t *new_spans, hbool_t c REVISION LOG --------------------------------------------------------------------------*/ static hsize_t -H5S_hyper_spans_nelem (H5S_hyper_span_info_t *spans) +H5S_hyper_spans_nelem(const H5S_hyper_span_info_t *spans) { - H5S_hyper_span_t *span; /* Hyperslab span */ - hsize_t ret_value; + hsize_t ret_value = 0; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR /* Count the number of elements in the span tree */ - if(spans==NULL) - ret_value=0; - else { - span=spans->head; - ret_value=0; - while(span!=NULL) { + if(spans != NULL) { + const H5S_hyper_span_t *span; /* Hyperslab span */ + + span = spans->head; + while(span != NULL) { /* If there are down spans, multiply the size of this span by the total down span elements */ - if(span->down!=NULL) - ret_value+=span->nelem*H5S_hyper_spans_nelem(span->down); + if(span->down != NULL) + ret_value += span->nelem * H5S_hyper_spans_nelem(span->down); /* If there are no down spans, just count the elements in this span */ else - ret_value+=span->nelem; + ret_value += span->nelem; /* Advance to next span */ - span=span->next; + span = span->next; } /* end while */ } /* end else */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_spans_nelem() */ +} /* end H5S_hyper_spans_nelem() */ + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_add_disjoint_spans + PURPOSE + Add new hyperslab spans to existing hyperslab selection in the case the + new hyperslab spans don't overlap or border with the existing hyperslab + selection + USAGE + herr_t H5S_hyper_add_disjoint_spans(space, new_spans) + H5S_t *space; IN: Dataspace to add new spans to hyperslab + selection. + H5S_hyper_span_t *new_spans; IN: Span tree of new spans to add to + hyperslab selection + RETURNS + non-negative on success, negative on failure + DESCRIPTION + Add a set of hyperslab spans to an existing hyperslab selection. The + new spans are required not to overlap or borderwith the existing spans + in the dataspace's current hyperslab selection in terms of bound box. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_add_disjoint_spans(H5S_t *space, H5S_hyper_span_info_t *new_spans) +{ + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check args */ + HDassert(space); + HDassert(new_spans); + + /* update the number of elements in the selection */ + space->select.num_elem += H5S_hyper_spans_nelem(new_spans); + + /* If this is the first span tree in the hyperslab selection, just use it */ + if(space->select.sel_info.hslab->span_lst == NULL) + space->select.sel_info.hslab->span_lst = new_spans; + else { + H5S_hyper_span_info_t *old_spans = space->select.sel_info.hslab->span_lst; + H5S_hyper_span_info_t *high_order_spans = NULL; + H5S_hyper_span_info_t *low_order_spans = NULL; + + /* Combine the new_spans with the old_spans only in the highest-order of dimension */ + /* Example: + * old_spans: ------------------> X + * | (1,2)--->(1,3)--->(6,4)--->|| + * | | ^ + * | | | + * Y | V | + * | (5,2)------. + * | | + * | | + * | V + * | = + * V + * new_spans: --------------------> X + * | (8,2)--->(12,3)--->(17,4)--->|| + * | | + * Y | | + * | V + * | = + * V + * + * After merging, the old_spans becomes + * + * old_spans: ------------------> X + * | (1,2)--->(1,3)--->(6,4)--->|| + * | | ^ + * | | | + * | V | + * | (5,2)------. + * | | + * Y | | + * | (8,2)--->(12,3)--->(17,4)--->|| + * | | + * | | + * | V + * | = + * V + */ + + /* Make sure the tail pointers are updated correctly */ + HDassert(old_spans->tail); + HDassert(NULL == old_spans->tail->next); + HDassert(new_spans->tail); + HDassert(NULL == new_spans->tail->next); + + /* Check old_spans and new_spans to see which one is of higher order, + * and append the higher order spans to the lower order ones. + */ + if(new_spans->head->low > old_spans->tail->high) { + high_order_spans = new_spans; + low_order_spans = old_spans; + } /* end if */ + else{ + high_order_spans = old_spans; + low_order_spans = new_spans; + } /* end else */ + + /* The high_order_spans should be appended to low_order_spans */ + low_order_spans->tail->next = high_order_spans->head; + + /* "pstride" is only updated in IO operations, so it needs no update here */ + /*high_order_spans->head->pstride = high_order_spans->head->low - low_order_spans->tail->low;*/ + low_order_spans->tail = high_order_spans->tail; + + /* Fix the selection's 1st span info node */ + space->select.sel_info.hslab->span_lst = low_order_spans; + + /* free the memory space for "new_spans" node */ + high_order_spans = H5FL_FREE(H5S_hyper_span_info_t, high_order_spans); + } /* end else */ + + FUNC_LEAVE_NOAPI(SUCCEED) +} /* end H5S_hyper_add_disjoint_spans */ /*-------------------------------------------------------------------------- @@ -5736,23 +5975,19 @@ H5S_hyper_make_spans(unsigned rank, const hsize_t *start, const hsize_t *stride, span->down = down; down->count++; /* Increment reference count for shared span */ } /* end if */ - else { + else span->down = NULL; - } /* end else */ } /* end for */ /* Allocate a span info node */ - if(NULL == (down = H5FL_MALLOC(H5S_hyper_span_info_t))) + if(NULL == (down = H5FL_CALLOC(H5S_hyper_span_info_t))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate hyperslab span") - /* Set the reference count */ - down->count = 0; - - /* Reset the scratch pad space */ - down->scratch = 0; - /* Keep the pointer to the next dimension down's completed list */ down->head = head; + + /* Keep the tail pointer to the next dimension down's completed list */ + down->tail = last_span; } /* end for */ /* Indicate that there is a pointer to this tree */ @@ -5786,7 +6021,217 @@ done: } /* end if */ FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_make_spans() */ +} /* end H5S_hyper_make_spans() */ + + +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_update_diminfo + PURPOSE + Attempt to update optimized hyperslab information quickly. (It can be + recovered with regular selection). If this algorithm cannot determine + the optimized dimension info quickly, this function will simply mark it + as invalid and unknown if it can be built (H5S_DIMINFO_VALID_NO), so + H5S_hyper_rebuild can be run later to determine for sure. + USAGE + herr_t H5S_hyper_update_diminfo(space, op, new_hyper_diminfo) + H5S_t *space; IN: Dataspace to check + H5S_seloper_t op; IN: The operation being performed on the + selection + const H5S_hyper_dim_t new_hyper_diminfo; IN: The new selection that + is being combined with + the current + 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 + EXAMPLES + REVISION LOG + NF, 2014/6/6 +--------------------------------------------------------------------------*/ +static herr_t +H5S_hyper_update_diminfo(H5S_t *space, H5S_seloper_t op, + const H5S_hyper_dim_t *new_hyper_diminfo) +{ + H5S_hyper_dim_t tmp_diminfo[H5S_MAX_RANK]; /* Temporary dimension info */ + hbool_t found_nonidentical_dim = FALSE; + unsigned curr_dim; + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT_NOERR + + /* Check args */ + HDassert(space); + HDassert(new_hyper_diminfo); + + /* Check for conditions that prevent us from using the fast algorithm here + * (and instead require H5S_hyper_rebuild) */ + if(!((op == H5S_SELECT_OR) || (op == H5S_SELECT_XOR)) + || space->select.sel_info.hslab->diminfo_valid != H5S_DIMINFO_VALID_YES + || !space->select.sel_info.hslab->span_lst->head) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + HGOTO_DONE(SUCCEED) + } /* end if */ + + /* Copy current opt_diminfo values */ + for(curr_dim = 0; curr_dim < space->extent.rank; curr_dim++) { + tmp_diminfo[curr_dim].start = space->select.sel_info.hslab->opt_diminfo[curr_dim].start; + tmp_diminfo[curr_dim].stride = space->select.sel_info.hslab->opt_diminfo[curr_dim].stride; + tmp_diminfo[curr_dim].count = space->select.sel_info.hslab->opt_diminfo[curr_dim].count; + tmp_diminfo[curr_dim].block = space->select.sel_info.hslab->opt_diminfo[curr_dim].block; + } /* end for */ + + /* Loop over dimensions */ + for(curr_dim = 0; curr_dim < space->extent.rank; curr_dim++) { + /* Check for this being identical */ + if((tmp_diminfo[curr_dim].start != new_hyper_diminfo[curr_dim].start) + || (tmp_diminfo[curr_dim].stride != new_hyper_diminfo[curr_dim].stride) + || (tmp_diminfo[curr_dim].count != new_hyper_diminfo[curr_dim].count) + || (tmp_diminfo[curr_dim].block != new_hyper_diminfo[curr_dim].block)) { + hsize_t high_start, high_count, high_block; /* The start, count & block values for the higher block */ + + /* Dimension is not identical */ + /* Check if we already found a nonidentical dim - only one is + * allowed */ + if(found_nonidentical_dim) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + + /* Check that strides are the same, or count is 1 for one of the + * slabs */ + if((tmp_diminfo[curr_dim].stride != new_hyper_diminfo[curr_dim].stride) + && (tmp_diminfo[curr_dim].count > 1) + && (new_hyper_diminfo[curr_dim].count > 1)) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + + /* Patch tmp_diminfo.stride if its count is 1 */ + if((tmp_diminfo[curr_dim].count == 1) + && (new_hyper_diminfo[curr_dim].count > 1)) + tmp_diminfo[curr_dim].stride = new_hyper_diminfo[curr_dim].stride; + + /* Determine lowest start, and set tmp_diminfo.start, count and + * block to use the lowest, and high_start, high_count and + * high_block to use the highest + */ + if(tmp_diminfo[curr_dim].start < new_hyper_diminfo[curr_dim].start) { + high_start = new_hyper_diminfo[curr_dim].start; + high_count = new_hyper_diminfo[curr_dim].count; + high_block = new_hyper_diminfo[curr_dim].block; + } /* end if */ + else { + high_start = tmp_diminfo[curr_dim].start; + tmp_diminfo[curr_dim].start = new_hyper_diminfo[curr_dim].start; + high_count = tmp_diminfo[curr_dim].count; + tmp_diminfo[curr_dim].count = new_hyper_diminfo[curr_dim].count; + high_block = tmp_diminfo[curr_dim].block; + tmp_diminfo[curr_dim].block = new_hyper_diminfo[curr_dim].block; + } /* end else */ + + /* If count is 1 for both slabs, take different actions */ + if((tmp_diminfo[curr_dim].count == 1) && (high_count == 1)) { + /* Check for overlap */ + if((tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block) + > high_start) { + /* Check operation type */ + if(op == H5S_SELECT_OR) + /* Merge blocks */ + tmp_diminfo[curr_dim].block = ((high_start + high_block) + >= (tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block)) + ? (high_start + high_block - tmp_diminfo[curr_dim].start) + : tmp_diminfo[curr_dim].block; + else { + /* Block values must be the same */ + if(tmp_diminfo[curr_dim].block != high_block) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + + /* XOR - overlap creates 2 blocks */ + tmp_diminfo[curr_dim].stride = high_block; + tmp_diminfo[curr_dim].count = 2; + tmp_diminfo[curr_dim].block = high_start - tmp_diminfo[curr_dim].start; + } /* end else */ + } /* end if */ + else if((tmp_diminfo[curr_dim].start + tmp_diminfo[curr_dim].block) + == high_start) + /* Blocks border, merge them */ + tmp_diminfo[curr_dim].block += high_block; + else { + /* Distinct blocks */ + /* Block values must be the same */ + if(tmp_diminfo[curr_dim].block != high_block) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + + /* Create strided selection */ + tmp_diminfo[curr_dim].stride = high_start - tmp_diminfo[curr_dim].start; + tmp_diminfo[curr_dim].count = 2; + } /* end else */ + } /* end if */ + else { + /* Check if block values are the same */ + if(tmp_diminfo[curr_dim].block != new_hyper_diminfo[curr_dim].block) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + + /* Check phase of strides */ + if((tmp_diminfo[curr_dim].start % tmp_diminfo[curr_dim].stride) + != (new_hyper_diminfo[curr_dim].start % tmp_diminfo[curr_dim].stride)) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + + /* Check operation type */ + if(op == H5S_SELECT_OR) { + /* Make sure the slabs border or overlap */ + if(high_start > (tmp_diminfo[curr_dim].start + + (tmp_diminfo[curr_dim].count + * tmp_diminfo[curr_dim].stride))) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + } /* end if */ + else + /* XOR: Make sure the slabs border */ + if(high_start != (tmp_diminfo[curr_dim].start + + (tmp_diminfo[curr_dim].count + * tmp_diminfo[curr_dim].stride))) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; + break; + } /* end if */ + + /* Set count for combined selection */ + tmp_diminfo[curr_dim].count = ((high_start + - tmp_diminfo[curr_dim].start) + / tmp_diminfo[curr_dim].stride) + high_count; + } /* end else */ + + /* Indicate that we found a nonidentical dim */ + found_nonidentical_dim = TRUE; + } /* end if */ + } /* end for */ + + /* Check if we succeeded, if so, set the new diminfo values */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) + for(curr_dim = 0; curr_dim < space->extent.rank; curr_dim++) { + space->select.sel_info.hslab->app_diminfo[curr_dim].start = space->select.sel_info.hslab->opt_diminfo[curr_dim].start = tmp_diminfo[curr_dim].start; + space->select.sel_info.hslab->app_diminfo[curr_dim].stride = space->select.sel_info.hslab->opt_diminfo[curr_dim].stride = tmp_diminfo[curr_dim].stride; + space->select.sel_info.hslab->app_diminfo[curr_dim].count = space->select.sel_info.hslab->opt_diminfo[curr_dim].count = tmp_diminfo[curr_dim].count; + space->select.sel_info.hslab->app_diminfo[curr_dim].block = space->select.sel_info.hslab->opt_diminfo[curr_dim].block = tmp_diminfo[curr_dim].block; + } /* end for */ + +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_hyper_update_diminfo() */ /*-------------------------------------------------------------------------- @@ -5819,23 +6264,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; - size_t outcount; - unsigned u; - H5S_hyper_dim_t canon_down_span_slab_info[H5S_MAX_RANK]; - hbool_t ret_value = TRUE; + hbool_t ret_value = TRUE; /* Return value */ FUNC_ENTER_NOAPI_NOINIT_NOERR if(span) { + H5S_hyper_dim_t canon_down_span_slab_info[H5S_MAX_RANK]; + hsize_t curr_stride; + hsize_t curr_block; + hsize_t curr_start; + hsize_t curr_low; + size_t outcount; /* Number of spans encountered in this dimension */ + /* Initialization */ curr_stride = 1; - curr_block = 0; - outcount = 0; curr_low = 0; + outcount = 0; /* Get "canonical" down span information */ if(span->down) { @@ -5854,9 +6298,13 @@ H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab /* Loop the span */ while(span) { + hsize_t next_stride; + hsize_t next_block; + if(outcount > 0) { if(span->down) { - H5S_hyper_dim_t *curr_down_span_slab_info; + H5S_hyper_dim_t *curr_down_span_slab_info; + unsigned u; /* Local index variable */ HDassert(span->down->head); @@ -5867,7 +6315,7 @@ H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab /* Compare the slab information of the adjacent spans in the down span tree. We have to compare all the sub-tree slab information with the canon_down_span_slab_info.*/ - for( u = 0; u < rank - 1; u++) { + for(u = 0; u < rank - 1; u++) { curr_down_span_slab_info = &span_slab_info[u]; if(curr_down_span_slab_info->count > 0 && canon_down_span_slab_info[u].count > 0) { @@ -5877,9 +6325,9 @@ H5S_hyper_rebuild_helper(const H5S_hyper_span_t *span, H5S_hyper_dim_t span_slab || curr_down_span_slab_info->count != canon_down_span_slab_info[u].count) HGOTO_DONE(FALSE) } /* end if */ - else if (!((curr_down_span_slab_info->count == 0) && (canon_down_span_slab_info[u].count == 0))) + else if(!((curr_down_span_slab_info->count == 0) && (canon_down_span_slab_info[u].count == 0))) HGOTO_DONE(FALSE) - } + } /* end for */ } /* end if */ } /* end if */ @@ -5941,22 +6389,19 @@ done: 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 --------------------------------------------------------------------------*/ -static htri_t +htri_t H5S_hyper_rebuild(H5S_t *space) { H5S_hyper_dim_t top_span_slab_info[H5O_LAYOUT_NDIMS]; - H5S_hyper_dim_t *diminfo; - H5S_hyper_dim_t *app_diminfo; - unsigned rank, curr_dim; - htri_t ret_value = TRUE; /* Return value */ + unsigned rank; /* Dataspace rank */ + htri_t ret_value = TRUE; /* Return value */ - FUNC_ENTER_NOAPI_NOINIT_NOERR + FUNC_ENTER_NOAPI_NOERR /* Check args */ HDassert(space); @@ -5967,27 +6412,32 @@ H5S_hyper_rebuild(H5S_t *space) /* Check whether the slab can be rebuilt. Only regular selection can be rebuilt. If yes, fill in correct values.*/ if(!H5S_hyper_rebuild_helper(space->select.sel_info.hslab->span_lst->head, top_span_slab_info, rank)) { + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_IMPOSSIBLE; 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++) { + H5S_hyper_dim_t *opt_diminfo; /* Convenience pointer to optimized dimension info */ + H5S_hyper_dim_t *app_diminfo; /* Convenience pointer to application dimension info */ + unsigned u; /* Local index variable */ - 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; + /* Set the convenience pointers */ + opt_diminfo = space->select.sel_info.hslab->opt_diminfo; + app_diminfo = space->select.sel_info.hslab->app_diminfo; + /* Set the dimension info for the dataspace, from the rebuilt info */ + for(u = 0; u < rank; u++) { + app_diminfo[(rank - u) - 1].start = opt_diminfo[(rank - u) - 1].start = top_span_slab_info[u].start; + app_diminfo[(rank - u) - 1].stride = opt_diminfo[(rank - u) - 1].stride = top_span_slab_info[u].stride; + app_diminfo[(rank - u) - 1].count = opt_diminfo[(rank - u) - 1].count = top_span_slab_info[u].count; + app_diminfo[(rank - u) - 1].block = opt_diminfo[(rank - u) - 1].block = top_span_slab_info[u].block; } /* end for */ - space->select.sel_info.hslab->diminfo_valid = TRUE; + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES; } /* end else */ done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_rebuild() */ +} /* end H5S_hyper_rebuild() */ /*-------------------------------------------------------------------------- @@ -6011,12 +6461,12 @@ done: static herr_t H5S_hyper_generate_spans(H5S_t *space) { - hsize_t tmp_start[H5O_LAYOUT_NDIMS]; /* Temporary start information */ + hsize_t tmp_start[H5O_LAYOUT_NDIMS]; /* Temporary start information */ hsize_t tmp_stride[H5O_LAYOUT_NDIMS]; /* Temporary stride information */ hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary count information */ hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block information */ - unsigned u; /* Counter */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT @@ -6024,203 +6474,367 @@ H5S_hyper_generate_spans(H5S_t *space) HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS); /* Get the diminfo */ - for(u=0; u<space->extent.rank; u++) { - tmp_start[u]=space->select.sel_info.hslab->opt_diminfo[u].start; - tmp_stride[u]=space->select.sel_info.hslab->opt_diminfo[u].stride; - tmp_count[u]=space->select.sel_info.hslab->opt_diminfo[u].count; - tmp_block[u]=space->select.sel_info.hslab->opt_diminfo[u].block; + for(u = 0; u < space->extent.rank; u++) { + tmp_start[u] = space->select.sel_info.hslab->opt_diminfo[u].start; + tmp_stride[u] = space->select.sel_info.hslab->opt_diminfo[u].stride; + tmp_count[u] = space->select.sel_info.hslab->opt_diminfo[u].count; + tmp_block[u] = space->select.sel_info.hslab->opt_diminfo[u].block; } /* end for */ /* Build the hyperslab information also */ - if(H5S_generate_hyperslab (space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block)<0) + if(H5S_generate_hyperslab(space, H5S_SELECT_SET, tmp_start, tmp_stride, tmp_count, tmp_block) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs") done: FUNC_LEAVE_NOAPI(ret_value) -} /* H5S_hyper_generate_spans() */ +} /* end H5S_hyper_generate_spans() */ -#ifndef NEW_HYPERSLAB_API - -/*------------------------------------------------------------------------- - * Function: H5S_generate_hyperlab - * - * Purpose: Generate hyperslab information from H5S_select_hyperslab() - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol (split from HS_select_hyperslab()). - * Tuesday, September 12, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ +/*-------------------------------------------------------------------------- + NAME + H5S_hyper_update_bound_box + PURPOSE + Update the bounding box of the hyperslab depending on the selection operator + USAGE + herr_t H5S_hyper_update_bound_box(space, op, low_bounds, high_bounds, overlapped) + H5S_t *space; IN/OUT: Dataspace containing the 1st space + H5S_seloper_t op; IN: Selection operator + const hszie_t low_bounds; IN: The lower bounds of the 2nd space + const hsize_t high_bounds; IN: The higher bounds of the 2nd space + RETURNS + Non-negative on success, negative on failure + DESCRIPTION + GLOBAL VARIABLES + COMMENTS, BUGS + ASSUMPTIONS + This function assumes that the two bound boxes are not overlapped. If two bound + boxes are overlapped, the "space"'s bound box should be calculated recursively, + which has been done in H5S_fill_in_new_space function. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ static herr_t -H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op, - const hsize_t start[], - const hsize_t stride[], - const hsize_t count[], - const hsize_t block[]) +H5S_hyper_update_bound_box(H5S_t *space, H5S_seloper_t op, + const hsize_t low_bounds[], const hsize_t high_bounds[]) { - 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 */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT - /* Check args */ HDassert(space); - HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID); - HDassert(start); - HDassert(stride); - HDassert(count); - HDassert(block); + HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS); - /* Generate span tree for new hyperslab information */ - if((new_spans=H5S_hyper_make_spans(space->extent.rank,start,stride,count,block))==NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information") + /* The offset of the dataspace is ignored here */ + switch(op) { + case H5S_SELECT_OR: + case H5S_SELECT_XOR: + { + unsigned u; /* Local index variable */ - /* Generate list of blocks to add/remove based on selection operation */ - if(op==H5S_SELECT_SET) { - /* Add new spans to current selection */ - if(H5S_hyper_merge_spans(space,new_spans,TRUE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + for(u = 0; u < space->extent.rank; u++) { + /* choose the smaller value for the low bound as the op is (X)OR */ + space->select.low_bounds[u] = MIN(low_bounds[u], space->select.low_bounds[u]); - /* Set the number of elements in current selection */ - space->select.num_elem=H5S_hyper_spans_nelem(new_spans); + /* choose the larger value for the high bound as the op is (X)OR */ + space->select.high_bounds[u] = MAX(high_bounds[u], space->select.high_bounds[u]); + } /* end for */ + } + break; - /* Indicate that the new_spans are owned */ - new_spans=NULL; - } /* end if */ - else { - hbool_t updated_spans = FALSE; /* Whether the spans in the selection were modified */ + case H5S_SELECT_AND: + { + hsize_t tmp = HSIZET_MAX; - /* Generate lists of spans which overlap and don't overlap */ - if(H5S_hyper_clip_spans(space->select.sel_info.hslab->span_lst,new_spans,&a_not_b,&a_and_b,&b_not_a)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") + H5VM_array_fill(space->select.low_bounds, &tmp, sizeof(hsize_t), space->extent.rank); + HDmemset(space->select.high_bounds, 0, sizeof(hsize_t) * space->extent.rank); + } + break; - switch(op) { - case H5S_SELECT_OR: - /* Add any new spans from b_not_a to current selection */ - if(b_not_a!=NULL) { - if(H5S_hyper_merge_spans(space,b_not_a,FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + case H5S_SELECT_NOTB: + /* Since the two spaces don't overlap, the bound box needs no update */ + break; - /* Update the number of elements in current selection */ - space->select.num_elem+=H5S_hyper_spans_nelem(b_not_a); + case H5S_SELECT_NOTA: + /* Since the two spaces don't overlap, the bound box is same with 2nd space */ + HDmemcpy(space->select.low_bounds, low_bounds, sizeof(hsize_t) * space->extent.rank); + HDmemcpy(space->select.high_bounds, high_bounds, sizeof(hsize_t) * space->extent.rank); + break; - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ - break; + case H5S_SELECT_NOOP: + case H5S_SELECT_SET: + case H5S_SELECT_APPEND: + case H5S_SELECT_PREPEND: + case H5S_SELECT_INVALID: + default: + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") + } /* end switch(op) */ - case H5S_SELECT_AND: - /* Free the current selection */ - if(H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans") - space->select.sel_info.hslab->span_lst=NULL; +done: + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_hyper_update_bound_box() */ - /* Reset the number of items in selection */ - space->select.num_elem=0; + +/*-------------------------------------------------------------------------- + NAME + H5S_fill_in_new_space + PURPOSE + Combine two span lists, one from an existing dataspace and the + other from input arguments, into a new selection depending on the + selection operator. The new selection is put into a resulting dataspace + which could be allocated inside the function. + USAGE + herr_t H5S_fill_in_new_space(space1, op, space2_span_lst, space2_low_bound, + space2_high_bound, can_own_span2, + span2_owned, result) + H5S_t *space1; IN: Dataspace containing the first span list + H5S_seloper_t op; IN: Selection operation + H5S_hyper_span_info_t *space2_span_lst; IN: Second span list + const hsize_t *span2_low_bound; IN: The lower bound box for 2nd span list + const hsize_t *span2_high_bound; IN: The higher bound box for 2nd span list + hbool_t can_own_span2; IN: Indicates whether the 2nd span list could be + owned by the result. If not, the 2nd span list + has to be copied. + hbool_t *span2_owned; OUT: Indicates if the 2nd span list is actually owned + H5S_t **result; OUT: The dataspace containing the the new selection. It + could be same with the 1st dataspace. + RETURNS + Non-negative on success, negative on failure + PROGRAMMER + Chao Mei July 8, 2011 + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + The function is extracted from H5S_generate_hyperslab, and then modified + to be general enough for hyperslab selection operations. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +static herr_t +H5S_fill_in_new_space(H5S_t *space1, H5S_seloper_t op, + H5S_hyper_span_info_t *space2_span_lst, const hsize_t *space2_low_bound, + const hsize_t *space2_high_bound, hbool_t can_own_span2, hbool_t *span2_owned, + hbool_t *updated_spans, H5S_t **result) +{ + 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 */ + hsize_t *space1_low_bound = space1->select.low_bounds; + hsize_t *space1_high_bound = space1->select.high_bounds; + hbool_t overlapped = FALSE; + hbool_t is_result_new = FALSE; + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ - /* Check if there are any overlapped selections */ - if(a_and_b!=NULL) { - if(H5S_hyper_merge_spans(space,a_and_b,TRUE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + FUNC_ENTER_NOAPI_NOINIT - /* Update the number of elements in current selection */ - space->select.num_elem=H5S_hyper_spans_nelem(a_and_b); + HDassert(space1); + HDassert(space2_span_lst); + HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA); + /* The result is either a to-be-created space or an empty one */ + HDassert(*result == NULL || *result == space1); + HDassert(space1->select.sel_info.hslab->span_lst); + HDassert(span2_owned); + + /* Reset flags to return */ + *span2_owned = FALSE; + *updated_spans = FALSE; + + /* The result shares the same info from space1 */ + if(*result == NULL) { + if(NULL == ((*result) = H5S_copy(space1, TRUE, TRUE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace") + space1->select.sel_info.hslab->span_lst->count--; + (*result)->select.sel_info.hslab->span_lst = NULL; + is_result_new = TRUE; + } /* end if */ - /* Indicate that the a_and_b spans are owned */ - a_and_b=NULL; + /* Check bound box of both spaces to see if they overlap or border */ + for(u = 0; u < space1->extent.rank; u++) { + /* + * Three conditions for overlapping/bordering: + * 1. the lower bound of the new span is between the lower and + * higher bound of the existing one. In other words, the left + * part of new span will at least overlap or border with the + * existing one. + * 2. the higher bound of the new span is between the lower and + * higher bound of the exisiting one. In other words, the right + * part of new span will at least overlap or border with the + * existing one. + * 3. The new span includes the existing one where the lower bound + * is smaller than that of the existing one, and the higher bound + * is larger than that of the existing one. + */ + /* condition 1 */ + if((space1_low_bound[u] >= space2_low_bound[u] && + space1_low_bound[u] <= (space2_high_bound[u] + 1)) || + /* condition 2 */ + ((space1_high_bound[u] + 1) >= space2_low_bound[u] && + space1_high_bound[u] <= space2_high_bound[u]) || + /* condition 3 */ + (space1_low_bound[u] < space2_low_bound[u] && + space1_high_bound[u] > space2_high_bound[u])) { + overlapped = TRUE; + break; + } /* end if */ + } /* end for */ - /* Indicate that the spans were updated */ - updated_spans = TRUE; + /* If two spans are disjoint in terms of bound box, then work could be much simplified. */ + if(!overlapped) { + switch(op) { + case H5S_SELECT_OR: + case H5S_SELECT_XOR: + /* Add the new disjoint spans to the space */ + /* A copy of space1's spans to *result, and another copy of space2's spans */ + if(is_result_new) + (*result)->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(space1->select.sel_info.hslab->span_lst); + if(!can_own_span2) { + b_not_a = H5S_hyper_copy_span(space2_span_lst); + if(H5S_hyper_add_disjoint_spans(*result, b_not_a) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs") + + /* The new_spans is now owned by space, so its memory space should not be released */ + b_not_a = NULL; } /* end if */ + else { + if(H5S_hyper_add_disjoint_spans(*result, space2_span_lst) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs") + *span2_owned = TRUE; + } /* end else */ + + /* Indicate that the spans changed */ + *updated_spans = TRUE; break; - case H5S_SELECT_XOR: - /* Free the current selection */ - if(H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans") - space->select.sel_info.hslab->span_lst=NULL; + case H5S_SELECT_AND: + /* Convert *result to "none" selection */ + if(H5S_select_none(*result) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") + HGOTO_DONE(SUCCEED); - /* Reset the number of items in selection */ - space->select.num_elem=0; + case H5S_SELECT_NOTB: + /* Copy space1's spans to *result */ + if(is_result_new) + (*result)->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(space1->select.sel_info.hslab->span_lst); - /* Check if there are any non-overlapped selections */ - if(a_not_b!=NULL) { - if(H5S_hyper_merge_spans(space,a_not_b,FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + /* Indicate that the spans changed */ + *updated_spans = TRUE; + break; - /* Update the number of elements in current selection */ - space->select.num_elem=H5S_hyper_spans_nelem(a_not_b); + case H5S_SELECT_NOTA: + if(!is_result_new) { + HDassert(space1 == *result); - /* Indicate that the spans were updated */ - updated_spans = TRUE; + /* Free the current selection */ + if(H5S_hyper_free_span_info(space1->select.sel_info.hslab->span_lst) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans") } /* end if */ - if(b_not_a!=NULL) { - if(H5S_hyper_merge_spans(space,b_not_a,FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - /* Update the number of elements in current selection */ - space->select.num_elem+=H5S_hyper_spans_nelem(b_not_a); + /* Copy space2's spans to *result */ + if(!can_own_span2) + (*result)->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(space2_span_lst); + else { + (*result)->select.sel_info.hslab->span_lst = space2_span_lst; + *span2_owned = TRUE; + } /* end else */ - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ + /* Reset the number of items in selection */ + (*result)->select.num_elem = H5S_hyper_spans_nelem(space2_span_lst); + + /* Indicate that the spans changed */ + *updated_spans = TRUE; break; - case H5S_SELECT_NOTB: - /* Free the current selection */ - if(H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans") - space->select.sel_info.hslab->span_lst=NULL; + case H5S_SELECT_NOOP: + case H5S_SELECT_SET: + case H5S_SELECT_APPEND: + case H5S_SELECT_PREPEND: + case H5S_SELECT_INVALID: + default: + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") + } /* end switch */ - /* Reset the number of items in selection */ - space->select.num_elem=0; + /* update bound box of the selection result */ + if(H5S_hyper_update_bound_box(*result, op, space2_low_bound, space2_high_bound) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't update the bound box") + } /* end if */ + else { + const hsize_t *span_a_b_bounds[4]; /* Pointers to space1 & space2 bound boxes */ + hsize_t bounds_array[6 * H5S_MAX_RANK]; /* Array for bounding boxes */ + hsize_t *tmp_bounds_array; /* Temp. pointer to array for bounding boxes */ + hsize_t tmp = HSIZET_MAX; + unsigned selector = 0; /* Select which clipping spans to generate */ - /* Check if there are any non-overlapped selections */ - if(a_not_b!=NULL) { - if(H5S_hyper_merge_spans(space,a_not_b,TRUE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + /* Generate mask for clip operation depending on the op */ + switch(op) { + case H5S_SELECT_OR: + selector = H5S_HYPER_COMPUTE_B_NOT_A; /* a + b_not_a */ + break; - /* Update the number of elements in current selection */ - space->select.num_elem=H5S_hyper_spans_nelem(a_not_b); + case H5S_SELECT_XOR: /* a_not_b + b_not_a */ + selector = H5S_HYPER_COMPUTE_A_NOT_B | H5S_HYPER_COMPUTE_B_NOT_A; + break; - /* Indicate that the a_not_b are owned */ - a_not_b=NULL; + case H5S_SELECT_AND: /* a_and_b */ + selector = H5S_HYPER_COMPUTE_A_AND_B; + break; - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ + case H5S_SELECT_NOTB: /* a_not_b */ + selector = H5S_HYPER_COMPUTE_A_NOT_B; break; - case H5S_SELECT_NOTA: - /* Free the current selection */ - if(H5S_hyper_free_span_info(space->select.sel_info.hslab->span_lst)<0) - HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans") - space->select.sel_info.hslab->span_lst=NULL; + case H5S_SELECT_NOTA: /* b_not_a */ + selector = H5S_HYPER_COMPUTE_B_NOT_A; + break; - /* Reset the number of items in selection */ - space->select.num_elem=0; + case H5S_SELECT_NOOP: + case H5S_SELECT_SET: + case H5S_SELECT_APPEND: + case H5S_SELECT_PREPEND: + case H5S_SELECT_INVALID: + default: + HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") + } /* end switch */ - /* Check if there are any non-overlapped selections */ - if(b_not_a!=NULL) { - if(H5S_hyper_merge_spans(space,b_not_a,TRUE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + /* Initialize arrays for 3 pairs of low/high bounds to default values */ + tmp_bounds_array = bounds_array; + for(u = 0; u < 3; u++) { + /* set the bounds to be the default value */ + H5VM_array_fill(tmp_bounds_array, &tmp, sizeof(hsize_t), space1->extent.rank); + tmp_bounds_array += space1->extent.rank; + HDmemset(tmp_bounds_array, 0, sizeof(hsize_t) * space1->extent.rank); + tmp_bounds_array += space1->extent.rank; + } /* end for */ - /* Update the number of elements in current selection */ - space->select.num_elem=H5S_hyper_spans_nelem(b_not_a); + /* Initialize array of pointers to space1 & space2's bound arrays */ + span_a_b_bounds[0] = space1->select.low_bounds; + span_a_b_bounds[1] = space1->select.high_bounds; + span_a_b_bounds[2] = space2_low_bound; + span_a_b_bounds[3] = space2_high_bound; - /* Indicate that the b_not_a are owned */ - b_not_a=NULL; + /* Generate lists of spans which overlap and don't overlap */ + if(H5S_hyper_clip_spans(space1->select.sel_info.hslab->span_lst, + space2_span_lst, selector, 0, space1->extent.rank, + span_a_b_bounds, bounds_array, &a_not_b, &a_and_b, &b_not_a) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") + switch(op) { + case H5S_SELECT_OR: + if(is_result_new) + (*result)->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(space1->select.sel_info.hslab->span_lst); + break; - /* Indicate that the spans were updated */ - updated_spans = TRUE; + case H5S_SELECT_AND: + case H5S_SELECT_XOR: + case H5S_SELECT_NOTB: + case H5S_SELECT_NOTA: + if(!is_result_new) { + HDassert(space1 == *result); + + /* Free the current selection */ + if(H5S_hyper_free_span_info(space1->select.sel_info.hslab->span_lst) < 0) + HGOTO_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release hyperslab spans") + space1->select.sel_info.hslab->span_lst = NULL; } /* end if */ + + /* Reset the number of items in selection */ + (*result)->select.num_elem = 0; break; case H5S_SELECT_NOOP: @@ -6232,40 +6846,110 @@ H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op, HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") } /* end switch */ - /* 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 */ + /* Check if there are any non-overlapped selections */ + if(a_not_b) { + hsize_t *a_not_b_low_bounds = bounds_array; + hsize_t *a_not_b_high_bounds = bounds_array + space1->extent.rank; - /* Sanity check */ - HDassert(space->select.num_elem == 0); + /* Other than OR, the span_lst is set to NULL. And in OR, a_not_b is not needed */ + HDassert(NULL == (*result)->select.sel_info.hslab->span_lst); - /* Allocate a span info node */ - if((spans = H5FL_MALLOC(H5S_hyper_span_info_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab span") + if(H5S_hyper_merge_spans(*result, a_not_b) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - /* Set the reference count */ - spans->count=1; + /* Update the bound box: just use a_not_b's bound box as no span tree is in result */ + HDmemcpy((*result)->select.low_bounds, a_not_b_low_bounds, sizeof(hsize_t) * space1->extent.rank); + HDmemcpy((*result)->select.high_bounds, a_not_b_high_bounds, sizeof(hsize_t) * space1->extent.rank); - /* Reset the scratch pad space */ - spans->scratch=0; + /* Update the number of elements in current selection */ + (*result)->select.num_elem += H5S_hyper_spans_nelem(a_not_b); - /* Set to empty tree */ - spans->head=NULL; + /* Indicate that the spans were updated */ + *updated_spans = TRUE; - /* Set pointer to empty span tree */ - space->select.sel_info.hslab->span_lst=spans; + /* Indicate that the a_not_b spans are owned */ + a_not_b = NULL; } /* end if */ - else { - /* Check if we updated the spans */ - if(updated_spans) { - /* Attempt to rebuild "optimized" start/stride/count/block information. - * from resulting hyperslab span tree - */ - if(H5S_hyper_rebuild(space) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info") + + if(a_and_b) { + hsize_t *a_and_b_low_bounds = bounds_array + 2 * space1->extent.rank; + hsize_t *a_and_b_high_bounds = bounds_array + 3 * space1->extent.rank; + + /** + * 1. Other than OR, the span_lst is set to NULL. And in OR, + * a_and_b is not needed + * 2. a_not_b will never be computed together with a_and_b + * because merging these two equals to a. + */ + HDassert(NULL == (*result)->select.sel_info.hslab->span_lst); + + if(H5S_hyper_merge_spans(*result, a_and_b) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + + /* Update the bound box: just use a_not_b's bound box as no span tree is in result */ + HDmemcpy((*result)->select.low_bounds, a_and_b_low_bounds, sizeof(hsize_t) * space1->extent.rank); + HDmemcpy((*result)->select.high_bounds, a_and_b_high_bounds, sizeof(hsize_t) * space1->extent.rank); + + /* Update the number of elements in current selection */ + (*result)->select.num_elem += H5S_hyper_spans_nelem(a_and_b); + + /* Indicate that the spans were updated */ + *updated_spans = TRUE; + + /* Indicate that the a_and_b spans are owned */ + a_and_b = NULL; + } /* end if */ + + if(b_not_a) { + hsize_t *b_not_a_low_bounds = bounds_array + 4 * space1->extent.rank; + hsize_t *b_not_a_high_bounds = bounds_array + 5 * space1->extent.rank; + hbool_t has_span_tree = (NULL != (*result)->select.sel_info.hslab->span_lst); + + if(H5S_hyper_merge_spans(*result, b_not_a) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") + + /* Update the bound box */ + if(has_span_tree) { + /* Since two span trees are merged, the update on bound box is like an OR operation */ + for(u = 0; u < space1->extent.rank; u++) { + (*result)->select.low_bounds[u] = MIN((*result)->select.low_bounds[u], b_not_a_low_bounds[u]); + (*result)->select.high_bounds[u] = MAX((*result)->select.high_bounds[u], b_not_a_high_bounds[u]); + } /* end for */ } /* end if */ + else { + /* Just use b_not_a's bound box as no span tree is in result */ + HDmemcpy((*result)->select.low_bounds, b_not_a_low_bounds, sizeof(hsize_t) * space1->extent.rank); + HDmemcpy((*result)->select.high_bounds, b_not_a_high_bounds, sizeof(hsize_t) * space1->extent.rank); + } /* end else */ + + /* Update the number of elements in current selection */ + (*result)->select.num_elem += H5S_hyper_spans_nelem(b_not_a); + + /* Indicate that the spans were updated */ + *updated_spans = TRUE; + + /* Indicate that the b_not_a spans are owned */ + b_not_a = NULL; + } /* end if */ + } /* end else for the case the new span overlaps with the old (i.e. space) */ + + /* Check if the spans weren't updated, and reset selection if so */ + if(!*updated_spans) { + /** If updated_spans remains FALSE as in this branch, it + * means the result has been cleared in cases + * XOR/AND/NOTB/NOTA, and the result is a copy of the + * dataspace in the case OR. + * + * If two dataspaces have generated any of the three clipped + * span trees (i.e. a_not_b, a_and_b, and b_not_a), the + * updated_spans must be TRUE. + */ + if(H5S_SELECT_OR != op) { + /* Convert *result to "none" selection */ + if(H5S_select_none(*result) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") } /* end else */ - } /* end else */ + } /* end if */ done: /* Free resources */ @@ -6278,6 +6962,108 @@ done: if(b_not_a) if(H5S_hyper_free_span_info(b_not_a) < 0) HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans") + + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_fill_in_new_space() */ + + +/*------------------------------------------------------------------------- + * Function: H5S_generate_hyperlab + * + * Purpose: Generate hyperslab information from H5S_select_hyperslab() + * + * Return: Non-negative on success/Negative on failure + * + * Programmer: Quincey Koziol + * Tuesday, September 12, 2000 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_generate_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[], + const hsize_t stride[], const hsize_t count[], const hsize_t block[]) +{ + H5S_hyper_span_info_t *new_spans=NULL; /* Span tree for new hyperslab */ + hsize_t new_spans_low_bounds[H5S_MAX_RANK]; /* The lower bound box for the new hyperslab */ + hsize_t new_spans_high_bounds[H5S_MAX_RANK]; /* The upper bound box for the new hyperslab */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ + + FUNC_ENTER_NOAPI_NOINIT + + /* Check args */ + HDassert(space); + HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID); + HDassert(start); + HDassert(stride); + HDassert(count); + HDassert(block); + + /* Generate span tree for new hyperslab information */ + if(NULL == (new_spans = H5S_hyper_make_spans(space->extent.rank, start, stride, count, block))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information") + + /* Generate the bound box for the new hyperslab */ + for(u = 0; u < space->extent.rank; u++) { + new_spans_low_bounds[u] = start[u]; + new_spans_high_bounds[u] = new_spans_low_bounds[u] + stride[u] * (count[u] - 1) + (block[u] - 1); + } /* end for */ + + /* Generate list of blocks to add/remove based on selection operation */ + if(op == H5S_SELECT_SET) { + H5S_hyper_span_info_t *existing_spans = space->select.sel_info.hslab->span_lst; + + /* Add new spans to current selection */ + if(NULL != existing_spans) + if(H5S_hyper_free_span_info(existing_spans) < 0) + HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release existing hyperslab spans") + + space->select.sel_info.hslab->span_lst = new_spans; + + /* Set the number of elements in current selection */ + space->select.num_elem = H5S_hyper_spans_nelem(new_spans); + + /* Update the bound box of this hyperslab */ + HDmemcpy(space->select.low_bounds, new_spans_low_bounds, sizeof(hsize_t) * space->extent.rank); + HDmemcpy(space->select.high_bounds, new_spans_high_bounds, sizeof(hsize_t) * space->extent.rank); + + /* Indicate that the new_spans are owned */ + new_spans = NULL; + } /* end if */ + else { + hbool_t new_spans_owned; + hbool_t updated_spans; + + /* Generate new spans for space */ + if(H5S_fill_in_new_space(space, op, new_spans, new_spans_low_bounds, new_spans_high_bounds, TRUE, &new_spans_owned, &updated_spans, &space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't generate the specified hyperslab") + + /* Check if the spans were updated by H5S_fill_in_new_space */ + if(updated_spans) { + H5S_hyper_dim_t new_hyper_diminfo[H5S_MAX_RANK]; + + /* Sanity check */ + HDassert(space->select.sel_info.hslab->span_lst->head); + + /* Build diminfo struct */ + for(u = 0; u <space->extent.rank; u++) { + new_hyper_diminfo[u].start = start[u]; + new_hyper_diminfo[u].stride = stride[u]; + new_hyper_diminfo[u].count = count[u]; + new_hyper_diminfo[u].block = block[u]; + } /* end for */ + + /* Update space's dim info */ + if(H5S_hyper_update_diminfo(space, op, new_hyper_diminfo) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info") + } /* end if */ + + /* Indicate that the new_spans are owned, there's no need to free */ + if(new_spans_owned) + new_spans = NULL; + } /* end else */ + +done: if(new_spans) if(H5S_hyper_free_span_info(new_spans) < 0) HDONE_ERROR(H5E_INTERNAL, H5E_CANTFREE, FAIL, "failed to release temporary hyperslab spans") @@ -6299,20 +7085,17 @@ done: *------------------------------------------------------------------------- */ herr_t -H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, - const hsize_t start[], - const hsize_t *stride, - const hsize_t count[], - const hsize_t *block) +H5S_select_hyperslab(H5S_t *space, H5S_seloper_t op, const hsize_t start[], + const hsize_t *stride, const hsize_t count[], const hsize_t *block) { hsize_t int_stride[H5O_LAYOUT_NDIMS]; /* Internal storage for stride information */ hsize_t int_count[H5O_LAYOUT_NDIMS]; /* Internal storage for count information */ hsize_t int_block[H5O_LAYOUT_NDIMS]; /* Internal storage for block information */ - const hsize_t *opt_stride; /* Optimized stride information */ - const hsize_t *opt_count; /* Optimized count information */ - const hsize_t *opt_block; /* Optimized block information */ - unsigned u; /* Counters */ - herr_t ret_value=SUCCEED; /* Return value */ + const hsize_t *opt_stride; /* Optimized stride information */ + const hsize_t *opt_count; /* Optimized count information */ + const hsize_t *opt_block; /* Optimized block information */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI(FAIL) @@ -6345,8 +7128,8 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, case H5S_SELECT_AND: /* Binary "and" operation for hyperslabs */ case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */ /* Convert to "none" selection */ - if(H5S_select_none(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") + if(H5S_select_none(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") HGOTO_DONE(SUCCEED); case H5S_SELECT_OR: /* Binary "or" operation for hyperslabs */ @@ -6465,8 +7248,8 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */ /* Convert to "none" selection */ - if(H5S_select_none(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") + if(H5S_select_none(space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") HGOTO_DONE(SUCCEED); case H5S_SELECT_NOOP: @@ -6515,14 +7298,21 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, space->select.sel_info.hslab->opt_diminfo[u].count = opt_count[u]; space->select.sel_info.hslab->opt_diminfo[u].block = opt_block[u]; + /* update bound box of the hyperslab selection */ + space->select.low_bounds[u] = start[u]; + space->select.high_bounds[u] = space->select.low_bounds[u] + stride[u] * (count[u] - 1) + (block[u] - 1); + space->select.num_elem *= (opt_count[u] * opt_block[u]); } /* end for */ /* Indicate that the dimension information is valid */ - space->select.sel_info.hslab->diminfo_valid = TRUE; + space->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_YES; /* Indicate that there's no slab information */ space->select.sel_info.hslab->span_lst = NULL; + + /* Set selection type */ + space->select.type = H5S_sel_hyper; } /* end if */ else if(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA) { /* Sanity check */ @@ -6533,8 +7323,9 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, if(H5S_hyper_generate_spans(space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree") - /* Indicate that the regular dimensions are no longer valid */ - space->select.sel_info.hslab->diminfo_valid = FALSE; + /* Set selection type */ + /* (Could be overridden by resetting selection to 'none', below) */ + space->select.type = H5S_sel_hyper; /* Add in the new hyperslab information */ if(H5S_generate_hyperslab(space, op, start, opt_stride, opt_count, opt_block) < 0) @@ -6543,12 +7334,9 @@ H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, else HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") - /* Set selection type */ - space->select.type = H5S_sel_hyper; - done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_hyperslab() */ +} /* end H5S_select_hyperslab() */ /*-------------------------------------------------------------------------- @@ -6579,10 +7367,9 @@ done: --------------------------------------------------------------------------*/ herr_t H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], - const hsize_t stride[], const hsize_t count[], const hsize_t block[]) + const hsize_t stride[], const hsize_t count[], const hsize_t block[]) { H5S_t *space; /* Dataspace to modify selection of */ - unsigned u; /* Local index variable */ herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) @@ -6590,7 +7377,7 @@ H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], /* Check args */ if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") if(H5S_SCALAR == H5S_GET_EXTENT_TYPE(space)) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_SCALAR space") if(H5S_NULL == H5S_GET_EXTENT_TYPE(space)) @@ -6599,617 +7386,283 @@ H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified") if(!(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID)) HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") - if(stride!=NULL) { + if(stride != NULL) { + unsigned u; /* Local index variable */ + /* Check for 0-sized strides */ - for(u=0; u<space->extent.rank; u++) { - if(stride[u]==0) + for(u = 0; u < space->extent.rank; u++) { + if(stride[u] == 0) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid stride==0 value") } /* end for */ } /* end if */ - if (H5S_select_hyperslab(space, op, start, stride, count, block)<0) + if(H5S_select_hyperslab(space, op, start, stride, count, block) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection") done: FUNC_LEAVE_API(ret_value) } /* end H5Sselect_hyperslab() */ -#else /* NEW_HYPERSLAB_API */ /* Works */ - -/*------------------------------------------------------------------------- - * Function: H5S_operate_hyperslab - * - * Purpose: Combines two hyperslabs with an operation, putting the - * result into a third hyperslab selection - * - * Return: non-negative on success/NULL on failure - * - * Programmer: Quincey Koziol - * Tuesday, October 30, 2001 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -static herr_t -H5S_operate_hyperslab (H5S_t *result, H5S_hyper_span_info_t *spans1, H5S_seloper_t op, H5S_hyper_span_info_t *spans2, - hbool_t can_own_span2, hbool_t *span2_owned) -{ - H5S_hyper_span_info_t *a_not_b=NULL; /* Span tree for hyperslab spans in old span tree and not in new span tree */ - H5S_hyper_span_info_t *a_and_b=NULL; /* Span tree for hyperslab spans in both old and new span trees */ - H5S_hyper_span_info_t *b_not_a=NULL; /* Span tree for hyperslab spans in new span tree and not in old span tree */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI_NOINIT - - /* Check args */ - HDassert(result); - HDassert(spans2); - HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID); - - /* Just copy the selection from spans2 if we are setting the selection */ - /* ('space1' to 'result' aliasing happens at the next layer up) */ - if(op==H5S_SELECT_SET) { - if(H5S_hyper_merge_spans(result,spans2,can_own_span2)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem=H5S_hyper_spans_nelem(spans2); - - /* Indicate that we took ownership of span2, if allowed */ - if(can_own_span2) - *span2_owned=TRUE; - } /* end if */ - else { - hbool_t updated_spans = FALSE; /* Whether the spans in the selection were modified */ - - HDassert(spans1); - - /* Generate lists of spans which overlap and don't overlap */ - if(H5S_hyper_clip_spans(spans1,spans2,&a_not_b,&a_and_b,&b_not_a)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") - - /* Switch on the operation */ - switch(op) { - case H5S_SELECT_OR: - /* Copy spans from spans1 to current selection */ - if(spans1!=NULL) { - if(H5S_hyper_merge_spans(result,spans1,FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem=H5S_hyper_spans_nelem(spans1); - } /* end if */ - - /* Add any new spans from spans2 to current selection */ - if(b_not_a!=NULL) { - if(H5S_hyper_merge_spans(result,b_not_a,FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem+=H5S_hyper_spans_nelem(b_not_a); - - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ - break; - - case H5S_SELECT_AND: - /* Check if there are any overlapped selections */ - if(a_and_b!=NULL) { - if(H5S_hyper_merge_spans(result,a_and_b,TRUE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem=H5S_hyper_spans_nelem(a_and_b); - - /* Indicate that the result owns the a_and_b spans */ - a_and_b=NULL; - - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ - break; - - case H5S_SELECT_XOR: - /* Check if there are any non-overlapped selections */ - if(a_not_b!=NULL) { - if(H5S_hyper_merge_spans(result,a_not_b,FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem=H5S_hyper_spans_nelem(a_not_b); - - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ - if(b_not_a!=NULL) { - if(H5S_hyper_merge_spans(result,b_not_a,FALSE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem+=H5S_hyper_spans_nelem(b_not_a); - - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ - break; - - case H5S_SELECT_NOTB: - /* Check if there are any non-overlapped selections */ - if(a_not_b!=NULL) { - if(H5S_hyper_merge_spans(result,a_not_b,TRUE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem=H5S_hyper_spans_nelem(a_not_b); - - /* Indicate that the result owns the a_not_b spans */ - a_not_b=NULL; - - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ - break; - - case H5S_SELECT_NOTA: - /* Check if there are any non-overlapped selections */ - if(b_not_a!=NULL) { - if(H5S_hyper_merge_spans(result,b_not_a,TRUE)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't insert hyperslabs") - - /* Update the number of elements in current selection */ - result->select.num_elem=H5S_hyper_spans_nelem(b_not_a); - - /* Indicate that the result owns the b_not_a spans */ - b_not_a=NULL; - - /* Indicate that the spans were updated */ - updated_spans = TRUE; - } /* end if */ - break; - - 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); - if(a_and_b) - 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(result->select.sel_info.hslab->span_lst==NULL) { - H5S_hyper_span_info_t *spans; /* Empty hyperslab span tree */ - - /* Sanity check */ - HDassert(result->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 */ - result->select.sel_info.hslab->span_lst=spans; - } /* end if */ - else { - /* Check if we updated the spans */ - if(updated_spans) { - /* Attempt to rebuild "optimized" start/stride/count/block information. - * from resulting hyperslab span tree - */ - if(H5S_hyper_rebuild(result) < 0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't rebuild hyperslab info") - } /* end if */ - } /* end else */ - } /* end else */ - -done: - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_operate_hyperslab() */ -/*------------------------------------------------------------------------- - * Function: H5S_generate_hyperlab - * - * Purpose: Generate hyperslab information from H5S_select_hyperslab() - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol (split from HS_select_hyperslab()). - * Tuesday, September 12, 2000 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ +/*-------------------------------------------------------------------------- + NAME + H5S_fill_in_hyperslab + PURPOSE + Specify a hyperslab to combine with the current hyperslab selection, and + store the result in the new hyperslab selection. + USAGE + herr_t H5S_fill_in_hyperslab(new_space, old_space, op, start, stride, count, block) + H5S_t old_space; IN: The old space the selection is performed on + H5S_seloper_t op; IN: Operation to perform on current selection + const hsize_t *start; IN: Offset of start of hyperslab + const hsize_t *stride; IN: Hyperslab stride + const hsize_t *count; IN: Number of blocks included in hyperslab + const hsize_t *block; IN: Size of block in hyperslab + H5S_t *new_space; OUT: The new dataspace to store the selection result + RETURNS + Non-negative on success/Negative on failure + DESCRIPTION + Combines a hyperslab selection with the current selection for a dataspace. + If STRIDE or BLOCK is NULL, they are assumed to be set to all '1'. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + In some cases, the whole span tree in the old_space could be avoided from copying + into the new_space. In order to deal with such cases, H5S_select_hyperslab could + not be directly called. Otherwise, this function equals two steps: + 1. copy the whole span tree from old_space into new_space + 2. call H5S_select_hyperslab with the new_space. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ static herr_t -H5S_generate_hyperslab (H5S_t *space, H5S_seloper_t op, - const hsize_t start[], - const hsize_t stride[], - const hsize_t count[], - const hsize_t block[]) +H5S_fill_in_hyperslab(H5S_t *old_space, H5S_seloper_t op, const hsize_t start[], + const hsize_t *stride, const hsize_t count[], const hsize_t *block, + H5S_t **new_space) { - H5S_hyper_span_info_t *new_spans=NULL; /* Span tree for new hyperslab */ - H5S_hyper_span_info_t *tmp_spans=NULL; /* Temporary copy of selection */ - hbool_t span2_owned=FALSE; /* Flag to indicate that span2 was used in H5S_operate_hyperslab() */ - herr_t ret_value=SUCCEED; /* Return value */ + unsigned u; /* Local index variable */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check args */ - HDassert(space); - HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID); - HDassert(start); - HDassert(stride); - HDassert(count); - HDassert(block); - - /* Generate span tree for new hyperslab information */ - if((new_spans=H5S_hyper_make_spans(space->extent.rank,start,stride,count,block))==NULL) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information") - - /* Copy the original dataspace */ - if(space->select.sel_info.hslab->span_lst!=NULL) { - /* Take ownership of the dataspace's hyperslab spans */ - /* (These are freed later) */ - tmp_spans=space->select.sel_info.hslab->span_lst; - space->select.sel_info.hslab->span_lst=NULL; - - /* Reset the other dataspace selection information */ - if(H5S_SELECT_RELEASE(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") - - /* Allocate space for the hyperslab selection information */ - if((space->select.sel_info.hslab=H5FL_MALLOC(H5S_hyper_sel_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info") - } /* end if */ - - /* Combine tmp_space (really space) & new_space, with the result in space */ - if(H5S_operate_hyperslab(space,tmp_spans,op,new_spans,TRUE,&span2_owned)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") - -done: - /* Free temporary data structures */ - if(tmp_spans!=NULL) - 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 && span2_owned==FALSE) - 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() */ - - -/*------------------------------------------------------------------------- - * Function: H5S_select_hyperslab - * - * Purpose: Internal version of H5Sselect_hyperslab(). - * - * Return: Non-negative on success/Negative on failure - * - * Programmer: Quincey Koziol - * Wednesday, January 10, 2001 - * - * Modifications: - * - *------------------------------------------------------------------------- - */ -herr_t -H5S_select_hyperslab (H5S_t *space, H5S_seloper_t op, - const hsize_t start[], - const hsize_t *stride, - const hsize_t count[], - const hsize_t *block) -{ - hsize_t int_stride[H5O_LAYOUT_NDIMS]; /* Internal storage for stride information */ - hsize_t int_count[H5O_LAYOUT_NDIMS]; /* Internal storage for count information */ - hsize_t int_block[H5O_LAYOUT_NDIMS]; /* Internal storage for block information */ - const hsize_t *opt_stride; /* Optimized stride information */ - const hsize_t *opt_count; /* Optimized count information */ - const hsize_t *opt_block; /* Optimized block information */ - unsigned u; /* Counters */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_NOAPI(FAIL) - - /* Check args */ - HDassert(space); + HDassert(old_space); HDassert(start); HDassert(count); - HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID); + HDassert(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA); + HDassert(new_space); + HDassert(*new_space == NULL); /* Point to the correct stride values */ - if(stride==NULL) + if(stride == NULL) stride = _ones; /* Point to the correct block values */ - if(block==NULL) + if(block == NULL) block = _ones; - /* - * Check new selection. - */ - for(u=0; u<space->extent.rank; u++) { + /* Check new selection. */ + for(u = 0; u < old_space->extent.rank; u++) { /* Check for overlapping hyperslab blocks in new selection. */ - if(count[u]>1 && stride[u]<block[u]) + if(count[u] > 1 && stride[u] < block[u]) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab blocks overlap") /* Detect zero-sized hyperslabs in new selection */ if(count[u] == 0 || block[u] == 0) { switch(op) { - case H5S_SELECT_SET: /* Select "set" operation */ case H5S_SELECT_AND: /* Binary "and" operation for hyperslabs */ case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */ /* Convert to "none" selection */ - if(H5S_select_none(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") + /* Copy the first dataspace without sharing the list of spans */ + if(NULL == ((*new_space) = H5S_copy(old_space, TRUE, TRUE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace") + if(H5S_select_none((*new_space)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") HGOTO_DONE(SUCCEED); case H5S_SELECT_OR: /* Binary "or" operation for hyperslabs */ case H5S_SELECT_XOR: /* Binary "xor" operation for hyperslabs */ case H5S_SELECT_NOTB: /* Binary "A not B" operation for hyperslabs */ + /* Copy the first dataspace with sharing the list of spans */ + if(NULL == ((*new_space) = H5S_copy(old_space, FALSE, TRUE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace") HGOTO_DONE(SUCCEED); /* Selection stays same */ + case H5S_SELECT_NOOP: + case H5S_SELECT_SET: + case H5S_SELECT_APPEND: + case H5S_SELECT_PREPEND: + case H5S_SELECT_INVALID: default: HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") } /* end switch */ } /* end if */ } /* end for */ - /* Optimize hyperslab parameters to merge contiguous blocks, etc. */ - if(stride == _ones && block == _ones) { - /* Point to existing arrays */ - opt_stride = _ones; - opt_count = _ones; - opt_block = count; - } /* end if */ - else { - /* Point to local arrays */ - opt_stride = int_stride; - opt_count = int_count; - opt_block = int_block; - for(u=0; u<space->extent.rank; u++) { - /* contiguous hyperslabs have the block size equal to the stride */ - if(stride[u]==block[u]) { - int_count[u]=1; - int_stride[u]=1; - if(block[u]==1) - int_block[u]=count[u]; - else - int_block[u]=block[u]*count[u]; - } /* end if */ - else { - if(count[u]==1) - int_stride[u]=1; - else { - HDassert(stride[u] > block[u]); - int_stride[u]=stride[u]; - } /* end else */ - int_count[u]=count[u]; - int_block[u]=block[u]; - } /* end else */ - } /* end for */ - } /* end else */ + if(H5S_GET_SELECT_TYPE(old_space) == H5S_SEL_HYPERSLABS) { + hsize_t new_low_bound[H5S_MAX_RANK]; + hsize_t new_high_bound[H5S_MAX_RANK]; + hbool_t overlapped = FALSE; - /* Fixup operation for non-hyperslab selections */ - switch(H5S_GET_SELECT_TYPE(space)) { - case H5S_SEL_NONE: /* No elements selected in dataspace */ - switch(op) { - case H5S_SELECT_SET: /* Select "set" operation */ - /* Change "none" selection to hyperslab selection */ - break; + /* Generate bounding box for hyperslab parameters */ + for(u = 0; u < old_space->extent.rank; u++) { + new_low_bound[u] = start[u]; + new_high_bound[u] = new_low_bound[u] + stride[u] * (count[u]-1) + (block[u]-1); + } /* end for */ - case H5S_SELECT_OR: /* Binary "or" operation for hyperslabs */ - case H5S_SELECT_XOR: /* Binary "xor" operation for hyperslabs */ - case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */ - op=H5S_SELECT_SET; /* Maps to "set" operation when applied to "none" selection */ - break; + /* Check bounding box to see if two are disjoint */ + for(u = 0; u < old_space->extent.rank; u++) { + /* Note: offset of this old_space is neglected */ + hsize_t old_low_bound = old_space->select.low_bounds[u]; + hsize_t old_high_bound = old_space->select.high_bounds[u]; + + /* The following condition tests are copied from H5S_fill_in_new_space */ + if((new_low_bound[u] >= old_low_bound && new_low_bound[u] <= old_high_bound) || + (new_high_bound[u] >= old_low_bound && new_high_bound[u] <= old_high_bound) || + (new_low_bound[u] <= old_low_bound && new_high_bound[u] >= old_high_bound)) { + overlapped = TRUE; + break; + } /* end if */ + } /* end for */ - case H5S_SELECT_AND: /* Binary "and" operation for hyperslabs */ - case H5S_SELECT_NOTB: /* Binary "A not B" operation for hyperslabs */ - HGOTO_DONE(SUCCEED); /* Selection stays "none" */ + if(!overlapped) { + H5S_hyper_span_info_t *new_spans = NULL; + H5S_hyper_dim_t new_hyper_diminfo[H5S_MAX_RANK]; - default: - HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") - } /* end switch */ - break; + if(NULL == ((*new_space) = H5S_copy(old_space, TRUE, TRUE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace") + if(NULL != (*new_space)->select.sel_info.hslab->span_lst) { + old_space->select.sel_info.hslab->span_lst->count--; + (*new_space)->select.sel_info.hslab->span_lst = NULL; + } /* end if */ - case H5S_SEL_ALL: /* All elements selected in dataspace */ + /* Generate hyperslab info for new space */ switch(op) { - case H5S_SELECT_SET: /* Select "set" operation */ - /* Change "all" selection to hyperslab selection */ + case H5S_SELECT_OR: + case H5S_SELECT_XOR: + /* Add the new space to the space */ + if(NULL == (new_spans = H5S_hyper_make_spans(old_space->extent.rank, start, stride, count, block))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information") + if(NULL != old_space->select.sel_info.hslab->span_lst) + (*new_space)->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(old_space->select.sel_info.hslab->span_lst); + if(H5S_hyper_add_disjoint_spans(*new_space, new_spans) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't append hyperslabs") break; - case H5S_SELECT_OR: /* Binary "or" operation for hyperslabs */ - HGOTO_DONE(SUCCEED); /* Selection stays "all" */ + case H5S_SELECT_AND: + if(H5S_select_none((*new_space)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") + HGOTO_DONE(SUCCEED); - case H5S_SELECT_AND: /* Binary "and" operation for hyperslabs */ - op=H5S_SELECT_SET; /* Maps to "set" operation when applied to "none" selection */ + case H5S_SELECT_NOTB: + if(old_space->select.sel_info.hslab->span_lst != NULL) + (*new_space)->select.sel_info.hslab->span_lst = H5S_hyper_copy_span(old_space->select.sel_info.hslab->span_lst); + else { + if(H5S_select_none((*new_space)) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't convert selection") + HGOTO_DONE(SUCCEED); + } /* end else */ break; - case H5S_SELECT_XOR: /* Binary "xor" operation for hyperslabs */ - case H5S_SELECT_NOTB: /* Binary "A not B" operation for hyperslabs */ - /* Convert current "all" selection to "real" hyperslab selection */ - /* Then allow operation to proceed */ - { - hsize_t tmp_start[H5O_LAYOUT_NDIMS]; /* Temporary start information */ - hsize_t tmp_stride[H5O_LAYOUT_NDIMS]; /* Temporary stride information */ - hsize_t tmp_count[H5O_LAYOUT_NDIMS]; /* Temporary count information */ - hsize_t tmp_block[H5O_LAYOUT_NDIMS]; /* Temporary block information */ - - /* Fill in temporary information for the dimensions */ - for(u=0; u<space->extent.rank; u++) { - tmp_start[u]=0; - tmp_stride[u]=1; - tmp_count[u]=1; - tmp_block[u]=space->extent.size[u]; - } /* end for */ - - /* Convert to hyperslab selection */ - if(H5S_select_hyperslab(space,H5S_SELECT_SET,tmp_start,tmp_stride,tmp_count,tmp_block)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") - } /* end case */ + case H5S_SELECT_NOTA: + if(NULL == (new_spans = H5S_hyper_make_spans(old_space->extent.rank, start, stride, count, block))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't create hyperslab information") + (*new_space)->select.sel_info.hslab->span_lst = new_spans; + (*new_space)->select.num_elem = H5S_hyper_spans_nelem(new_spans); break; - case H5S_SELECT_NOTA: /* Binary "B not A" operation for hyperslabs */ - /* Convert to "none" selection */ - if(H5S_select_none(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't convert selection") - HGOTO_DONE(SUCCEED); - + case H5S_SELECT_NOOP: + case H5S_SELECT_SET: + case H5S_SELECT_APPEND: + case H5S_SELECT_PREPEND: + case H5S_SELECT_INVALID: default: HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") } /* end switch */ - break; - - case H5S_SEL_HYPERSLABS: - /* Hyperslab operation on hyperslab selection, OK */ - break; - - case H5S_SEL_POINTS: /* Can't combine hyperslab operations and point selections currently */ - if(op==H5S_SELECT_SET) /* Allow only "set" operation to proceed */ - break; - /* Else fall through to error */ - - default: - HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") - } /* end switch */ - - - if(op==H5S_SELECT_SET) { - /* If we are setting a new selection, remove current selection first */ - if(H5S_SELECT_RELEASE(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release hyperslab") - - /* Allocate space for the hyperslab selection information */ - if((space->select.sel_info.hslab=H5FL_MALLOC(H5S_hyper_sel_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab info") - - /* Save the diminfo */ - space->select.num_elem=1; - for(u=0; u<space->extent.rank; u++) { - space->select.sel_info.hslab->app_diminfo[u].start = start[u]; - space->select.sel_info.hslab->app_diminfo[u].stride = stride[u]; - space->select.sel_info.hslab->app_diminfo[u].count = count[u]; - space->select.sel_info.hslab->app_diminfo[u].block = block[u]; - - space->select.sel_info.hslab->opt_diminfo[u].start = start[u]; - space->select.sel_info.hslab->opt_diminfo[u].stride = opt_stride[u]; - space->select.sel_info.hslab->opt_diminfo[u].count = opt_count[u]; - space->select.sel_info.hslab->opt_diminfo[u].block = opt_block[u]; - - space->select.num_elem*=(opt_count[u]*opt_block[u]); - } /* end for */ - /* Indicate that the dimension information is valid */ - space->select.sel_info.hslab->diminfo_valid=TRUE; + /* Update bound box */ + if(H5S_hyper_update_bound_box(*new_space, op, new_low_bound, new_high_bound)<0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't update the bound box") - /* Indicate that there's no slab information */ - space->select.sel_info.hslab->span_lst=NULL; - } /* end if */ - else if(op>=H5S_SELECT_OR && op<=H5S_SELECT_NOTA) { - /* Sanity check */ - HDassert(H5S_GET_SELECT_TYPE(space) == H5S_SEL_HYPERSLABS); + /* Build diminfo struct */ + for(u = 0; u < (*new_space)->extent.rank; u++) { + new_hyper_diminfo[u].start = start[u]; + new_hyper_diminfo[u].stride = stride[u]; + new_hyper_diminfo[u].count = count[u]; + new_hyper_diminfo[u].block = block[u]; + } /* end for */ - /* Check if there's no hyperslab span information currently */ - if(space->select.sel_info.hslab->span_lst==NULL) - if(H5S_hyper_generate_spans(space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree") + /* Update space's dim info */ + if(H5S_hyper_update_diminfo(*new_space, op, new_hyper_diminfo) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info") - /* Add in the new hyperslab information */ - if(H5S_generate_hyperslab (space, op, start, opt_stride, opt_count, opt_block)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINSERT, FAIL, "can't generate hyperslabs") + HGOTO_DONE(SUCCEED); + } /* end if(!overlapped) */ + } /* end if the selection of old space is H5S_SEL_HYPERSLABS*/ - /* Indicate that the regular dimensions are no longer valid */ - space->select.sel_info.hslab->diminfo_valid=FALSE; - } /* end if */ - else - HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") + /* Copy the first dataspace with sharing the list of spans */ + if(NULL == ((*new_space) = H5S_copy(old_space, FALSE, TRUE))) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to copy dataspace") - /* Set selection type */ - space->select.type=H5S_sel_hyper; + /* Note: a little overhead in calling the function as some conditions are checked again */ + if(H5S_select_hyperslab(*new_space, op, start, stride, count, block) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection") done: FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_hyperslab() */ +} /* end H5S_fill_in_hyperslab() */ -/*-------------------------------------------------------------------------- - NAME - H5Sselect_hyperslab - PURPOSE - Specify a hyperslab to combine with the current hyperslab selection - USAGE - herr_t H5Sselect_hyperslab(dsid, op, start, stride, count, block) - hid_t dsid; IN: Dataspace ID of selection to modify - H5S_seloper_t op; IN: Operation to perform on current selection - const hsize_t *start; IN: Offset of start of hyperslab - const hsize_t *stride; IN: Hyperslab stride - const hsize_t *count; IN: Number of blocks included in hyperslab - const hsize_t *block; IN: Size of block in hyperslab - RETURNS - Non-negative on success/Negative on failure - DESCRIPTION - Combines a hyperslab selection with the current selection for a dataspace. - If the current selection is not a hyperslab, it is freed and the hyperslab - parameters passed in are combined with the H5S_SEL_ALL hyperslab (ie. a - selection composing the entire current extent). If STRIDE or BLOCK is - NULL, they are assumed to be set to all '1'. - GLOBAL VARIABLES - COMMENTS, BUGS, ASSUMPTIONS - EXAMPLES - REVISION LOG ---------------------------------------------------------------------------*/ -herr_t -H5Sselect_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], - const hsize_t stride[], const hsize_t count[], const hsize_t block[]) +/*------------------------------------------------------------------------- + * Function: H5S_fill_in_select + * + * Purpose: Combines two hyperslabs with an operation, putting the + * result into a third hyperslab selection + * + * Return: non-negative on success/NULL on failure + * + * Programmer: Chao Mei + * Tuesday, July 5, 2011 + * + *------------------------------------------------------------------------- + */ +static herr_t +H5S_fill_in_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2, H5S_t **result) { - H5S_t *space = NULL; /* Dataspace to modify selection of */ - herr_t ret_value=SUCCEED; /* Return value */ - - FUNC_ENTER_API(FAIL) - H5TRACE6("e", "iSs*h*h*h*h", space_id, op, start, stride, count, block); + hbool_t span2_owned; + hbool_t updated_spans; + herr_t ret_value = SUCCEED; /* Return value */ - /* Check args */ - if (NULL == (space=H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - if (H5S_SCALAR==H5S_GET_EXTENT_TYPE(space)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_SCALAR space") - if (H5S_NULL==H5S_GET_EXTENT_TYPE(space)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "hyperslab doesn't support H5S_NULL space") - if(start==NULL || count==NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified") - if(!(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID)) - HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") - if(stride!=NULL) { - unsigned u; /* Local index variable */ + FUNC_ENTER_NOAPI_NOINIT - /* Check for 0-sized strides */ - for(u=0; u<space->extent.rank; u++) { - if(stride[u]==0) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid stride==0 value") - } /* end for */ + /* Sanity check */ + HDassert(space1); + HDassert(space2); + HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA); + HDassert(space1->extent.rank == space2->extent.rank); + /* The result is either a to-be-created space or an empty one */ + HDassert(NULL == *result || *result == space1); + HDassert(space1->select.sel_info.hslab->span_lst); + HDassert(space2->select.sel_info.hslab->span_lst); + + /* Note: the offset of space2 is not considered here for bounding box */ + if(H5S_fill_in_new_space(space1, op, space2->select.sel_info.hslab->span_lst, space2->select.low_bounds, space2->select.high_bounds, FALSE, &span2_owned, &updated_spans, result) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSELECT, FAIL, "can't create the specified selection") + + /* Update diminfo if space2's diminfo was valid, otherwise just mark it as + * invalid if the spans were updated */ + HDassert(result); + if(updated_spans) { + if(space2->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { + if(H5S_hyper_update_diminfo(*result, op, space2->select.sel_info.hslab->opt_diminfo) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOUNT, FAIL, "can't update hyperslab info") + } /* end if */ + else + (*result)->select.sel_info.hslab->diminfo_valid = H5S_DIMINFO_VALID_NO; } /* end if */ - if (H5S_select_hyperslab(space, op, start, stride, count, block)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection") - done: - FUNC_LEAVE_API(ret_value) -} /* end H5Sselect_hyperslab() */ + FUNC_LEAVE_NOAPI(ret_value) +} /* end H5S_fill_in_select() */ /*-------------------------------------------------------------------------- @@ -7243,38 +7696,33 @@ done: --------------------------------------------------------------------------*/ hid_t H5Scombine_hyperslab(hid_t space_id, H5S_seloper_t op, const hsize_t start[], - const hsize_t stride[], const hsize_t count[], const hsize_t block[]) + const hsize_t stride[], const hsize_t count[], const hsize_t block[]) { - H5S_t *space = NULL; /* Dataspace to modify selection of */ - H5S_t *new_space = NULL; /* New dataspace created */ - hid_t ret_value; + H5S_t *space; /* Dataspace to modify selection of */ + H5S_t *new_space = NULL; /* New dataspace created */ + hid_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE6("i", "iSs*h*h*h*h", space_id, op, start, stride, count, block); /* Check args */ - if (NULL == (space=H5I_object_verify(space_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - if(start==NULL || count==NULL) + if(NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(start == NULL || count == NULL) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "hyperslab not specified") - - if(!(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID)) + if(!(op >= H5S_SELECT_SET && op <= H5S_SELECT_NOTA)) HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") - /* Copy the first dataspace */ - if (NULL == (new_space = H5S_copy (space, TRUE, TRUE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to copy data space") - - /* Go modify the selection in the new dataspace */ - if (H5S_select_hyperslab(new_space, op, start, stride, count, block)<0) + /* Generate new space, with combination of selections */ + if(H5S_fill_in_hyperslab(space, op, start, stride, count, block, &new_space) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection") /* Atomize */ - if ((ret_value=H5I_register (H5I_DATASPACE, new_space, TRUE))<0) + if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom") done: - if (ret_value<0 && new_space) + if(ret_value < 0 && new_space) H5S_close(new_space); FUNC_LEAVE_API(ret_value) @@ -7291,57 +7739,62 @@ done: * Programmer: Quincey Koziol * Tuesday, October 30, 2001 * - * Modifications: + * Chao Mei + * Wednesday, June 29, 2011 * *------------------------------------------------------------------------- */ static H5S_t * -H5S_combine_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2) +H5S_combine_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2) { - H5S_t *new_space=NULL; /* New dataspace generated */ - hbool_t span2_owned=FALSE; /* Flag to indicate that span2 was used in H5S_operate_hyperslab() */ - H5S_t *ret_value; /* return value */ + H5S_t *new_space = NULL; /* New dataspace generated */ + H5S_t *ret_value = NULL; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check args */ HDassert(space1); HDassert(space2); - HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID); + HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA); - /* Check that the space selections both have span trees */ - if(space1->select.sel_info.hslab->span_lst==NULL) - if(H5S_hyper_generate_spans(space1)<0) + /* Check that if space1 selections has span trees */ + if(NULL == space1->select.sel_info.hslab->span_lst) + if(H5S_hyper_generate_spans(space1) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree") - if(space2->select.sel_info.hslab->span_lst==NULL) - if(H5S_hyper_generate_spans(space2)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, NULL, "dataspace does not have span tree") - - /* Copy the first dataspace */ - if (NULL == (new_space = H5S_copy (space1, TRUE, TRUE))) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to copy data space") - - /* Free the current selection for the new dataspace */ - if(H5S_SELECT_RELEASE(new_space)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, NULL, "can't release selection") - /* Allocate space for the hyperslab selection information */ - if((new_space->select.sel_info.hslab=H5FL_CALLOC(H5S_hyper_sel_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "can't allocate hyperslab info") + if(NULL == space2->select.sel_info.hslab->span_lst) { + hsize_t tmp_start[H5S_MAX_RANK]; + hsize_t tmp_stride[H5S_MAX_RANK]; + hsize_t tmp_count[H5S_MAX_RANK]; + hsize_t tmp_block[H5S_MAX_RANK]; + unsigned u; + + for(u = 0; u < space2->extent.rank; u++) { + tmp_start[u] = space2->select.sel_info.hslab->opt_diminfo[u].start; + tmp_stride[u] = space2->select.sel_info.hslab->opt_diminfo[u].stride; + tmp_count[u] = space2->select.sel_info.hslab->opt_diminfo[u].count; + tmp_block[u] = space2->select.sel_info.hslab->opt_diminfo[u].block; + } /* end for */ - /* Combine space1 & space2, with the result in new_space */ - if(H5S_operate_hyperslab(new_space,space1->select.sel_info.hslab->span_lst,op,space2->select.sel_info.hslab->span_lst,FALSE,&span2_owned)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information") + /* call H5S_select_hyperslab directly */ + if(H5S_fill_in_hyperslab(space1, op, tmp_start, tmp_stride, tmp_count, tmp_block, &new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to set hyperslab selection") + } /* end if */ + else{ + /* Combine new_space (a copy of space 1) & space2, with the result in new_space */ + if(H5S_fill_in_select(space1, op, space2, &new_space) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, NULL, "can't clip hyperslab information") + } /* end else */ /* Set return value */ - ret_value=new_space; + ret_value = new_space; done: - if(ret_value==NULL && new_space!=NULL) + if(ret_value == NULL && new_space) H5S_close(new_space); FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_combine_select() */ +} /* end H5S_combine_select() */ /*-------------------------------------------------------------------------- @@ -7372,37 +7825,47 @@ H5Scombine_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id) H5S_t *space1; /* First Dataspace */ H5S_t *space2; /* Second Dataspace */ H5S_t *new_space = NULL; /* New Dataspace */ - hid_t ret_value; + hid_t ret_value; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("i", "iSsi", space1_id, op, space2_id); /* Check args */ - if (NULL == (space1=H5I_object_verify(space1_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - if (NULL == (space2=H5I_object_verify(space2_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - if(!(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID)) + if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA)) HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") /* Check that both dataspaces have the same rank */ - if(space1->extent.rank!=space2->extent.rank) + if(space1->extent.rank != space2->extent.rank) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank") + /* Note: currently, the offset of each dataspace is ignored */ +#if 0 + /* Check that both dataspaces have the same offset */ + /* Same note as in H5Sselect_select */ + for(u=0; u<space1->extent.rank; u++) { + if(space1->select.offset[u] != space2->select.offset[u]) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same offset") + } /* end for */ +#endif + /* Check that both dataspaces have hyperslab selections */ - if(H5S_GET_SELECT_TYPE(space1)!=H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2)!=H5S_SEL_HYPERSLABS) + if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces don't have hyperslab selections") /* Go combine the dataspaces */ - if ((new_space=H5S_combine_select(space1, op, space2))==NULL) + if(NULL == (new_space = H5S_combine_select(space1, op, space2))) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to create hyperslab selection") /* Atomize */ - if ((ret_value=H5I_register (H5I_DATASPACE, new_space, TRUE))<0) + if((ret_value = H5I_register(H5I_DATASPACE, new_space, TRUE)) < 0) HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom") done: - if (ret_value<0 && new_space) + if(ret_value < 0 && new_space) H5S_close(new_space); FUNC_LEAVE_API(ret_value) @@ -7419,55 +7882,55 @@ done: * Programmer: Quincey Koziol * Tuesday, October 30, 2001 * - * Modifications: + * Chao Mei + * Wednesday, June 29, 2011 * *------------------------------------------------------------------------- */ static herr_t -H5S_select_select (H5S_t *space1, H5S_seloper_t op, H5S_t *space2) +H5S_select_select(H5S_t *space1, H5S_seloper_t op, H5S_t *space2) { - H5S_hyper_span_info_t *tmp_spans=NULL; /* Temporary copy of selection */ - hbool_t span2_owned=FALSE; /* Flag to indicate that span2 was used in H5S_operate_hyperslab() */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_NOAPI_NOINIT /* Check args */ HDassert(space1); HDassert(space2); - HDassert(op > H5S_SELECT_NOOP && op < H5S_SELECT_INVALID); + HDassert(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA); /* Check that the space selections both have span trees */ - if(space1->select.sel_info.hslab->span_lst==NULL) - if(H5S_hyper_generate_spans(space1)<0) + if(NULL == space1->select.sel_info.hslab->span_lst) + if(H5S_hyper_generate_spans(space1) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree") - if(space2->select.sel_info.hslab->span_lst==NULL) - if(H5S_hyper_generate_spans(space2)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_UNINITIALIZED, FAIL, "dataspace does not have span tree") - - /* Take ownership of the dataspace's hyperslab spans */ - /* (These are freed later) */ - tmp_spans=space1->select.sel_info.hslab->span_lst; - space1->select.sel_info.hslab->span_lst=NULL; - /* Reset the other dataspace selection information */ - if(H5S_SELECT_RELEASE(space1)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't release selection") - - /* Allocate space for the hyperslab selection information */ - if((space1->select.sel_info.hslab=H5FL_CALLOC(H5S_hyper_sel_t))==NULL) - HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "can't allocate hyperslab info") + if(NULL == space2->select.sel_info.hslab->span_lst) { + hsize_t tmp_start[H5S_MAX_RANK]; + hsize_t tmp_stride[H5S_MAX_RANK]; + hsize_t tmp_count[H5S_MAX_RANK]; + hsize_t tmp_block[H5S_MAX_RANK]; + unsigned u; + + for(u = 0; u < space2->extent.rank; u++) { + tmp_start[u] = space2->select.sel_info.hslab->opt_diminfo[u].start; + tmp_stride[u] = space2->select.sel_info.hslab->opt_diminfo[u].stride; + tmp_count[u] = space2->select.sel_info.hslab->opt_diminfo[u].count; + tmp_block[u] = space2->select.sel_info.hslab->opt_diminfo[u].block; + } /* end for */ - /* Combine tmp_spans (from space1) & spans from space2, with the result in space1 */ - if(H5S_operate_hyperslab(space1,tmp_spans,op,space2->select.sel_info.hslab->span_lst,FALSE,&span2_owned)<0) - HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't clip hyperslab information") + /* Call H5S_select_hyperslab directly */ + if(H5S_select_hyperslab(space1, op, tmp_start, tmp_stride, tmp_count, tmp_block) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set hyperslab selection") + } /* end if */ + else { + /* Combine spans from space1 & spans from space2, with the result in space1 */ + if(H5S_fill_in_select(space1, op, space2, &space1) < 0) + HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCLIP, FAIL, "can't perform operation on two selections") + } /* end else*/ done: - if(tmp_spans!=NULL) - H5S_hyper_free_span_info(tmp_spans); - FUNC_LEAVE_NOAPI(ret_value) -} /* end H5S_select_select() */ +} /* end H5S_select_select() */ /*-------------------------------------------------------------------------- @@ -7475,7 +7938,7 @@ done: H5Sselect_select PURPOSE Refine a hyperslab selection with an operation using a second hyperslab - to modify it. + to modify it USAGE herr_t H5Sselect_select(space1, op, space2) hid_t space1; IN/OUT: First Dataspace ID @@ -7497,35 +7960,59 @@ H5Sselect_select(hid_t space1_id, H5S_seloper_t op, hid_t space2_id) { H5S_t *space1; /* First Dataspace */ H5S_t *space2; /* Second Dataspace */ - herr_t ret_value=SUCCEED; /* Return value */ + herr_t ret_value = SUCCEED; /* Return value */ FUNC_ENTER_API(FAIL) H5TRACE3("e", "iSsi", space1_id, op, space2_id); /* Check args */ - if (NULL == (space1=H5I_object_verify(space1_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - if (NULL == (space2=H5I_object_verify(space2_id, H5I_DATASPACE))) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a data space") - if(!(op>H5S_SELECT_NOOP && op<H5S_SELECT_INVALID)) + if(NULL == (space1 = (H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(NULL == (space2 = (H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace") + if(!(op >= H5S_SELECT_OR && op <= H5S_SELECT_NOTA)) HGOTO_ERROR(H5E_ARGS, H5E_UNSUPPORTED, FAIL, "invalid selection operation") /* Check that both dataspaces have the same rank */ - if(space1->extent.rank!=space2->extent.rank) + if(space1->extent.rank != space2->extent.rank) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same rank") + /* Check that both dataspaces have the same offset */ + /** Note that this is a tricky part of this function. It's + * possible that two dataspaces have different "offset". If the + * space2 has smaller offset value than that of space1 in a + * dimension, then the span elements of this dimension in + * space2 could have negative "low" and "high" values relative + * to the offset in space1. In other words, if the bounds of + * span elements in space2 are adjusted relative to the offset + * in space1, then every span element's bound is computed as + * "origin_bound+offset2-offset1". Therefore, if offset2 (the + * offset of space2) is smaller, then + * "origin_bound+offset2-offset1" could be negative which is + * not allowed by the bound type declaration as hsize_t! + * As a result, if the op is an OR selection, then the final + * result may contain span elements that have negative bound! + * So right now, the difference in the offset is totally + * ignored!! + */ +#if 0 + for(u=0; u<space1->extent.rank; u++) { + if(space1->select.offset[u] != space2->select.offset[u]) + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces not same offset") + } /* end for */ +#endif + /* Check that both dataspaces have hyperslab selections */ - if(H5S_GET_SELECT_TYPE(space1)!=H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2)!=H5S_SEL_HYPERSLABS) + if(H5S_GET_SELECT_TYPE(space1) != H5S_SEL_HYPERSLABS || H5S_GET_SELECT_TYPE(space2) != H5S_SEL_HYPERSLABS) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "dataspaces don't have hyperslab selections") /* Go refine the first selection */ - if (H5S_select_select(space1, op, space2)<0) + if(H5S_select_select(space1, op, space2) < 0) HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to modify hyperslab selection") done: FUNC_LEAVE_API(ret_value) } /* end H5Sselect_select() */ -#endif /* NEW_HYPERSLAB_API */ /* Works */ /*-------------------------------------------------------------------------- @@ -7559,7 +8046,7 @@ done: REVISION LOG --------------------------------------------------------------------------*/ static herr_t -H5S_hyper_get_seq_list_gen(const H5S_t *space,H5S_sel_iter_t *iter, +H5S_hyper_get_seq_list_gen(const H5S_t *space, H5S_sel_iter_t *iter, size_t maxseq, size_t maxelem, size_t *nseq, size_t *nelem, hsize_t *off, size_t *len) { @@ -8731,8 +9218,14 @@ H5S_hyper_get_seq_list(const H5S_t *space, unsigned UNUSED flags, H5S_sel_iter_t HDassert(off); HDassert(len); + /* Rebuild diminfo if it is invalid and has not been confirmed to be + * impossible */ + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_NO) + /* Casting away const OK -NAF */ + (void)H5S_hyper_rebuild((H5S_t *)space); + /* Check for the special case of just one H5Sselect_hyperslab call made */ - if(space->select.sel_info.hslab->diminfo_valid) { + if(space->select.sel_info.hslab->diminfo_valid == H5S_DIMINFO_VALID_YES) { const H5S_hyper_dim_t *tdiminfo; /* Temporary pointer to diminfo information */ const hssize_t *sel_off; /* Selection offset in dataspace */ hsize_t *mem_size; /* Size of the source buffer */ |